[asterisk-commits] branch oej/res_config_ldap r12474 - in
/team/oej/res_config_ldap: ./ configs/...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Wed Mar 8 14:10:26 MST 2006
Author: oej
Date: Wed Mar 8 15:10:21 2006
New Revision: 12474
URL: http://svn.digium.com/view/asterisk?rev=12474&view=rev
Log:
Adding patch from issue #5768 with some formatting changes.
Added:
team/oej/res_config_ldap/configs/res_ldap.conf.sample (with props)
team/oej/res_config_ldap/doc/rt-ldap.txt (with props)
team/oej/res_config_ldap/res/res_config_ldap.c (with props)
Modified:
team/oej/res_config_ldap/ (props changed)
team/oej/res_config_ldap/res/Makefile
Propchange: team/oej/res_config_ldap/
------------------------------------------------------------------------------
svnmerge-integrated = /trunk:1-12471
Added: team/oej/res_config_ldap/configs/res_ldap.conf.sample
URL: http://svn.digium.com/view/asterisk/team/oej/res_config_ldap/configs/res_ldap.conf.sample?rev=12474&view=auto
==============================================================================
--- team/oej/res_config_ldap/configs/res_ldap.conf.sample (added)
+++ team/oej/res_config_ldap/configs/res_ldap.conf.sample Wed Mar 8 15:10:21 2006
@@ -1,0 +1,134 @@
+; Sample Asterisk config file for res_config_ldap
+; in extconfig.conf you can use it like this:
+; sipusers => ldap,"dc=myDomain,dc=myDomainExt",sip
+; sippeers => ldap,"dc=myDomain,dc=myDomainExt",sip
+; extensions => ldap,"dc=myDomain,dc=myDomainExt",extensions
+; sip.conf => ldap,"dc=myDomain,dc=myDomainExt",config
+
+
+[_general]
+dbhost=192.168.1.1,ldap.mydomain.com ; LDAP host(s)
+dbbasedn=MyRootDN ; Base DN
+dbpass=MyPassword ; Bind password
+dbuser=MyDN ; Bind DN
+
+; Configuration Table
+[config]
+; Attributes mapping (asterisk variable name => ldap attribute name)
+attribute = filename => oxyPBXConfigFilename
+attribute = category => oxyPBXConfigCategory
+attribute = variable_name => oxyPBXConfigVariableName
+attribute = variable_value => oxyPBXConfigVariableValue
+attribute = cat_metric => oxyPBXConfigCategoryMetric
+attribute = commented => oxyPBXConfigCommented
+
+; addtional filter
+additionalFilter=(objectClass=oxyPBXConfig)
+
+; Extensions Table
+[extensions]
+attribute = context => oxyPBXExtensionContext
+attribute = exten => oxyPBXExtensionExten
+attribute = priority => oxyPBXExtensionPriority
+attribute = app => oxyPBXExtensionApplication
+attribute = appdata => oxyPBXExtensionApplicationData
+additionalFilter=(objectClass=oxyPBXExtension)
+
+// Sip Users Table
+[sip]
+attribute = name => uid
+attribute = amaflags => oxyPBXAccountAMAFlags
+attribute = callgroup => oxyPBXAccountCallGroup
+attribute = callerid => oxyPBXAccountCallerID
+attribute = canreinvite => oxyPBXAccountCanReinvite
+attribute = context => oxyPBXAccountContext
+attribute = dtmfmode => oxyPBXAccountDTMFMode
+attribute = fromuser => oxyPBXAccountFromUser
+attribute = fromdomain => oxyPBXAccountFromDomain
+attribute = fullcontact => oxyPBXAccountFullContact
+attribute = fullcontact => gecos
+attribute = host => oxyPBXAccountHost
+attribute = insecure => oxyPBXAccountInsecure
+attribute = mailbox => oxyPBXAccountMailbox
+attribute = md5secret => realmedPassword
+attribute = nat => oxyPBXAccountNAT
+attribute = deny => oxyPBXAccountDeny
+attribute = permit => oxyPBXAccountPermit
+attribute = pickupgroup => oxyPBXAccountPickupGroup
+attribute = port => oxyPBXAccountPort
+attribute = qualify => oxyPBXAccountQualify
+attribute = restrictcid => oxyPBXAccountRestrictCID
+attribute = rtptimeout => oxyPBXAccountRTPTimeout
+attribute = rtpholdtimeout => oxyPBXAccountRTPHoldTimeout
+attribute = type => oxyPBXAccountType
+attribute = disallow => oxyPBXAccountDisallowedCodec
+attribute = allow => oxyPBXAccountAllowedCodec
+attribute = MusicOnHold => oxyPBXAccountMusicOnHold
+attribute = regseconds => oxyPBXAccountExpirationTimestamp
+attribute = regcontext => oxyPBXAccountRegistrationContext
+attribute = regexten => oxyPBXAccountRegistrationExten
+attribute = CanCallForward => oxyPBXAccountCanCallForward
+additionalFilter=(objectClass=oxyPBXAccountSIP)
+
+; IAX Users Table
+[iax]
+attribute = amaflags => oxyPBXAccountAMAFlags
+attribute = callerid => oxyPBXAccountCallerID
+attribute = context => oxyPBXAccountContext
+attribute = fullcontact => oxyPBXAccountFullContact
+attribute = fullcontact => gecos
+attribute = host => oxyPBXAccountHost
+attribute = mailbox => oxyPBXAccountMailbox
+attribute = md5secret => realmedPassword
+attribute = deny => oxyPBXAccountDeny
+attribute = permit => oxyPBXAccountPermit
+attribute = port => oxyPBXAccountPort
+attribute = qualify => oxyPBXAccountQualify
+attribute = type => oxyPBXAccountType
+attribute = disallow => oxyPBXAccountDisallowedCodec
+attribute = allow => oxyPBXAccountAllowedCodec
+attribute = regseconds => oxyPBXAccountExpirationTimestamp
+attribute = regcontext => oxyPBXAccountRegistrationContext
+attribute = regexten => oxyPBXAccountRegistrationExten
+attribute = notransfer => oxyPBXAccountNoTransfer
+additionalFilter=(objectClass=oxyPBXAccountIAX)
+
+; A Test Family
+[testfamily]
+attribute = MyUSERID => uid
+additionalFilter=(objectClass=*)
+
+[accounts]
+attribute = amaflags => oxyPBXAccountAMAFlags
+attribute = callgroup => oxyPBXAccountCallGroup
+attribute = callerid => oxyPBXAccountCallerID
+attribute = canreinvite => oxyPBXAccountCanReinvite
+attribute = context => oxyPBXAccountContext
+attribute = dtmfmode => oxyPBXAccountDTMFMode
+attribute = fromuser => oxyPBXAccountFromUser
+attribute = fromdomain => oxyPBXAccountFromDomain
+attribute = fullcontact => oxyPBXAccountFullContact
+attribute = fullcontact => gecos
+attribute = host => oxyPBXAccountHost
+attribute = insecure => oxyPBXAccountInsecure
+attribute = mailbox => oxyPBXAccountMailbox
+attribute = md5secret => realmedPassword
+attribute = nat => oxyPBXAccountNAT
+attribute = deny => oxyPBXAccountDeny
+attribute = permit => oxyPBXAccountPermit
+attribute = pickupgroup => oxyPBXAccountPickupGroup
+attribute = port => oxyPBXAccountPort
+attribute = qualify => oxyPBXAccountQualify
+attribute = restrictcid => oxyPBXAccountRestrictCID
+attribute = rtptimeout => oxyPBXAccountRTPTimeout
+attribute = rtpholdtimeout => oxyPBXAccountRTPHoldTimeout
+attribute = type => oxyPBXAccountType
+attribute = disallow => oxyPBXAccountDisallowedCodec
+attribute = allow => oxyPBXAccountAllowedCodec
+attribute = MusicOnHold => oxyPBXAccountMusicOnHold
+attribute = regseconds => oxyPBXAccountExpirationTimestamp
+attribute = regcontext => oxyPBXAccountRegistrationContext
+attribute = regexten => oxyPBXAccountRegistrationExten
+attribute = CanCallForward => oxyPBXAccountCanCallForward
+additionalFilter=(objectClass=oxyPBXAccount)
+
Propchange: team/oej/res_config_ldap/configs/res_ldap.conf.sample
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/oej/res_config_ldap/configs/res_ldap.conf.sample
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/oej/res_config_ldap/configs/res_ldap.conf.sample
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/oej/res_config_ldap/doc/rt-ldap.txt
URL: http://svn.digium.com/view/asterisk/team/oej/res_config_ldap/doc/rt-ldap.txt?rev=12474&view=auto
==============================================================================
--- team/oej/res_config_ldap/doc/rt-ldap.txt (added)
+++ team/oej/res_config_ldap/doc/rt-ldap.txt Wed Mar 8 15:10:21 2006
@@ -1,0 +1,65 @@
+Asterisk Realtim LDAP Driver
+---------------------------
+
+With this driver Asterisk can retrieve information from a LDAP drectory, including
+sip/iax users, extensions and configuration.
+
+See configs/res_ldap.conf.sample for a configuration file sample
+
+
+Here is a LDAP dif sample:
+
+# Base SIP Phones Entry
+dn: uid=phone-base,dc=myDomain,dc=myDomainExt
+objectClass: top
+objectClass: oxyPBXAccount
+objectClass: oxyPBXAccountSIP
+uid: phone-base
+oxyPBXAccountAccountingCode: baseacccode
+oxyPBXAccountHost: dynamic
+preferredLanguage: FR
+oxyPBXAccountAMAFlags: billing
+oxyPBXAccountContext: ldaptest
+
+
+# A Phone. realmedPassword md5 hash should be the result of
+# echo -n "UID:SIPRealm:Password" | md5sum
+dn: uid=phone-test,dc=myDomain,dc=myDomainExt
+objectClass: top
+objectClass: oxyPBXAccount
+objectClass: oxyPBXAccountSIP
+uid: phone-test
+oxyPBXAccountAccountingCode: acc-phone-base
+oxyPBXAccountFullContact: Noone <1234>
+oxyPBXAccountCallerID: 1234
+oxyPBXAccountBaseDN: uid=phone-base,dc=myDomain,dc=myDomainExt
+realmedPassword: {MD5}f67965da780bf9c70d6e337f938cee6f
+
+
+# extensions,
+dn: ou=extensions,dc=myDomain,dc=myDomainExt
+ou: extensions
+objectClass: top
+objectClass: organizationalUnit
+
+# Extension 100 Priority 1 in context ldaptest
+dn: cn=100-1,ou=extensions,dc=myDomain,dc=myDomainExt
+oxyPBXExtensionApplication: NoOp
+oxyPBXExtensionApplicationData: TEST LDAP
+objectClass: top
+objectClass: oxyPBXExtension
+oxyPBXExtensionExten: 100
+oxyPBXExtensionContext: ldaptest
+cn: 100-1
+oxyPBXExtensionPriority: 1
+
+# Extension 100 Priority 1 in context ldaptest
+dn: cn=100-2,ou=extensions,dc=myDomain,dc=myDomainExt
+objectClass: top
+objectClass: oxyPBXExtension
+oxyPBXExtensionExten: 100
+oxyPBXExtensionContext: ldaptest
+cn: 100-2
+oxyPBXExtensionPriority: 2
+oxyPBXExtensionApplication: hangup
+
Propchange: team/oej/res_config_ldap/doc/rt-ldap.txt
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/oej/res_config_ldap/doc/rt-ldap.txt
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/oej/res_config_ldap/doc/rt-ldap.txt
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/oej/res_config_ldap/res/Makefile
URL: http://svn.digium.com/view/asterisk/team/oej/res_config_ldap/res/Makefile?rev=12474&r1=12473&r2=12474&view=diff
==============================================================================
--- team/oej/res_config_ldap/res/Makefile (original)
+++ team/oej/res_config_ldap/res/Makefile Wed Mar 8 15:10:21 2006
@@ -41,6 +41,11 @@
ifeq ($(findstring BSD,$(OSARCH)),BSD)
MODS:=$(filter-out res_snmp.so,$(MODS))
endif
+endif
+
+
+ifeq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/ldap.h $(CROSS_COMPILE_TARGET)/usr/local/include/ldap.h),)
+ MODS:=$(filter-out res_config_ldap.so,$(MODS))
endif
ifeq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/net-snmp/net-snmp-config.h),)
@@ -128,6 +133,10 @@
res_snmp.so: res_snmp.o snmp/agent.o
$(CC) $(SOLINK) ${SNMP_LDFLAGS} -o $@ ${CYGSOLINK} res_snmp.o snmp/agent.o ${CYGSOLIB} ${SNMP_LDLIBS}
+res_config_ldap.so: res_config_ldap.o
+ $(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} -lldap
+
+
ifneq ($(wildcard .depend),)
include .depend
endif
Added: team/oej/res_config_ldap/res/res_config_ldap.c
URL: http://svn.digium.com/view/asterisk/team/oej/res_config_ldap/res/res_config_ldap.c?rev=12474&view=auto
==============================================================================
--- team/oej/res_config_ldap/res/res_config_ldap.c (added)
+++ team/oej/res_config_ldap/res/res_config_ldap.c Wed Mar 8 15:10:21 2006
@@ -1,0 +1,1308 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Copyright (C) 2005, Oxymium sarl
+ *
+ * Manuel Guesdon <mguesdon at oxymium.net> - LDAP RealTime Driver Author/Adaptor
+ *
+ * res_config_ldap.c <LDAP plugin for RealTime configuration engine>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ *
+ */
+
+/*! \file
+ *
+ * \brief ldap plugin for portable configuration engine (ARA)
+ *
+ * \author Mark Spencer <markster at digium.com>
+ * \author Manuel Guesdon
+ *
+ * \arg http://www.openldap.org
+ * \par Version notes
+ * - v0.5 - (11-16-2005) - Initial version based
+ * - v0.7 - (03-08-2006) - Fixes, confg file changes
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <ldap.h>
+#include <stdio.h>
+
+#include "asterisk.h"
+
+STERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include <asterisk/channel.h>
+#include <asterisk/logger.h>
+#include <asterisk/config.h>
+#include <asterisk/module.h>
+#include <asterisk/lock.h>
+#include <asterisk/options.h>
+#include <asterisk/cli.h>
+#include <asterisk/utils.h>
+#include <asterisk/strings.h>
+#include <asterisk/pbx.h>
+
+static char *res_config_ldap_desc = "LDAP RealTime Configuration Driver";
+AST_MUTEX_DEFINE_STATIC(ldap_lock);
+#define RES_CONFIG_LDAP_CONF "res_ldap.conf"
+static LDAP *ldapConn = NULL;
+static char dbhost[512] = "";
+static char dbuser[512] = "";
+static char dbpass[50] = "";
+static char dbbasedn[512] = "";
+static int dbport = 389;
+static time_t connect_time = 0;
+
+static int parse_config(void);
+static int ldap_reconnect(void);
+static int realtime_ldap_status(int fd, int argc, char **argv);
+
+
+STANDARD_LOCAL_USER;
+
+LOCAL_USER_DECL;
+
+static char cli_realtime_ldap_status_usage[] =
+ "Usage: realtime ldap status\n"
+ " Shows connection information for the LDAP RealTime driver\n";
+
+static struct ast_cli_entry cli_realtime_ldap_status = {
+ {"realtime", "ldap", "status", NULL}, realtime_ldap_status,
+ "Shows connection information for the LDAP RealTime driver",
+ cli_realtime_ldap_status_usage, NULL
+};
+
+/*! \brief Log variable */
+static void ast_variable_log(const char *log_prefix, struct ast_variable *var)
+{
+ ast_log(LOG_DEBUG, "LOG Variable: %s\n", log_prefix);
+ while (var) {
+ ast_log(LOG_DEBUG, "%s => %s\n", var->name, var->value);
+ var = var->next;
+ };
+ ast_log(LOG_DEBUG, "END LOG Variable: %s\n", log_prefix);
+}
+
+/*! \brief Log config */
+static void ast_config_log(const char *log_prefix, struct ast_config *config)
+{
+ ast_log(LOG_DEBUG, "LOG Config: %s\n", log_prefix);
+ char *category_name = NULL;
+ while ((category_name = ast_category_browse(config, category_name))) {
+ ast_log(LOG_DEBUG, "========= category: %s ==========\n",
+ category_name);
+ struct ast_variable *var = ast_variable_browse(config, category_name);
+ if (var) {
+ while (var) {
+ ast_log(LOG_DEBUG, "%s=%s\n", var->name, var->value);
+ var = var->next;
+ }
+ }
+ }
+ ast_log(LOG_DEBUG, "END LOG Config: %s\n", log_prefix);
+};
+
+/*! \brief Table configuration */
+struct ldap_table_config {
+ char *table_name; /* table name */
+ char *additional_filter; /* additional filter */
+ struct ast_variable *attributes; /* attribute names conversion */
+ struct ldap_table_config *next; /* next table */
+};
+
+/*! \brief Should be locked before using it */
+static struct ldap_table_config *table_configs = NULL;
+static struct ldap_table_config *base_table_config = NULL;
+
+/*! \brief Create a new table_config */
+static struct ldap_table_config *table_config_new(const char *table_name)
+{
+ struct ldap_table_config *p = malloc(sizeof(struct ldap_table_config));
+ memset(p, 0, sizeof(struct ldap_table_config));
+ if (table_name)
+ p->table_name = strdup(table_name);
+ return p;
+};
+
+/*! \brief Find a table_config - Should be locked before using it */
+static struct ldap_table_config *table_config_for_table_name(const char *table_name)
+{
+ struct ldap_table_config *c = table_configs;
+ while (c) {
+ if (strcmp(c->table_name, table_name) == 0)
+ return c;
+ else
+ c = c->next;
+ };
+ return NULL;
+};
+
+/*! \brief add attributes to table config - Should be locked before using it */
+static void ldap_table_config_add_attributes(struct ldap_table_config* table_config,const char* attributes_string)
+{
+ if (attributes_string && *attributes_string) {
+ char* string=strdup(attributes_string);
+ char* string_end=string+strlen(string);
+ char* start=string;
+ while(start<string_end) {
+ char* conv_sep=NULL;
+ char* attr_sep=strchr(start,',');
+ if (!attr_sep)
+ attr_sep=string_end;
+ else
+ *attr_sep='\0';
+ conv_sep=strchr(start,'=');
+ if (conv_sep>=attr_sep)
+ conv_sep=NULL;
+ if (!conv_sep) {
+ ast_log(LOG_WARNING, "LDAP RealTime: Missing '=' in attributes conversion list: %s\n",attributes_string);
+ } else {
+ struct ast_variable* var;
+ *conv_sep='\0';
+ var=ast_variable_new(start,conv_sep+1);
+ if (table_config->attributes)
+ var->next=table_config->attributes;
+ table_config->attributes=var;
+ }
+ start=attr_sep+1;
+ };
+ free(string);
+ };
+};
+*/
+
+/*! \brief add attribute to table config - Should be locked before using it */
+static void ldap_table_config_add_attribute(struct ldap_table_config *table_config,
+ const char *attribute_string)
+{
+ if (attribute_string && *attribute_string) {
+ char *string = strdup(attribute_string);
+ char *start = string;
+ ast_log(LOG_DEBUG, "LDAP RealTime: Add attribute: start: %s\n",
+ start);
+ char *p = strstr(start, "=>");
+ if (!p) {
+ ast_log(LOG_WARNING,
+ "LDAP RealTime: Missing '=>' in attribute: %s in %s\n",
+ attribute_string, table_config->table_name);
+ } else {
+ char *value = p + 2; //skip =>
+ /* trim ! */
+ while (isspace(*start))
+ start++;
+ p--;
+ while (p >= start && isspace(*p)) {
+ *p = '\0';
+ p--;
+ }
+ while (isspace(*value))
+ value++;
+ p = value + strlen(value) - 1;
+ while (p >= value && isspace(*p)) {
+ *p = '\0';
+ p--;
+ }
+ if (*start == '\0') {
+ ast_log(LOG_WARNING,
+ "LDAP RealTime: Empty variable name in attribute: %s in %s\n",
+ attribute_string, table_config->table_name);
+ } else if (*value == '\0') {
+ ast_log(LOG_WARNING,
+ "LDAP RealTime: Empty ldap attribute name in attribute: %s in %s\n",
+ attribute_string, table_config->table_name);
+ } else {
+ struct ast_variable *var = ast_variable_new(start, value);
+ //ast_log(LOG_DEBUG, "LDAP RealTime: Add attribute: VAR %s => %s\n",var->name,var->value);
+ if (table_config->attributes)
+ var->next = table_config->attributes;
+ table_config->attributes = var;
+ ast_log(LOG_DEBUG,
+ "LDAP RealTime (%d): Added attribute in %s: %s -> %s\n",
+ __LINE__, table_config->table_name, start, value);
+ }
+ };
+ free(string);
+ };
+};
+
+/*! \brief Free table_config */
+static void table_configs_free(void)
+{
+ struct ldap_table_config *c = table_configs;
+ while (c) {
+ struct ldap_table_config *next = c->next;
+ if (c->table_name)
+ free(c->table_name);
+ if (c->additional_filter)
+ free(c->additional_filter);
+ if (c->attributes) {
+ ast_variables_destroy(c->attributes);
+ };
+ free(c);
+ c = next;
+ };
+ table_configs = NULL;
+ base_table_config = NULL;
+}
+
+/*! \brief Convert variable name to ldap attribute name - Should be locked before using it */
+static const char *convert_attribute_name_to_ldap(struct ldap_table_config *table_config,
+ const char *attribute_name)
+{
+ int i = 0;
+ for (i = 0; i < 2; i++) {
+ if (table_config) {
+ struct ast_variable *attribute = table_config->attributes;
+ while (attribute) {
+ if (strcasecmp(attribute_name, attribute->name) == 0)
+ return attribute->value;
+ else
+ attribute = attribute->next;
+ };
+ };
+ if (table_config == base_table_config)
+ break;
+ else
+ table_config = base_table_config;
+ };
+ return attribute_name;
+};
+
+/*! \brief Convert ldap attribute name to variable name - Should be locked before using it */
+static const char *convert_attribute_name_from_ldap(struct ldap_table_config *table_config,
+ const char *attribute_name)
+{
+ int i = 0;
+ for (i = 0; i < 2; i++) {
+ if (table_config) {
+ struct ast_variable *attribute = table_config->attributes;
+ while (attribute) {
+ if (strcasecmp(attribute_name, attribute->value) == 0)
+ return attribute->name;
+ else
+ attribute = attribute->next;
+ };
+ };
+ if (table_config == base_table_config)
+ break;
+ else
+ table_config = base_table_config;
+ };
+ return attribute_name;
+};
+
+/*! \brief Find variable by name */
+static struct ast_variable *variable_named(struct ast_variable *var,
+ const char *name)
+{
+ while (var) {
+ if (strcasecmp(name, var->name) == 0)
+ return var;
+ else
+ var = var->next;
+ }
+ return NULL;
+}
+
+/*! \brief Get variables from ldap entry attributes - Should be locked before using it */
+static struct ast_variable *realtime_ldap_entry_to_var(struct ldap_table_config *table_config,
+ LDAPMessage *ldap_entry)
+{
+ BerElement *ber = NULL;
+ struct ast_variable *var = NULL;
+ struct ast_variable *prev = NULL;
+
+ char *ldap_attribute_name =
+ ldap_first_attribute(ldapConn, ldap_entry, &ber);
+
+ while (ldap_attribute_name) {
+ const char *attribute_name =
+ convert_attribute_name_from_ldap(table_config,ldap_attribute_name);
+ int is_realmed_password_attribute =
+ strcasecmp(attribute_name, "md5secret") == 0;
+ char **values = NULL;
+
+ values = ldap_get_values(ldapConn, ldap_entry, ldap_attribute_name);
+ if (!values) {
+ } else {
+ char **v = values;
+
+ while (*v) {
+ char *value = *v;
+ ast_log(LOG_DEBUG,
+ "LDAP RealTime (%d): attribute_name: %s value: %s\n",
+ __LINE__, attribute_name, value);
+ if (is_realmed_password_attribute) {
+ if (strncasecmp(value, "{md5}", 5) == 0)
+ value += 5;
+ else
+ value = NULL;
+ ast_log(LOG_DEBUG, "LDAP RealTime (%d): md5: %s\n",
+ __LINE__, value);
+ };
+ if (value) {
+ if (prev) {
+ prev->next = ast_variable_new(attribute_name, value);
+ if (prev->next) {
+ prev = prev->next;
+ }
+ } else {
+ prev = var = ast_variable_new(attribute_name, value);
+ }
+ }
+ v++;
+ };
+ ldap_value_free(values);
+ }
+ ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
+ }
+ ber_free(ber, 0);
+
+ return var;
+}
+
+static int is_ldap_connect_error(int err)
+{
+ return (err == LDAP_SERVER_DOWN
+ || err == LDAP_TIMEOUT || err == LDAP_CONNECT_ERROR);
+}
+
+/*! \brief LGet LDAP entry by dn and return attributes as variables - Should be locked before using it */
+static struct ast_variable *ldap_loadentry(struct ldap_table_config *table_config,
+ const char *dn)
+{
+ if (!table_config) {
+ ast_log(LOG_ERROR, "LDAP RealTime: Not table config\n");
+ return NULL;
+ } else {
+ struct ast_variable *var = NULL;
+ int result = -1;
+ LDAPMessage *ldap_result = NULL;
+ int tries = 0;
+
+ ast_log(LOG_DEBUG, "LDAP RealTime (%d): ldap_loadentry dn=%s\n",
+ __LINE__, dn);
+
+ do {
+ result = ldap_search_s(ldapConn, dn, LDAP_SCOPE_BASE,
+ "(objectclass=*)", NULL, 0, &ldap_result);
+ if (result < 0 && is_ldap_connect_error(result)) {
+ ast_log(LOG_WARNING,
+ "LDAP RealTime: Failed to query database. Try %d/3\n",
+ tries + 1);
+ tries++;
+ if (tries < 3) {
+ usleep(500000L * tries);
+ if (ldapConn) {
+ ldap_unbind_s(ldapConn);
+ ldapConn = NULL;
+ };
+ if (!ldap_reconnect())
+ break;
+ }
+ }
+ } while (result < 0 && tries < 3 && is_ldap_connect_error(result));
+
+ if (result < 0) {
+ ast_log(LOG_WARNING,
+ "LDAP RealTime: Failed to query database. Check debug for more info.\n");
+ ast_log(LOG_DEBUG, "LDAP RealTime: dn=%s\n", dn);
+ ast_log(LOG_DEBUG, "LDAP RealTime: Query Failed because: %s\n",
+ ldap_err2string(result));
+ ast_mutex_unlock(&ldap_lock);
+ return NULL;
+ } else {
+ int num_entry = 0;
+ if ((num_entry = ldap_count_entries(ldapConn, ldap_result)) > 0) {
+ LDAPMessage *ldap_entry = NULL;
+ ast_log(LOG_DEBUG, "LDAP RealTime (%d): num_entry: %d\n",
+ __LINE__, num_entry);
+
+ ldap_entry = ldap_first_entry(ldapConn, ldap_result);
+ var = realtime_ldap_entry_to_var(table_config, ldap_entry);
+ if (num_entry > 1) {
+ ast_log(LOG_WARNING,
+ "LDAP RealTime: More than one entry for dn=%s. Take only 1st one\n",
+ dn);
+ }
+ } else {
+ ast_log(LOG_WARNING,
+ "LDAP RealTime: Could not find any entry dn=%s.\n",
+ dn);
+ }
+ }
+ ldap_msgfree(ldap_result);
+
+ ast_variable_log("LDAP RealTime: Found Entry", var);
+ return var;
+ }
+}
+
+/*! \brief caller should free returned pointer */
+static char *substituted(struct ast_channel *channel, const char *string)
+{
+#define MAXRESULT 2048
+ char *ret_string = NULL;
+ if (!ast_strlen_zero(string)) {
+ ret_string = malloc(MAXRESULT);
+ if (!ret_string) {
+ ast_log(LOG_WARNING, "Out of memory\n");
+ } else {
+ memset(ret_string, 0, MAXRESULT);
+ pbx_substitute_variables_helper(channel, string, ret_string, MAXRESULT - 1);
+ }
+ }
+ ast_log(LOG_DEBUG, "LDAP RealTime: substituted: string: '%s' => '%s' \n",
+ string, ret_string);
+ return ret_string;
+}
+
+/*! \brief caller should free returned pointer */
+static char *cleaned_basedn(struct ast_channel *channel, const char *basedn)
+{
+ char *cbasedn = NULL;
+ if (basedn) {
+ char *p = NULL;
+ cbasedn = substituted(channel, basedn);
+ if (*cbasedn == '"') {
+ cbasedn++;
+ if (*cbasedn != '\0') {
+ int len = strlen(cbasedn);
+ if (cbasedn[len - 1] == '"')
+ cbasedn[len - 1] = '\0';
+
+ }
+ }
+ p = cbasedn;
+ while (*p) {
+ if (*p == '|')
+ *p = ',';
+ p++;
+ };
+ }
+ ast_log(LOG_DEBUG, "LDAP RealTime (%d): basedn: '%s' => '%s' \n",
+ __LINE__, basedn, cbasedn);
+ return cbasedn;
+}
+
+/*! \brief Append a string to a filter string. The filter string can grow */
+static void append_string_to_filter(char **filter_ptr, int *filter_size_ptr,
+ const char *filter)
+{
+ int current_len = 0;
+ int needed_len = 0;
+ char *r_filter = NULL;
+ if (strchr(filter, '$')) {
+ r_filter = substituted(NULL, filter);
+ filter = r_filter;
+ };
+ current_len = (*filter_ptr ? strlen(*filter_ptr) : 0);
+ needed_len = current_len + strlen(filter);
+ if (*filter_size_ptr < (needed_len + 1)) {
+ if (*filter_size_ptr == 0)
+ *filter_size_ptr = (needed_len > 128 ? needed_len : 128);
+ else
+ *filter_size_ptr = (*filter_size_ptr) * 2;
+ *filter_ptr = realloc(*filter_ptr, *filter_size_ptr);
+ }
+ if (*filter_ptr) {
+ strcpy((*filter_ptr) + current_len, filter);
+ }
+ if (r_filter)
+ free(r_filter);
+}
+
+/*! \brief Replace search by by in string. No check is done on string allocated size ! */
+static int replace_string_in_string(char *string, const char *search,const char *by)
+{
+ int search_len = strlen(search);
+ int by_len = strlen(by);
+ int replaced = 0;
+ char *p = strstr(string, search);
+ if (p) {
+ replaced = 1;
+ while (p) {
+ if (by_len == search_len)
+ memcpy(p, by, by_len);
+ else {
+ memmove(p + by_len, p + search_len,
+ strlen(p + search_len) + 1);
+ memcpy(p, by, by_len);
+ }
+ p = strstr(p + by_len, search);
+ };
+ };
+ return replaced;
+};
+
+/*! \brief Append a name=value filter string. The filter string can grow. */
+/*! \brief convert name and value if "LIKE' is used (see http://bugs.digium.com/view.php?id=5765) */
+static void append_var_and_value_to_filter(char **filter_ptr,
+ int *filter_size_ptr,
+ struct ldap_table_config
+ *table_config, const char *name,
+ const char *value)
+{
+ char *new_name = NULL;
+ char *new_value = NULL;
+ char *wsPos = strstr(name, " LIKE");
+ //ast_log(LOG_DEBUG, "LDAP RealTime: name='%s' value='%s'\n",name,value);
+ if (wsPos) {
+ new_name = strndup(name, wsPos - name);
+ name = new_name;
+ new_value = strdup(value);
+ replace_string_in_string(new_value, "\\_", "_");
+ replace_string_in_string(new_value, "%", "*");
+ value = new_value;
+ }
+ name = convert_attribute_name_to_ldap(table_config, name);
+ append_string_to_filter(filter_ptr, filter_size_ptr, "(");
+ append_string_to_filter(filter_ptr, filter_size_ptr, name);
+ append_string_to_filter(filter_ptr, filter_size_ptr, "=");
+ append_string_to_filter(filter_ptr, filter_size_ptr, value);
+ append_string_to_filter(filter_ptr, filter_size_ptr, ")");
+ if (new_name)
+ free(new_name);
+ if (new_value)
+ free(new_value);
+}
+
+/*! \brief LDAP base function */
+ return a null terminated array of ast_variable (one per entry) or NULL if no entry is found or if an error occured
+ caller should free the returned array and ast_variables
+ entries_count_ptr is a pointer to found entries count (can be NULL)
+ basedn is the base DN
+ table_name is the table_name (used dor attribute convertion and additional filter)
+ ap contains null terminated list of pairs name/value
+*/
+static struct ast_variable **realtime_ldap_base(unsigned int
+ *entries_count_ptr,
+ const char *basedn,
+ const char *table_name,
+ va_list ap)
+{
+ ast_log(LOG_DEBUG,
+ "LDAP RealTime (%d): realtime_ldap_base: basedn: %s table_name: %s\n",
+ __LINE__, basedn, table_name);
+ struct ast_variable **vars = NULL;
+ if (!table_name) {
+ ast_log(LOG_WARNING, "LDAP RealTime: No table_name specified.\n");
+ } else {
+ const char *newparam = NULL;
+ const char *newval = NULL;
+
+ /* Get the first parameter and first value in our list of passed paramater/value pairs */
+ newparam = va_arg(ap, const char *);
+ newval = va_arg(ap, const char *);
+ if (!newparam || !newval) {
+ ast_log(LOG_WARNING,
+ "LDAP RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
+ } else {
+ ast_mutex_lock(&ldap_lock);
+
+ /* We now have our complete statement; Lets connect to the server and execute it. */
+ if (!ldap_reconnect()) {
+ } else {
+ struct ldap_table_config *table_config = NULL;
+
+ table_config = table_config_for_table_name(table_name);
+ if (!table_config) {
+ ast_log(LOG_WARNING,
+ "LDAP RealTime: No table named '%s'.\n",
+ table_name);
+ } else {
+ char *clean_basedn = cleaned_basedn(NULL, basedn);
+ char *filter = NULL;
+ int filter_size = 0;
+ int tries = 0;
+
+ int result = 0;
+ LDAPMessage *ldap_result = NULL;
+
+ append_string_to_filter(&filter, &filter_size, "(&");
+
+ if (table_config && table_config->additional_filter) {
+ append_string_to_filter(&filter, &filter_size,
+ table_config->additional_filter);
+ };
+ if (table_config != base_table_config && base_table_config
+ && base_table_config->additional_filter) {
+ append_string_to_filter(&filter, &filter_size,
+ base_table_config->additional_filter);
+ };
+
+ /* Create the first part of the query using the first parameter/value pairs we just extracted */
+ /* If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
+
+ append_var_and_value_to_filter(&filter, &filter_size,
+ table_config, newparam, newval);
+ while ((newparam = va_arg(ap, const char *))) {
+ newval = va_arg(ap, const char *);
+ append_var_and_value_to_filter(&filter, &filter_size,
+ table_config, newparam,
+ newval);
+ }
+ append_string_to_filter(&filter, &filter_size, ")");
+
+ ast_log(LOG_DEBUG, "LDAP RealTime (%d): filter: %s\n",
+ __LINE__, filter);
+
+
+ do {
+ result =
+ ldap_search_s(ldapConn, clean_basedn,
+ LDAP_SCOPE_SUBTREE, filter, NULL, 0,
+ &ldap_result);
+ if (result < 0 && is_ldap_connect_error(result)) {
+ ast_log(LOG_WARNING,
+ "LDAP RealTime: Failed to query database. Try %d/3\n",
+ tries + 1);
+ tries++;
+ if (tries < 3) {
+ usleep(500000L * tries);
+ if (ldapConn) {
+ ldap_unbind_s(ldapConn);
+ ldapConn = NULL;
+ };
+ if (!ldap_reconnect())
+ break;
+ }
+ }
+ } while (result < 0 && tries < 3 &&
+ is_ldap_connect_error(result));
+
+ if (result < 0) {
+ ast_log(LOG_WARNING,
+ "LDAP RealTime: Failed to query database. Check debug for more info.\n");
+ ast_log(LOG_WARNING, "LDAP RealTime: Query: %s\n",
+ filter);
+ ast_log(LOG_WARNING,
+ "LDAP RealTime: Query Failed because: %s\n",
+ ldap_err2string(result));
+ } else {
+ int num_entry = 0;
+ if ((num_entry =
+ ldap_count_entries(ldapConn, ldap_result)) > 0) {
+ LDAPMessage *ldap_entry = NULL;
+ int entry_index = 0;
+ if (entries_count_ptr)
+ *entries_count_ptr = num_entry;
+ vars =
+ malloc(sizeof(struct ast_variable *) *
+ (num_entry + 1));
+ memset(vars, 0,
+ sizeof(struct ast_variable *) *
+ (num_entry + 1));
+ ast_log(LOG_DEBUG,
+ "LDAP RealTime (%d): num_entry: %d\n",
+ __LINE__, num_entry);
+
+ ldap_entry =
+ ldap_first_entry(ldapConn, ldap_result);
+
+ for (entry_index = 0; ldap_entry; entry_index++) {
+ vars[entry_index] =
+ realtime_ldap_entry_to_var(table_config,ldap_entry);
+ ast_variable_log("LDAP RealTime: Found Entry",
+ vars[entry_index]);
+ ldap_entry =
+ ldap_next_entry(ldapConn, ldap_entry);
+ ast_log(LOG_DEBUG,
+ "LDAP RealTime (%d): next entry: %p\n",
+ __LINE__, ldap_entry);
+ };
+ } else {
+ ast_log(LOG_WARNING,
+ "LDAP RealTime: Could not find any entry matching %s in base dn %s.\n",
+ filter, clean_basedn);
+ }
+
+ ldap_msgfree(ldap_result);
+
+ if (vars) {
+ struct ast_variable **p = vars;
+ while (*p) {
+ struct ast_variable *append_var = NULL;
+ struct ast_variable *tmp = *p;
+ while (tmp) {
+ if (strcasecmp(tmp->name, "accountBaseDN")
+ == 0) {
+ struct ast_variable *base_var =
+ ldap_loadentry(table_config,
+ tmp->value);
+ ast_log(LOG_DEBUG,
+ "LDAP RealTime (%d): Loaded base: %s\n",
+ __LINE__, tmp->value);
+ ast_variable_log("Base Variables",
+ base_var);
+ while (base_var) {
+ struct ast_variable *next =
+ base_var->next;
+ struct ast_variable *test_var =
+ *p;
+ int base_var_found = 0;
+ while (test_var) {
+ if (strcasecmp
+ (test_var->name,
+ base_var->name) == 0) {
+ base_var_found = 1;
+ break;
+ } else
+ test_var = test_var->next;
+ };
+ if (base_var_found) {
+ base_var->next = NULL;
+ ast_variables_destroy
+ (base_var);
+ base_var = next;
+ } else {
+ if (append_var)
+ base_var->next =
+ append_var;
+ else
+ base_var->next = NULL;
+ append_var = base_var;
+ base_var = next;
+ };
+ }
+ }
+ if (!tmp->next && append_var) {
+ tmp->next = append_var;
+ tmp = NULL;
+ } else
+ tmp = tmp->next;
+ };
+ p++;
+ }
+ }
+ }
+ if (filter)
+ free(filter);
+ if (clean_basedn)
+ free(clean_basedn);
+ }
+ }
+ ast_mutex_unlock(&ldap_lock);
+ }
+ }
+ return vars;
+}
+
+/*! \brief same as realtime_ldap_base_ but take variable arguments count list */
+static struct ast_variable **realtime_ldap_base_(unsigned int
+ *entries_count_ptr,
+ const char *basedn,
+ const char *table_name, ...)
+{
+ struct ast_variable **vars = NULL;
+ va_list ap;
+ va_start(ap, table_name);
+ vars = realtime_ldap_base(entries_count_ptr, basedn, table_name, ap);
+ va_end(ap);
+ return vars;
+}
+
+/*! \brief See Asterisk doc */
+static struct ast_variable *realtime_ldap(const char *basedn,
+ const char *table_name, va_list ap)
+{
+ ast_log(LOG_DEBUG,
+ "LDAP RealTime (%d): realtime_ldap: basedn: %s table_name: %s\n",
+ __LINE__, basedn, table_name);
+ struct ast_variable **vars =
+ realtime_ldap_base(NULL, basedn, table_name, ap);
+ struct ast_variable *var = NULL;
+ if (vars) {
+ struct ast_variable *last_var = NULL;
+ struct ast_variable **p = vars;
+ while (*p) {
+ if (last_var) {
+ while (last_var->next)
+ last_var = last_var->next;
+ last_var->next = *p;
+ } else {
+ var = *p;
+ last_var = var;
+ }
+ p++;
+ }
+ free(vars);
+ }
+ ast_variable_log("LDAP RealTime: ==> Found Entry", var);
+ return var;
+}
+
+/*! \brief See Asterisk doc */
+static struct ast_config *realtime_multi_ldap(const char *basedn,
+ const char *table_name,
+ va_list ap)
+{
+ ast_log(LOG_DEBUG,
+ "LDAP RealTime (%d): realtime_multi_ldap: basedn: %s table_name: %s\n",
+ __LINE__, basedn, table_name);
+ struct ast_variable **vars =
+ realtime_ldap_base(NULL, basedn, table_name, ap);
+ struct ast_config *cfg = NULL;
+ if (vars) {
+ cfg = ast_config_new();
+ if (!cfg) {
+ ast_log(LOG_WARNING, "Out of memory!\n");
+ } else {
+ struct ast_variable **p = vars;
+ while (*p) {
+ struct ast_category *cat = NULL;
+ cat = ast_category_new("");
+ if (!cat) {
+ ast_log(LOG_WARNING, "Out of memory!\n");
+ break;
+ } else {
+ struct ast_variable *var = *p;
+ while (var) {
+ struct ast_variable *next = var->next;
+ var->next = NULL;
+ ast_variable_append(cat, var);
+ var = next;
+ }
+ }
+ ast_category_append(cfg, cat);
+ p++;
+ }
+ }
+ free(vars);
+ }
+ return cfg;
+
+}
+struct category_and_metric {
+ char *name;
+ int metric;
+ char *variable_name;
+ char *variable_value;
+};
+static int compare_categories(const void *a, const void *b)
+{
+ struct category_and_metric *as = (struct category_and_metric *) a;
+ struct category_and_metric *bs = (struct category_and_metric *) b;
+ if (as->metric < bs->metric)
+ return -1;
+ else if (as->metric > bs->metric)
+ return 1;
+ else
+ return strcmp(as->name, bs->name);
+}
+
+/*! \brief See Asterisk doc */
+static struct ast_config *config_ldap(const char *basedn,
+ const char *table_name,
+ const char *file,
+ struct ast_config *cfg)
+{
+ ast_log(LOG_DEBUG,
+ "LDAP RealTime (%d): config_ldap: basedn: %s table_name: %s\n",
+ __LINE__, basedn, table_name);
+ if (!file || !strcmp(file, RES_CONFIG_LDAP_CONF)) {
+ ast_log(LOG_WARNING, "LDAP RealTime: Cannot configure myself.\n");
+ } else {
+ unsigned int vars_count = 0;
+ struct ast_variable **vars =
+ realtime_ldap_base_(&vars_count, basedn, table_name, "filename",
+ file, "commented", "FALSE", NULL);
+
+ if (vars) {
+ int i = 0;
+ struct ast_variable *new_v = NULL;
+ struct ast_category *cur_cat = NULL;
+ char *last_category = NULL;
+ int last_category_metric = 0;
+
+ /* sort on metric and category */
+ struct category_and_metric *categories =
+ malloc(sizeof(struct category_and_metric) * vars_count);
+ struct ast_variable **p = vars;
+ vars_count = 0;
+ while (*p) {
+ struct ast_variable *category =
+ variable_named(*p, "category");
+ struct ast_variable *cat_metric =
+ variable_named(*p, "cat_metric");
+ struct ast_variable *var_name =
+ variable_named(*p, "variable_name");
+ struct ast_variable *var_val =
+ variable_named(*p, "variable_value");
+ ast_log(LOG_DEBUG, "LDAP RealTime: category: %s\n",
+ category->value);
+ ast_log(LOG_DEBUG, "LDAP RealTime: var_name: %s\n",
+ var_name->value);
+ ast_log(LOG_DEBUG, "LDAP RealTime: var_val: %s\n",
+ var_val->value);
+ ast_log(LOG_DEBUG, "LDAP RealTime: cat_metric: %s\n",
+ cat_metric->value);
+ if (!category) {
+ struct ast_variable *dn = variable_named(*p, "dn");
[... 369 lines stripped ...]
More information about the asterisk-commits
mailing list