Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 183095
Collapse All | Expand All

(-)Makefile.orig (+6 lines)
Lines 18-23 Link Here
18
CFLAGS+=-fPIC
18
CFLAGS+=-fPIC
19
CFLAGS+=-D_GNU_SOURCE
19
CFLAGS+=-D_GNU_SOURCE
20
20
21
LDAPCFLAGS=-DLDAP_DEPRECATED=1
21
INSTALL=install
22
INSTALL=install
22
INSTALL_PREFIX=
23
INSTALL_PREFIX=
23
ASTLIBDIR=$(INSTALL_PREFIX)/usr/lib/asterisk
24
ASTLIBDIR=$(INSTALL_PREFIX)/usr/lib/asterisk
Lines 27-32 Link Here
27
# MySQL stuff...  Autoconf anyone??
28
# MySQL stuff...  Autoconf anyone??
28
#
29
#
29
MODS+=$(shell if [ -d /usr/include/mysql ]; then echo "cdr_addon_mysql.so app_addon_sql_mysql.so res_config_mysql.so"; fi)
30
MODS+=$(shell if [ -d /usr/include/mysql ]; then echo "cdr_addon_mysql.so app_addon_sql_mysql.so res_config_mysql.so"; fi)
31
MODS+=$(shell if [ -f /usr/include/ldap.h ]; then echo "res_config_ldap.so"; fi)
30
CFLAGS+=$(shell if [ -d /usr/include/mysql ]; then echo "-I/usr/include/mysql"; fi)
32
CFLAGS+=$(shell if [ -d /usr/include/mysql ]; then echo "-I/usr/include/mysql"; fi)
31
MLFLAGS=
33
MLFLAGS=
32
MLFLAGS+=$(shell if [ -d /usr/lib64/mysql ]; then echo "-L/usr/lib64/mysql"; fi)
34
MLFLAGS+=$(shell if [ -d /usr/lib64/mysql ]; then echo "-L/usr/lib64/mysql"; fi)
Lines 69-74 Link Here
69
res_config_mysql.so: res_config_mysql.o
71
res_config_mysql.so: res_config_mysql.o
70
	$(CC) $(SOLINK) -o $@ $< -lmysqlclient -lz $(MLFLAGS)
72
	$(CC) $(SOLINK) -o $@ $< -lmysqlclient -lz $(MLFLAGS)
71
73
74
res_config_ldap.so: res_config_ldap.o
75
	$(CC) $(LDAPCFLAGS) $(SOLINK) -o $@ $< -lldap_r -llber -lz $(MLFLAGS)
76
		
77
72
app_addon_sql_mysql.so: app_addon_sql_mysql.o
78
app_addon_sql_mysql.so: app_addon_sql_mysql.o
73
	$(CC) $(SOLINK) -o $@ $< -lmysqlclient -lz $(MLFLAGS)
79
	$(CC) $(SOLINK) -o $@ $< -lmysqlclient -lz $(MLFLAGS)
74
80
(-)res_config_ldap.c.orig (+1248 lines)
Line 0 Link Here
1
/*
2
 * Asterisk -- A telephony toolkit for Linux.
3
 *
4
 * res_config_ldap.c <ldap plugin for RealTime configuration engine>
5
 *
6
 * Todo: 
7
 *	- config_ldap for the static stuff
8
 *	- useful default base dn
9
 *	- testing / bugfixing :-)
10
 *	- check for mem leaks
11
 *
12
 * v0.7   - (12-12-05) - test res and strncat cleanup
13
 * v0.6   - (25-11-05) - less verbose output
14
 * v0.5   - (24-11-05) - makefile cleanups
15
 * v0.4   - (22-09-05) - improved reconnect ( Norbert Graf )
16
 * v0.3   - (18-09-05) - sort by initfield
17
 *                     - use ldap_initialize()
18
 * v0.2   - (14-09-05) - prepend ast to config values
19
 *                     - minor bugfixes & cleanups
20
 * v0.1   - (11-09-05) - Initial version based on res_config_mysql from asterisk-addons
21
 */
22
23
#include <asterisk/channel.h>
24
#include <asterisk/logger.h>
25
#include <asterisk/config.h>
26
#include <asterisk/module.h>
27
#include <asterisk/lock.h>
28
#include <asterisk/options.h>
29
#include <asterisk/cli.h>
30
#include <asterisk/utils.h>
31
#include <stdlib.h>
32
#include <stdio.h>
33
#include <string.h>
34
#include <ldap.h>
35
36
static char *res_config_ldap_desc = "LDAP RealTime Configuration Driver";
37
38
AST_MUTEX_DEFINE_STATIC(ldap_lock);
39
#define RES_CONFIG_LDAP_CONF "res_ldap.conf"
40
#define QUERY_SIZE 512
41
#define OPTION_SIZE 100
42
static char ldapuri[80];
43
static char ldapuser[80];
44
static char ldappass[80];
45
static char ldapbasedn[80];
46
static int  connected;
47
static time_t connect_time;
48
static int errorcount = 0;
49
static int parse_config(void);
50
static LDAP *ldap_reconnect();
51
void ldap_disconnect(LDAP *ldap);
52
static int realtime_ldap_status(int fd, int argc, char **argv);
53
int ldap_get_value_s(LDAP *ldap, const char *ldapbasedn,const char filter[QUERY_SIZE], char *attrs[], char *attrvalues[]);
54
55
typedef struct list
56
{
57
	char *string[QUERY_SIZE];
58
	char *members[QUERY_SIZE];
59
	struct list *next;
60
} context;
61
62
context *anf = NULL;
63
64
STANDARD_LOCAL_USER;
65
66
LOCAL_USER_DECL;
67
68
static char cli_realtime_ldap_status_usage[] =
69
"Usage: realtime ldap status\n"
70
"       Shows connection information for the LDAP RealTime driver\n";
71
72
static struct ast_cli_entry cli_realtime_ldap_status = {
73
        { "realtime", "ldap", "status", NULL }, realtime_ldap_status,
74
        "Shows connection information for the LDAP RealTime driver", cli_realtime_ldap_status_usage, NULL };
75
76
static struct ast_variable *realtime_ldap(const char *database, const char *table, va_list ap)
77
{
78
	int numFields;
79
	char *chunk;
80
	char *op;
81
	struct ast_variable *var=NULL, *prev=NULL;
82
	const char *newparam, *newval;
83
	char query[QUERY_SIZE];
84
	char query2[QUERY_SIZE];
85
	int i=0;
86
	int j=0;
87
	int search;
88
	LDAPMessage *res, *res2;
89
	BerElement *ber;
90
	char **values;
91
	char *attr;
92
	LDAP *ldap;
93
	
94
	ast_log(LOG_DEBUG, "realtime_ldap\n");
95
96
	if(!table) {
97
		ast_log(LOG_WARNING, "LDAP RealTime: No table specified.\n");
98
		return NULL;
99
	}
100
101
	/* Get the first parameter and first value in our list of passed paramater/value pairs */
102
	newparam = va_arg(ap, const char *);
103
	newval = va_arg(ap, const char *);
104
	if(!newparam || !newval)  {
105
		ast_log(LOG_WARNING, "LDAP RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
106
		return NULL;
107
	}
108
	
109
	/* Create the first part of the query using the first parameter/value pairs we just extracted
110
	   If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
111
112
	if(!strchr(newparam, ' ')) op = "="; else op = "";
113
114
	snprintf(query, sizeof(query), "(&(objectClass=ast%s)(ast%s%s%s))", table, newparam, op, newval);
115
	while((newparam = va_arg(ap, const char *))) {
116
		i++;
117
		newval = va_arg(ap, const char *);
118
		if(!strchr(newparam, ' ')) op = "="; else op = "";
119
		snprintf(query + strlen(query), sizeof(query) - strlen(query), "(ast%s%s%s))", newparam, op, newval);
120
	}
121
	va_end(ap);
122
	query2[0] = '\0';
123
	for ( j=0; j<i; j++ ) 
124
		strncat(query2, "&", sizeof(query2)-1);
125
126
	strncat(query2, query, sizeof(query2)-1);
127
128
	ast_log(LOG_WARNING, "LDAP RealTime: Retrieve LDAP: %s\n", query2);
129
	/* We now have our complete statement; Lets connect to the server and execute it. */
130
	ldap = ldap_reconnect();
131
	if(!ldap) {
132
		return NULL;
133
	}
134
	ast_mutex_lock(&ldap_lock);
135
	search = ldap_search_s(ldap, ldapbasedn, LDAP_SCOPE_SUBTREE, query2, NULL, 0, &res);
136
	if(search != LDAP_SUCCESS) {
137
		ast_log(LOG_WARNING, "LDAP RealTime: Failed to query database. Check debug for more info.\n");
138
		ast_log(LOG_WARNING, "LDAP RealTime: Query: %s\n", query2);
139
		if ( res != NULL ) {
140
			ast_log(LOG_WARNING, "LDAP RealTime: Query Failed because: %s\n", ldap_err2string(search));
141
		}
142
		ldap_disconnect(ldap);
143
		ast_mutex_unlock(&ldap_lock);
144
		return NULL;
145
	}
146
	numFields = ldap_count_entries(ldap, res);
147
	if ( numFields > 0 ) {
148
		res2 = ldap_first_entry(ldap, res);		
149
		while(res2) {
150
			attr = ldap_first_attribute(ldap, res, &ber);
151
			while (attr) {
152
				if ( attr && !strncmp(attr, "ast", 3) ) {
153
					values = ldap_get_values(ldap, res, attr);
154
					attr += 3;
155
					i = 0;
156
					while(values[i]) {
157
						chunk = strsep((char **) &values[i], ";");
158
						if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
159
						//	ast_log(LOG_WARNING, "%s-%s\n", attr, chunk);
160
							if(prev) {
161
								prev->next = ast_variable_new(attr, chunk);
162
								if (prev->next) {
163
									prev = prev->next;
164
								}
165
							} else {
166
								prev = var = ast_variable_new(attr, chunk);
167
							}
168
						}
169
						i++;
170
					}
171
				}
172
				/* ldap_value_free(values); */
173
				/* ldap_memfree(attr-3); */
174
				attr = ldap_next_attribute(ldap, res, ber); 
175
			}
176
			res = ldap_next_entry(ldap, res2);
177
			ldap_memfree(res2);
178
			res2 = res;
179
		}
180
	} else {                                
181
		ast_log(LOG_DEBUG, "LDAP RealTime: Could not find any entries in table %s.\n", table);
182
	}
183
	ldap_msgfree(res);
184
	ldap_disconnect(ldap);
185
	ast_mutex_unlock(&ldap_lock);
186
187
	return var;
188
}
189
190
static struct ast_config *realtime_multi_ldap(const char *database, const char *table, va_list ap)
191
{
192
	int numFields, i, j, search = 0;
193
	char query[QUERY_SIZE];
194
	char query2[QUERY_SIZE];
195
	const char *initfield = NULL;
196
	char *chunk;
197
	char *op;
198
	const char *newparam, *newval;
199
	struct ast_realloca ra;
200
	struct ast_variable *var=NULL;
201
	struct ast_config *cfg = NULL;
202
	struct ast_category *cat = NULL;
203
	LDAPMessage *res, *res2;
204
	BerElement *ber;
205
	char **values;
206
	char *attr;
207
	LDAP *ldap;
208
	
209
	ast_log(LOG_DEBUG, "realtime_multi_ldap\n");
210
	if(!table) {
211
		ast_log(LOG_WARNING, "LDAP RealTime: No table specified.\n");
212
		return NULL;
213
	}
214
	
215
	memset(&ra, 0, sizeof(ra));
216
217
	cfg = ast_config_new();
218
	if (!cfg) {
219
		/* If I can't alloc memory at this point, why bother doing anything else? */
220
		ast_log(LOG_WARNING, "Out of memory!\n");
221
		return NULL;
222
	}
223
224
	/* Get the first parameter and first value in our list of passed paramater/value pairs */
225
	newparam = va_arg(ap, const char *);
226
	newval = va_arg(ap, const char *);
227
	if(!newparam || !newval)  {
228
		ast_log(LOG_WARNING, "LDAP RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
229
		return NULL;
230
	}
231
232
	initfield = ast_strdupa(newparam);
233
	if(initfield && (op = strchr(initfield, ' '))) {
234
		*op = '\0';
235
	}
236
237
	/* Create the first part of the query using the first parameter/value pairs we just extracted
238
	   If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
239
240
	if(!strchr(newparam, ' ')) op = "="; else op = "";
241
	snprintf(query, sizeof(query), "(&(objectClass=ast%s)(ast%s%s%s))", table, newparam, op, newval);
242
	while((newparam = va_arg(ap, const char *))) {
243
		i++;
244
		newval = va_arg(ap, const char *);
245
		if(!strchr(newparam, ' ')) op = "="; else op = "";
246
		snprintf(query + strlen(query), sizeof(query) - strlen(query), "(ast%s%s%s))", newparam, op, newval);
247
	}
248
	va_end(ap);
249
	query2[0] = '\0';
250
	for ( j=0; j<i; j++ ) 
251
		strncat(query2, "(&", sizeof(query2)-1);
252
253
	strncat(query2, query, sizeof(query2)-1);
254
255
	va_end(ap);
256
257
	ast_log(LOG_WARNING, "LDAP RealTime: Retrieve LDAP: %s\n", query);
258
259
	/* We now have our complete statement; Lets connect to the server and execute it. */
260
	ldap = ldap_reconnect();
261
	if(!ldap) {
262
		return NULL;
263
	}
264
265
	ast_mutex_lock(&ldap_lock);
266
	search = ldap_search_s(ldap, ldapbasedn, LDAP_SCOPE_SUBTREE, query2, NULL, 0, &res);
267
	if(search != LDAP_SUCCESS) {
268
		ast_log(LOG_WARNING, "LDAP RealTime: Failed to query database. Check debug for more info.\n");
269
		ast_log(LOG_WARNING, "LDAP RealTime: Query: %s\n", query2);
270
		if ( res != NULL ) {
271
			ast_log(LOG_WARNING, "LDAP RealTime: Query Failed because: %s\n", ldap_err2string(search));
272
		}
273
		ast_mutex_unlock(&ldap_lock);
274
		ldap_disconnect(ldap);
275
		return NULL;
276
	}
277
278
	if (initfield) {
279
		ldap_sort_entries(ldap, &res, initfield, strcasecmp);
280
	}
281
282
	numFields = ldap_count_entries(ldap, res);
283
	if ( numFields > 0 ) {
284
		res2 = ldap_first_entry(ldap, res);		
285
		while(res2) {
286
			var = NULL;
287
			cat = ast_category_new("");
288
			if(!cat) {
289
				ast_log(LOG_WARNING, "Out of memory!\n");
290
				continue;
291
			}
292
293
			attr = ldap_first_attribute(ldap, res, &ber);
294
			while (attr) {
295
				if ( !strncmp(attr, "ast", 3) ) {
296
					values = ldap_get_values(ldap, res, attr);
297
					attr += 3;
298
					i = 0;
299
					while(values[i]) {
300
						chunk = strsep((char **) &values[i], ";");
301
						if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
302
							if(initfield && !strcmp(initfield, attr)) {
303
								ast_category_rename(cat, chunk);
304
							}
305
							var = ast_variable_new(attr, chunk);
306
							ast_variable_append(cat, var);
307
						}
308
						i++;
309
					}
310
				}
311
				ldap_value_free(values);
312
				attr = ldap_next_attribute(ldap, res, ber); 
313
			}
314
			ast_category_append(cfg, cat);
315
			res = ldap_next_entry(ldap, res2);
316
			ldap_memfree(res2);
317
			res2 = res;
318
		}
319
	} else {
320
		ast_log(LOG_DEBUG, "LDAP RealTime: Could not find any rows in table %s.\n", table);
321
	}
322
323
	ldap_msgfree(res);
324
	ldap_disconnect(ldap);
325
	ast_mutex_unlock(&ldap_lock);
326
	return cfg;
327
}
328
329
static int update_ldap(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
330
{
331
	char query[QUERY_SIZE];
332
	//char query2[QUERY_SIZE];
333
	char buf[256];
334
	const char *newparam, *newval;
335
	char *dn;
336
	LDAPMessage *res, *res2;
337
	LDAPMod mod_change;
338
	LDAPMod *all_changes[2];
339
	char *mod_vals[] = {"", NULL};
340
	int search, numFields;
341
	LDAP *ldap;
342
	
343
	all_changes[0] = &mod_change;
344
	all_changes[1] = NULL;
345
346
347
	ast_log(LOG_DEBUG, "update_ldap\n");
348
349
	mod_change.mod_op = LDAP_MOD_REPLACE;
350
	mod_change.mod_values = mod_vals;
351
	mod_change.mod_type = buf;
352
353
	if(!table) {
354
		ast_log(LOG_WARNING, "LDAP RealTime: No table specified.\n");
355
		return -1;
356
	}
357
358
	/* Get the first parameter and first value in our list of passed paramater/value pairs */
359
	newparam = va_arg(ap, const char *);
360
	newval = va_arg(ap, const char *);
361
	if(!newparam || !newval)  {
362
		ast_log(LOG_WARNING, "LDAP RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
363
		return -1;
364
	}
365
366
	/* Create the first part of the query using the first parameter/value pairs we just extracted
367
	   If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
368
369
370
	snprintf(query, sizeof(query), "(&(objectClass=ast%s)(ast%s=%s))", table, keyfield, lookup);
371
	ast_log(LOG_WARNING, "LDAP RealTime: Retrieve LDAP: %s\n", query);
372
373
	/* We now have our complete statement; Lets connect to the server and execute it. */
374
	ldap = ldap_reconnect();
375
	if(!ldap) {
376
		return -1;
377
	}
378
379
	ast_mutex_lock(&ldap_lock);
380
	search = ldap_search_s(ldap, ldapbasedn, LDAP_SCOPE_SUBTREE, query, NULL, 0, &res);
381
	if(search != LDAP_SUCCESS) {
382
		ast_log(LOG_WARNING, "LDAP RealTime: Failed to query database. Check debug for more info.\n");
383
		ast_log(LOG_DEBUG, "LDAP RealTime: Query: %s\n", query);
384
		if ( res != NULL ) {
385
			ast_log(LOG_WARNING, "LDAP RealTime: Query Failed because: %s\n", ldap_err2string(ldap_result2error(ldap, res, 1)));
386
		}
387
		ast_mutex_unlock(&ldap_lock);
388
		ldap_disconnect(ldap);
389
		return -1;
390
	}
391
392
	numFields = ldap_count_entries(ldap, res);
393
	if ( numFields > 0 ) {
394
		res2 = ldap_first_entry(ldap, res);		
395
		while(res2) {
396
			dn = ldap_get_dn(ldap, res2);
397
			ast_log(LOG_DEBUG, "LDAP RealTime: --%s\n", dn);
398
			do {
399
				ast_log(LOG_WARNING, "LDAP RealTime update: --%s --%s\n", newparam, newval);
400
				snprintf(buf, sizeof(buf), "ast%s", newparam);
401
				mod_vals[0] = (char *) newval;
402
				ldap_modify_s(ldap, dn, all_changes);
403
			} while((newparam = va_arg(ap, const char *)) && (newval = va_arg(ap, const char *)));
404
			res = ldap_next_entry(ldap, res2);
405
			ldap_memfree(res2);
406
			res2 = res;
407
		}
408
	}
409
	ldap_disconnect(ldap);
410
	ast_mutex_unlock(&ldap_lock);
411
	
412
	/* get better return value */
413
	return 1;
414
}
415
416
context *get_config(LDAP *ldap, const char *ldapbasedn, const char filter[QUERY_SIZE], char *attrs[], char *doubleEntries)
417
{
418
	int numFields;
419
	char *chunk, *dn, *attr, **values;
420
	int i = 0;
421
	int j = 0;
422
	int k = 0;
423
	long ldapSearchResult = 0;
424
	LDAPMessage *res, *res2;
425
	BerElement *ber;
426
	context *start = NULL, *p = NULL;
427
428
	/* Is the ldapbasedn set? */
429
	if(!ldapbasedn) {
430
		ast_log(LOG_DEBUG, "No BaseDN specified.\n");
431
		return NULL;
432
	}
433
434
	/* Dose we have a filter */
435
	if(!filter || !strlen(filter))  {
436
		ast_log(LOG_DEBUG, "No Filter specified.\n");
437
		return NULL;
438
	}
439
440
	if(!ldap) {
441
		ast_log(LOG_DEBUG, "No connection!\n");
442
		return NULL;
443
	}
444
445
	/* lets search the statement */
446
	ldapSearchResult = ldap_search_s(ldap, ldapbasedn, LDAP_SCOPE_SUBTREE, filter, attrs , 0, &res);
447
	if(ldapSearchResult != LDAP_SUCCESS) {
448
		ast_log(LOG_WARNING, "LDAP RealTime: Failed to query database. Check debug for more info.\n");
449
		ast_log(LOG_WARNING, "LDAP RealTime: Query: %s\n", filter);
450
		if ( res != NULL ) {
451
			ast_log(LOG_WARNING, "LDAP RealTime: Query Failed because: %s\n", ldap_err2string(ldap_result2error(ldap, res, 1)));
452
		}
453
		return NULL;
454
	}
455
456
	numFields = ldap_count_entries(ldap, res);
457
	if ( numFields > 0 ) {
458
		/* sort the result */
459
		ldap_sort_entries(ldap, &res, attrs[1], strcasecmp);
460
		res2 = ldap_first_entry(ldap, res);
461
		while(res2) {
462
			attr = ldap_first_attribute(ldap, res, &ber);
463
			/* initialize a new context */
464
			if((p = (context*)malloc(sizeof(context)))) {
465
				/* initialize field */
466
				for(i=0; attrs[i] != NULL; i++) {
467
					p->string[i] = strdup("");
468
					p->members[i] = strdup("");
469
				}
470
				p->string[i] = NULL;
471
				p->members[i] = NULL;
472
473
				/* set field values */
474
				dn = ldap_get_dn(ldap, res);
475
				/* if we must look for a "dn" */
476
				for(i = 0; attrs[i] != NULL; i++)
477
					if(!strcasecmp(attrs[i], "dn")) {
478
						p->string[i] = strdup(dn);
479
						break;
480
					}
481
482
				k = 0;
483
				while (attr) {
484
					values = ldap_get_values(ldap, res, attr);
485
					i = 0;
486
487
					while(values[i]) {
488
						chunk = strsep((char **) &values[i], ";");
489
						if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
490
							for(j = 0; attrs[j] != NULL; j++) {
491
								if(!strcmp(attr, attrs[j]) || !strcmp(chunk, attrs[0])) {
492
									ast_log(LOG_DEBUG, "%s-%s\n", attr, chunk);
493
									if(!strcmp(attr, doubleEntries)) {
494
										p->members[k] = strdup(chunk);
495
										k++;
496
										break;
497
									} else {
498
										p->string[j] = strdup(chunk);
499
										break;
500
									}
501
								}
502
							}
503
						}
504
						i++;
505
					}
506
					ldap_value_free(values);
507
					ldap_memfree(attr);
508
					attr = ldap_next_attribute(ldap, res, ber); 
509
				}
510
				/* set the last element */
511
				p->members[k] = NULL;
512
				res = ldap_next_entry(ldap, res2);
513
				ldap_memfree(res2);
514
				res2 = res;
515
				p->next=start;
516
				start = p;
517
			} else
518
				ast_log(LOG_WARNING, "Out of memory!\n");
519
		}
520
	} else {                                
521
		ast_log(LOG_DEBUG, "LDAP RealTime: Could not find any entries in DN \'%s\' with filter \'%s\'.\n", ldapbasedn, filter);
522
	}
523
	/* free all stuff */
524
	ldap_msgfree(res);
525
	free(chunk);
526
	free(dn);
527
	free(attr);
528
	ast_mutex_unlock(&ldap_lock);
529
530
	return start;
531
}
532
533
void rm_context()
534
{
535
	context *p;
536
537
	while(anf != NULL) {
538
		p = anf;
539
		anf = p->next;
540
		free(p);
541
	}
542
}
543
544
context *del_akt_context(context *p)
545
{
546
	context *q;
547
548
	if(p == anf) {
549
		anf = p->next;
550
		return anf;
551
	} else {
552
		q = anf;
553
		while(q->next != p)
554
			q = q->next;
555
		q->next = p->next;
556
	}
557
	free(p);
558
	return q->next;
559
}
560
561
context *search_context(const char *stringToSearch, int index)
562
{
563
	context *p = anf;
564
565
	while(p) {
566
		if(!strcmp(p->string[index], stringToSearch))
567
			break;
568
		p = p->next;
569
	}
570
571
	return p;
572
}
573
574
575
static struct ast_config *config_ldap(const char *database, const char *table, const char *file, struct ast_config *cfg)
576
{
577
	int i, j, barrier;
578
	char *attrs[OPTION_SIZE], *options[OPTION_SIZE], filter[QUERY_SIZE], *var_val = NULL, *old_context = NULL;
579
	struct ast_variable *var=NULL;
580
	struct ast_category *cat = NULL;
581
	LDAP *ldap;
582
	context *p = NULL;
583
	FILE *datei;
584
	char a[QUERY_SIZE], b[QUERY_SIZE];
585
	
586
	/* Is it my config file ("res_ldap.conf")? */
587
	if(!file || !strcmp(file, RES_CONFIG_LDAP_CONF)) {
588
		ast_log(LOG_WARNING, "LDAP RealTime: Cannot configure myself.\n");
589
		return NULL;
590
	
591
	} else {
592
		if((datei = fopen(database, "rt"))) {
593
			ast_log(LOG_WARNING, "LDAP RealTime: Reading LDAP-Fields from File: \'%s\'.\n", database);
594
595
			i = 0;
596
			while(!feof(datei)) {
597
				fscanf(datei, "%s\t%s\n", a, b);
598
				if(i+1 >= OPTION_SIZE) {
599
					ast_log(LOG_ERROR, "LDAP RealTime: Out of memory! %i\n",i);
600
					fclose(datei);
601
					/* free fields */
602
					for(j = 0; j < i; j++)
603
						free(attrs[j]);
604
					for(j = 0; j < i; j++)
605
						free(options[j]);
606
					return NULL;
607
				}
608
				attrs[i]   = strdup(a);
609
				options[i] = strdup(b);
610
				i++;
611
			}
612
			fclose(datei);
613
			attrs[i]   = NULL;
614
			options[i] = NULL;
615
616
			/* show the field entrys */
617
			for(i=0; options[i]; i++)
618
					ast_log(LOG_DEBUG, "%s=%s\n", attrs[i], options[i]);
619
620
		} else {
621
			ast_log(LOG_WARNING, "LDAP RealTime: Fail to open file \'%s\'. Using defaults!\n", database);
622
		
623
			if(!strcmp(file, "voicemail.conf")) {
624
			/* fields we wont to get from ldap
625
			   We don't care about global options! 
626
			   (need no new objct) */
627
			attrs[0]  = strdup("astVoicemailGeneralConfig");		options[0] = strdup("objectClass");	// objectClass for the generals
628
			attrs[1]  = strdup("astVoicemailContext");			options[1] = strdup("Context");
629
			/* General options */
630
			attrs[2]  = strdup("astVoicemailFormat");			options[2]  = strdup("Format");
631
			attrs[3]  = strdup("astVoicemailServeremail");			options[3]  = strdup("Serveremail");
632
			attrs[4]  = strdup("astVoicemailAttach");			options[4]  = strdup("Attach");		// Is general and MailBox option
633
			attrs[5]  = strdup("astVoicemailMaxmsg");			options[5]  = strdup("Maxmsg");
634
			attrs[6]  = strdup("astVoicemailMaxmessage");			options[6]  = strdup("Maxmessage");
635
			attrs[7]  = strdup("astVoicemailMinmessage");			options[7]  = strdup("Minmessage");
636
			attrs[8]  = strdup("astVoicemailMaxgreet");			options[8]  = strdup("Maxgreet");
637
			attrs[9]  = strdup("astVoicemailSkipms");			options[9]  = strdup("Skipms");
638
			attrs[10] = strdup("astVoicemailMaxsilence");			options[10] = strdup("Maxsilence");
639
			attrs[11] = strdup("astVoicemailMaxlogins");			options[11] = strdup("Maxlogins");
640
			attrs[12] = strdup("astVoicemailExternnotify");			options[12] = strdup("Externnotify");
641
			attrs[13] = strdup("astVoicemailExternpass");			options[13] = strdup("Externpass");
642
			attrs[14] = strdup("astVoicemailDirectoryintro");		options[14] = strdup("Directoryintro");
643
			attrs[15] = strdup("astVoicemailCharset");			options[15] = strdup("Charset");
644
			attrs[16] = strdup("astVoicemailAdsifdn");			options[16] = strdup("Adsifdn");
645
			attrs[17] = strdup("astVoicemailAdsisec");			options[17] = strdup("Adsisec");
646
			attrs[18] = strdup("astVoicemailAdsiver");			options[18] = strdup("Adsiver");
647
			attrs[19] = strdup("astVoicemailPbxskip");			options[19] = strdup("Pbxskip");
648
			attrs[20] = strdup("astVoicemailFromstring");			options[20] = strdup("Fromstring");
649
			attrs[21] = strdup("astVoicemailUsedirectory");			options[21] = strdup("Usedirectory");
650
			attrs[22] = strdup("astVoicemailEmailsubject");			options[22] = strdup("Emailsubject");
651
			attrs[23] = strdup("astVoicemailEmailbody");			options[23] = strdup("Emailbody");
652
			attrs[24] = strdup("astVoicemailEmaildateformat");		options[24] = strdup("Emaildateformat");
653
			attrs[25] = strdup("astVoicemailMailcmd");			options[25] = strdup("Mailcmd");
654
			attrs[26] = strdup("astVoicemailTz");				options[26] = strdup("Tz");
655
			/* MailBox spezific */
656
			attrs[27] = strdup("astVoicemailSaycid");			options[27] = strdup("Saycid");
657
			attrs[28] = strdup("astVoicemailCidinternalContexts");		options[28] = strdup("CidinternalContexts");
658
			attrs[29] = strdup("astVoicemailSayduration");			options[29] = strdup("Sayduration");
659
			attrs[30] = strdup("astVoicemailSaydurationm");			options[30] = strdup("Saydurationm");
660
			attrs[31] = strdup("astVoicemailDialout");			options[31] = strdup("Dialout");
661
			attrs[32] = strdup("astVoicemailSendvoicemail");		options[32] = strdup("Sendvoicemail");
662
			attrs[33] = strdup("astVoicemailSearchcontexts");		options[33] = strdup("Searchcontexts");
663
			attrs[34] = strdup("astVoicemailCallback");			options[34] = strdup("Callback");
664
			attrs[35] = strdup("astVoicemailReview");			options[35] = strdup("Review");
665
			attrs[36] = strdup("astVoicemailOperator");			options[36] = strdup("Operator");
666
			attrs[37] = strdup("astVoicemailEnvelope");			options[37] = strdup("Envelope");
667
			attrs[38] = strdup("astVoicemailDelete");			options[38] = strdup("Delete");
668
			attrs[39] = strdup("astVoicemailNextaftercmd");			options[39] = strdup("Nextaftercmd");
669
			attrs[40] = strdup("astVoicemailForcename");			options[40] = strdup("Forcename");
670
			attrs[41] = strdup("astVoicemailForcegreetings");		options[41] = strdup("Forcegreetings");
671
			attrs[42] = strdup("astVoicemailHidefromdir");			options[42] = strdup("Hidefromdir");
672
			/* Fix Mailbox identifiers */
673
			attrs[43] = strdup("astVoicemailVoiceboxNr");			options[43] = strdup("VoiceboxNr");	// <mailbox_Nr> =>
674
			attrs[44] = strdup("astVoicemailPassword");			options[44] = strdup("Password");	// <password>
675
			attrs[45] = strdup("cn");					options[45] = strdup("Mailbox");	// <name> we get from somewhere
676
			attrs[46] = strdup("mail");					options[46] = strdup("Email");		// <email>  we get from somewhere
677
			attrs[47] = strdup("astVoicemailPager");			options[47] = strdup("Pager");		// <pager>
678
			attrs[48] = NULL;						options[48]= NULL;
679
680
		} else if(!strcmp(file, "queues.conf")) {
681
			/* fields we wont to get from ldap 
682
			   (need a new object) */
683
			attrs[0]  = strdup("astQueueGeneralConfig");			options[0]  = strdup("objectClass");	// objectClass for the generals
684
			attrs[1]  = strdup("astQueueContext");				options[1]  = strdup("Context");
685
			/* General options */
686
			attrs[2]  = strdup("astQueuePersistentmembers");		options[2]  = strdup("astQueuePersistentmembers");
687
			/* Queue spezific */
688
			attrs[3]  = strdup("astQueueMusiconhold");			options[3]  = strdup("Musiconhold");
689
			attrs[4]  = strdup("astQueueAnnounce");				options[4]  = strdup("Announce");
690
			attrs[5]  = strdup("astQueueStrategy");				options[5]  = strdup("Strategy");
691
			attrs[6]  = strdup("astQueueDervicelevel");			options[6]  = strdup("Dervicelevel");
692
			attrs[7]  = strdup("astQueueGoToContext");			options[7]  = strdup("Context");
693
			attrs[8]  = strdup("astQueueTimeout");				options[8]  = strdup("Timeout");
694
			attrs[9]  = strdup("astQueueRetry");				options[9]  = strdup("Retry");
695
			attrs[10] = strdup("astQueueWeight");				options[10] = strdup("Weight");
696
			attrs[11] = strdup("astQueueWrapuptime");			options[11] = strdup("Wrapuptime");
697
			attrs[12] = strdup("astQueueMaxlen");				options[12] = strdup("Maxlen");
698
			attrs[13] = strdup("astQueueAnnounceFrequency");		options[13] = strdup("Announce-frequency");
699
			attrs[14] = strdup("astQueuePeriodicAnnounceFrequency");	options[14] = strdup("Periodic-announce-frequency");
700
			attrs[15] = strdup("astQueueAnnounceHoldtime");			options[15] = strdup("Announce-holdtime");
701
			attrs[16] = strdup("astQueueAnnounceRoundSeconds");		options[16] = strdup("Announce-round-seconds");
702
			attrs[17] = strdup("astQueueQueueYouarenext");			options[17] = strdup("Queue-youarenext");
703
			attrs[18] = strdup("astQueueQueueThereare");			options[18] = strdup("Queue-thereare");
704
			attrs[19] = strdup("astQueueQueueCallswaiting");		options[19] = strdup("Queue-callswaiting");
705
			attrs[20] = strdup("astQueueQueueHoldtime");			options[20] = strdup("Queue-holdtime");
706
			attrs[21] = strdup("astQueueQueueMinutes");			options[21] = strdup("Queue-minutes");
707
			attrs[22] = strdup("astQueueQueueSeconds");			options[22] = strdup("Queue-seconds");
708
			attrs[23] = strdup("astQueueQueueThankyou");			options[23] = strdup("Queue-thankyou");
709
			attrs[24] = strdup("astQueueQueueLessthan");			options[24] = strdup("Queue-lessthan");
710
			attrs[25] = strdup("astQueueQueueReporthold");			options[25] = strdup("Queue-reporthold");
711
			attrs[26] = strdup("astQueuePeriodicAnnounce");			options[26] = strdup("Periodic-announce");
712
			attrs[27] = strdup("astQueueMonitorFormat");			options[27] = strdup("Monitor-format");
713
			attrs[28] = strdup("astQueueMonitorJoin");			options[28] = strdup("Monitor-join");
714
			attrs[29] = strdup("astQueueJoinempty");			options[29] = strdup("Joinempty");
715
			attrs[30] = strdup("astQueueLeavewhenempty");			options[30] = strdup("Leavewhenempty");
716
			attrs[31] = strdup("astQueueEventwhencalled");			options[31] = strdup("Eventwhencalled");
717
			attrs[32] = strdup("astQueueEventmemberstatusoff");		options[32] = strdup("Eventmemberstatusoff");
718
			attrs[33] = strdup("astQueueReportholdtime");			options[33] = strdup("Reportholdtime");
719
			attrs[34] = strdup("astQueueMemberdelay");			options[34] = strdup("Memberdelay");
720
			attrs[35] = strdup("astQueueTimeoutrestart");			options[35] = strdup("Timeoutrestart");
721
			/* the QueueMembers */
722
			attrs[36] = strdup("astQueueMember");				options[36]= strdup("member");		// must be the last field element!
723
			attrs[37] = NULL;						options[37]= NULL;
724
725
		} else if(!strcmp(file, "agents.conf")) {
726
			/* fields we wont to get from ldap 
727
			   (need a new object) */
728
			attrs[0]  = strdup("astAgentGeneralConfig");			options[0] = strdup("objectClass");	// objectClass for the generals
729
			attrs[1]  = strdup("astAgentContext");				options[1] = strdup("Context");
730
			/* General options */
731
			attrs[2]  = strdup("astAgentPersistentagents");			options[2] = strdup("Persistentagents");
732
			/* Agent spezific */
733
			attrs[3]  = strdup("astAgentAutologoff");			options[3] = strdup("Autologoff");
734
			attrs[4]  = strdup("astAgentAckcall");				options[4] = strdup("Ackcall");
735
			attrs[5]  = strdup("astAgentWrapuptime");			options[5] = strdup("Wrapuptime");
736
			attrs[6]  = strdup("astAgentMusiconhold");			options[6] = strdup("Musiconhold");
737
			attrs[7]  = strdup("astAgentUpdatecdr");			options[7] = strdup("Updatecdr");
738
			attrs[8]  = strdup("astAgentGroup");				options[8] = strdup("Group");
739
			attrs[9]  = strdup("astAgentRecordagentcalls");			options[9] = strdup("Recordagentcalls");
740
			attrs[10] = strdup("astAgentRecordformat");			options[10]= strdup("Recordformat");
741
			attrs[11] = strdup("astAgentCreatelink");			options[11]= strdup("Createlink");
742
			attrs[12] = strdup("astAgentUrlprefix");			options[12]= strdup("Urlprefix");
743
			attrs[13] = strdup("astAgentSavecallsin");			options[13]= strdup("Savecallsin");
744
			attrs[14] = strdup("astAgentCustombeep");			options[14]= strdup("Custom_beep");
745
			/* The agent parameters */
746
			attrs[15] = strdup("astAgentAgentID");				options[15]= strdup("AgentID");
747
			attrs[16] = strdup("astAgentAgentPassword");			options[16]= strdup("AgentPassword");
748
			attrs[17] = strdup("cn");					options[17]= strdup("AgentDiscription");
749
			attrs[18] = NULL;						options[18]= NULL;
750
751
		} else if(!strcmp(file, "meetme.conf")) {
752
			/* fields we wont to get from ldap */
753
			attrs[0] = strdup("astMeetMeGeneralConfig");			options[0] = strdup("objectClass");	// objectClass for the generals
754
			attrs[1] = strdup("astMeetMeContext");				options[1] = strdup("Context");
755
			/* General options */
756
			attrs[2] = strdup("astMeetMeAudiobuffers");			options[2] = strdup("Audiobuffers");
757
			/* MeetMe spezific */
758
			/* The  MeetMe options */
759
			attrs[3] = strdup("astMeetMeConfno");				options[3] = strdup("Confno");		// must value if is it not a emty context
760
			attrs[4] = strdup("astMeetMePincode");				options[4] = strdup("Pincode");
761
			attrs[5] = strdup("astMeetMeAdminpin");				options[5] = strdup("Adminpin");
762
			attrs[6] = NULL;						options[6] = NULL;
763
764
		} else {
765
			ast_log(LOG_WARNING, "LDAP RealTime: Useing of %s not supported!.\n",file);
766
			return NULL;
767
		}
768
		}
769
	}
770
771
	/* generate the query */
772
	snprintf(filter, sizeof(filter), "(|(objectClass=%s)(objectClass=%s))", table, attrs[0]);
773
774
	/* We now have our complete statement; Lets connect to the server and execute it. */
775
	ast_mutex_lock(&ldap_lock);
776
	ldap = ldap_reconnect();
777
	if(!ldap) {
778
		/* free all stuff */
779
		for(i = 0; attrs[i]; i++)
780
			free(attrs[i]);
781
		for(i = 0; options[i]; i++)
782
			free(options[i]);
783
		ast_mutex_unlock(&ldap_lock);
784
		return NULL;
785
	}
786
787
	/* Seting up barrier */
788
	for(i = 0; options[i]; i++)
789
		if(!strcasecmp(options[i], "VoiceboxNr") || !strcasecmp(options[i], "AgentID") || !strcasecmp(options[i], "Confno") || !strcasecmp(options[i], "member")) {
790
			barrier = i;
791
			break;
792
		} 
793
794
	/* Lets get available contexts */
795
	anf = get_config(ldap, ldapbasedn, filter, attrs, !strcmp(file, "queues.conf") ? attrs[barrier] : "");
796
797
	/* Get the context "general" */
798
	if((p = search_context("general", 1))) {
799
		if (!(cat = ast_category_new(p->string[1]))) {
800
			ast_log(LOG_WARNING, "Out of memory!\n");
801
		} else {
802
			ast_verbose("  -- Add context: '%s'\n", p->string[1]);
803
			/* Add the options */
804
			for(i = 2; i < barrier; i++) {
805
				if(strlen(p->string[i])) {
806
					var = ast_variable_new(options[i], p->string[i]);
807
					ast_variable_append(cat, var);
808
					ast_verbose("\t'%s = %s'\n", options[i], p->string[i]);
809
				}
810
			}
811
			/* We not longer need the akt. context */
812
			del_akt_context(p);
813
			/* add the category "general" */
814
			ast_category_append(cfg, cat);
815
			cat = NULL;
816
		}
817
	} else {
818
		ast_log(LOG_WARNING, "LDAP RealTime: Couldn't finde the \"general\" part.\n");
819
	}
820
821
	if(!strcmp(file, "agents.conf") || !strcmp(file, "meetme.conf")) {
822
		if(!strcmp(file, "agents.conf") && (p = search_context("agents", 1))) {
823
			if (!(cat = ast_category_new(p->string[1]))) {
824
				ast_log(LOG_WARNING, "Out of memory!\n");
825
			} else {
826
				ast_verbose("  -- Add context: '%s'\n", p->string[1]);
827
				/* A general config only for agents */
828
				if(strlen(p->string[0])) {
829
					/* Add the options */
830
					for(i = 2; i < barrier; i++) {
831
						if(strlen(p->string[i])) {
832
							var = ast_variable_new(options[i], p->string[i]);
833
							ast_variable_append(cat, var);
834
							ast_verbose("\t'%s = %s'\n", options[i], p->string[i]);
835
						}
836
					}
837
					/* We not longer need the list element */
838
					del_akt_context(p);
839
				}
840
			}
841
		}
842
843
		/* clear all elements we don't need */
844
		p = anf;
845
		while(p) {
846
			if(!strcmp(attrs[0], p->string[0])) {
847
				p = del_akt_context(p);
848
				continue;
849
			}
850
			p = p->next;
851
		}
852
		p = anf;
853
854
		/* Add the contextes "rooms" / "agents" without global options */
855
		if(!cat && p) {
856
			if(!strcmp(file, "meetme.conf")) p->string[1] = strdup("rooms"); else p->string[1] = strdup("agents");
857
			if (!(cat = ast_category_new(p->string[1])))
858
				ast_log(LOG_WARNING, "Out of memory!\n");
859
			else
860
				ast_verbose("  -- Add context: '%s'\n", p->string[1]);
861
		}
862
863
		/* Add the spezific entries */
864
		while(p && cat) {
865
			/* generate values */
866
			var_val = strdup(p->string[barrier]);
867
			for(i=barrier+1; options[i]; i++){
868
				if(strlen(p->string[i]) != 0) {
869
					if (!(var_val = (char *)realloc(var_val, strlen(var_val) + 1 + strlen(p->string[i]) + 1))) {
870
						ast_log(LOG_WARNING, "Out of memory!\n");
871
						continue;
872
					}
873
					var_val = strcat(strcat(var_val, ","), p->string[i]);
874
				} else {
875
					if (!(var_val = (char *)realloc(var_val, strlen(var_val) + 1 + 1))) {
876
						ast_log(LOG_WARNING, "Out of memory!\n");
877
						continue;
878
					}
879
					var_val = strcat(var_val, ",");
880
				}
881
			}
882
			/* add a new entry to the category */
883
			var = ast_variable_new(!strcmp(file, "agents.conf") ? "agent" : "conf", var_val);
884
			ast_variable_append(cat, var);
885
			ast_verbose("\t'%s => %s'\n", !strcmp(file, "agents.conf") ? "agent" : "conf", var_val);
886
			p = p->next;
887
		}
888
		/* add the category "agents/rooms" */
889
		if(cat)
890
			ast_category_append(cfg, cat);
891
892
	} else if(!strcmp(file, "voicemail.conf") && (p = anf)) {
893
		/* clear all elements we don't need */
894
		while(p) {
895
			if(!strcmp(attrs[0], p->string[0])) {
896
				p = del_akt_context(p);
897
				continue;
898
			}
899
			p = p->next;
900
		}
901
902
		/* Add the rest contexts without global options */
903
		if((p = anf)) {
904
			if (!(cat = ast_category_new(p->string[1]))) {
905
				ast_log(LOG_WARNING, "Out of memory!\n");
906
			}
907
			ast_verbose("  -- Add context: '%s'\n", p->string[1]);
908
			old_context = strdup(p->string[1]);
909
		}
910
		while(p) {
911
			if(strcmp(old_context, p->string[1])) {
912
				/* add the category */
913
				ast_category_append(cfg, cat);
914
				if (!(cat = ast_category_new(p->string[1]))) {
915
					ast_log(LOG_WARNING, "Out of memory!\n");
916
					continue;
917
				}
918
				ast_verbose("  -- Add context: '%s'\n", p->string[1]);
919
				old_context = strdup(p->string[1]);
920
			}
921
922
			/* generate the first part of the value */
923
			var_val = strdup( p->string[barrier+1]);
924
			for(i=barrier+2;  p->string[i]; i++)
925
				if(strlen( p->string[i]) == 0) { 
926
					if (!(var_val = (char *)realloc(var_val, strlen(var_val) + 1 + 1))) {
927
						ast_log(LOG_WARNING, "Out of memory!\n");
928
						continue;
929
					}
930
					strcat(var_val, ",");
931
				} else {
932
					if (!(var_val = (char *)realloc(var_val, strlen(var_val) + 1 + strlen( p->string[i]) + 1))) {
933
						ast_log(LOG_WARNING, "Out of memory!\n");
934
						continue;
935
					} 
936
					strcat(strcat(var_val, ","),  p->string[i]);
937
				}
938
			
939
			/* generate the second part of the value */
940
			for(i=2;  i < barrier; i++)
941
				if(strlen( p->string[i]) != 0) {
942
					if (!(var_val = (char *)realloc(var_val, strlen(var_val) + 1 + strlen(options[i]) + 1 + strlen( p->string[i]) + 1))) {
943
						ast_log(LOG_WARNING, "Out of memory!\n");
944
						continue;
945
					}
946
					strcat(strcat(strcat(strcat(var_val, ","), options[i]), "="),  p->string[i]);
947
				}
948
			/* add a new entry to the category */
949
			var = ast_variable_new(p->string[barrier], var_val);
950
			ast_variable_append(cat, var);
951
			ast_verbose("\t'%s => %s'\n", p->string[barrier], var_val);
952
			p = p->next;
953
		}
954
		/* add the category */
955
		if(anf)
956
			ast_category_append(cfg, cat);
957
958
	} else if(!strcmp(file, "queues.conf") && (p = anf)) {
959
		while(p) {
960
			if (!(cat = ast_category_new(p->string[1]))) {
961
				ast_log(LOG_WARNING, "Out of memory!\n");
962
			} else {
963
				ast_verbose("  -- Add context: '%s'\n", p->string[1]);
964
				/* add options */
965
				for(i = 2; p->string[i]; i++) {
966
					if(strlen(p->string[i]) != 0) {
967
						var = ast_variable_new(options[i], p->string[i]);
968
						ast_variable_append(cat, var);
969
						ast_verbose("\t'%s = %s'\n", options[i], p->string[i]);
970
					}
971
				}
972
973
				/* Add QueueMembers */
974
				for(i = 0; p->members[i]; i++) {
975
					var = ast_variable_new(options[barrier], p->members[i]);
976
					ast_variable_append(cat, var);
977
					ast_verbose("\t'%s = %s'\n", options[barrier], p->members[i]);
978
				}
979
			}
980
			/* add the category */
981
			ast_category_append(cfg, cat);
982
			p = p->next;
983
		}
984
	}
985
986
	/* free all stuff */
987
	rm_context();
988
	for(i = 0; attrs[i]; i++)
989
		free(attrs[i]);
990
	for(i = 0; options[i]; i++)
991
		free(options[i]);
992
	free(var_val);
993
	free(old_context);
994
	ldap_disconnect(ldap);
995
	ast_mutex_unlock(&ldap_lock);
996
997
	return cfg;
998
}
999
1000
static struct ast_config_engine ldap_engine = {
1001
	.name = "ldap",
1002
	.load_func = config_ldap,
1003
	.realtime_func = realtime_ldap,
1004
	.realtime_multi_func = realtime_multi_ldap,
1005
	.update_func = update_ldap
1006
};
1007
1008
int load_module (void)
1009
{
1010
	parse_config();
1011
1012
	if(!ldap_reconnect()) {
1013
		ast_log(LOG_WARNING, "LDAP RealTime: Couldn't establish connection. Check debug.\n");
1014
		ast_log(LOG_DEBUG, "LDAP RealTime: Cannot Connect\n");
1015
	}
1016
1017
	ast_config_engine_register(&ldap_engine);
1018
	if(option_verbose) {
1019
		ast_verbose("LDAP RealTime driver loaded.\n");
1020
	}
1021
	ast_cli_register(&cli_realtime_ldap_status);
1022
1023
	return 0;
1024
}
1025
1026
int unload_module (void)
1027
{
1028
	/* Aquire control before doing anything to the module itself. */
1029
	ast_mutex_lock(&ldap_lock);
1030
1031
	ast_cli_unregister(&cli_realtime_ldap_status);
1032
	ast_config_engine_deregister(&ldap_engine);
1033
	if(option_verbose) {
1034
		ast_verbose("LDAP RealTime unloaded.\n");
1035
	}
1036
1037
	STANDARD_HANGUP_LOCALUSERS;
1038
1039
	/* Unlock so something else can destroy the lock. */
1040
	ast_mutex_unlock(&ldap_lock);
1041
1042
	return 0;
1043
}
1044
1045
int reload (void)
1046
{
1047
	/* Aquire control before doing anything to the module itself. */
1048
	ast_mutex_lock(&ldap_lock);
1049
1050
	connected = 0;
1051
	parse_config();
1052
1053
	/* Need to unlock so that ldap_reconnect can regain the lock. */
1054
	ast_mutex_unlock(&ldap_lock);
1055
1056
	if(!ldap_reconnect()) {
1057
		ast_log(LOG_WARNING, "LDAP RealTime: Couldn't establish connection. Check debug.\n");
1058
		ast_log(LOG_DEBUG, "LDAP RealTime: Cannot Connect\n");
1059
	}
1060
1061
	ast_verbose(VERBOSE_PREFIX_2 "LDAP RealTime reloaded.\n");
1062
1063
	return 0;
1064
}
1065
1066
int parse_config (void)
1067
{
1068
	struct ast_config *config;
1069
	char *s;
1070
1071
	config = ast_config_load(RES_CONFIG_LDAP_CONF);
1072
1073
	if(config) {
1074
		if(!(s=ast_variable_retrieve(config, "general", "ldapuser"))) {
1075
			ast_log(LOG_WARNING, "LDAP RealTime: No database user found, using 'asterisk' as default.\n");
1076
			strncpy(ldapuser, "asterisk", sizeof(ldapuser) - 1);
1077
		} else {
1078
			strncpy(ldapuser, s, sizeof(ldapuser) - 1);
1079
		}
1080
1081
		if(!(s=ast_variable_retrieve(config, "general", "ldappass"))) {
1082
                        ast_log(LOG_WARNING, "LDAP RealTime: No database password found, using 'asterisk' as default.\n");
1083
                        strncpy(ldappass, "asterisk", sizeof(ldappass) - 1);
1084
                } else {
1085
                        strncpy(ldappass, s, sizeof(ldappass) - 1);
1086
                }
1087
1088
		if(!(s=ast_variable_retrieve(config, "general", "ldapuri"))) {
1089
                        ast_log(LOG_WARNING, "LDAP RealTime: No database host found, using localhost via socket.\n");
1090
			strncpy(ldapuri, "ldap://localhost", sizeof(ldapuri) - 1);
1091
                } else {
1092
                        strncpy(ldapuri, s, sizeof(ldapuri) - 1);
1093
                }
1094
1095
		if(!(s=ast_variable_retrieve(config, "general", "ldapbasedn"))) {
1096
                        ast_log(LOG_WARNING, "LDAP RealTime: No base dn found, using 'asterisk' as default.\n");
1097
			strncpy(ldapbasedn, "asterisk", sizeof(ldapbasedn) - 1);
1098
                } else {
1099
                        strncpy(ldapbasedn, s, sizeof(ldapbasedn) - 1);
1100
                }
1101
	}
1102
	ast_config_destroy(config);
1103
1104
	ast_log(LOG_WARNING, "LDAP RealTime Host: %s\n", ldapuri);
1105
	ast_log(LOG_WARNING, "LDAP RealTime User: %s\n", ldapuser);
1106
	ast_log(LOG_WARNING, "LDAP RealTime Base DN: %s\n", ldapbasedn);
1107
1108
	return 1;
1109
}
1110
1111
char *description (void)
1112
{
1113
	return res_config_ldap_desc;
1114
}
1115
1116
int usecount (void)
1117
{
1118
	/* Try and get a lock. If unsuccessful, than that means another thread is using the ldap object. */
1119
	if(ast_mutex_trylock(&ldap_lock)) {
1120
		ast_log(LOG_DEBUG, "LDAP RealTime: Module usage count is 1.\n");
1121
		return 1;
1122
	}
1123
	ast_mutex_unlock(&ldap_lock);
1124
	return 0;
1125
}
1126
1127
char *key ()
1128
{
1129
	return ASTERISK_GPL_KEY;
1130
}
1131
1132
void ldap_disconnect(LDAP *ldap) 
1133
{
1134
1135
	ldap_unbind_s(ldap);
1136
}
1137
1138
static LDAP *ldap_reconnect()
1139
{
1140
	int ver = LDAP_VERSION3;
1141
	int deref = LDAP_DEREF_ALWAYS;
1142
	int ldap_err;
1143
	LDAP *ldap;
1144
	
1145
	ast_mutex_lock(&ldap_lock);
1146
1147
	//if(!connected) {
1148
		if(strlen(ldapuri) && strlen(ldapuser) && strlen(ldappass) && strlen(ldapbasedn)) {
1149
			ldap_err = ldap_initialize(&ldap, ldapuri);
1150
			if(ldap_err != LDAP_SUCCESS || !ldap) {
1151
				ast_log(LOG_WARNING, "LDAP connection failed (host=%s)!\n", ldapuri);
1152
				connected = 0;
1153
				ast_mutex_unlock(&ldap_lock);
1154
				return NULL;
1155
			}
1156
			ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ver);
1157
			ldap_err = ldap_simple_bind_s(ldap, ldapuser, ldappass);
1158
			if(ldap_err == LDAP_SUCCESS) {
1159
				ast_log(LOG_WARNING, "LDAP RealTime: Successfully connected to LDAP.\n");
1160
				connected = 1;
1161
				connect_time = time(NULL);
1162
				ast_mutex_unlock(&ldap_lock);
1163
				errorcount = 0;
1164
				return ldap;
1165
			} else if(ldap_err == LDAP_PROTOCOL_ERROR) {
1166
				if(ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ver) == -1 ||
1167
					ldap_set_option(ldap, LDAP_OPT_DEREF, &deref) == -1) {
1168
					ast_log(LOG_ERROR, "LDAP RealTime: Failed to connect LDAP server %s on %s. Check debug for more info.\n", ldapbasedn, ldapuri);
1169
					ast_log(LOG_DEBUG, "LDAP RealTime: Cannot Connect: %s\n", ldap_err2string(ldap_err));
1170
					connected = 0;
1171
					ast_mutex_unlock(&ldap_lock);
1172
					return NULL;
1173
				} else {
1174
					ast_log(LOG_DEBUG, "LDAP RealTime: Using LDAP_VERSION3 but successfully connected to LDAP.\n");
1175
					connected = 1;
1176
					errorcount = 0;
1177
					connect_time = time(NULL);
1178
					ast_mutex_unlock(&ldap_lock);
1179
					return ldap;
1180
				}
1181
			} else {
1182
				ast_log(LOG_ERROR, "LDAP failed to bind (host=%s, user=%s %s %d)!\n",ldapuri, ldapuser, ldap_err2string(ldap_err), errorcount);
1183
				ldap_unbind(ldap);
1184
				errorcount++;
1185
				ast_mutex_unlock(&ldap_lock);
1186
				if ( errorcount < 3 ) {
1187
					usleep(50000);
1188
					return ldap_reconnect();
1189
				}
1190
				return NULL;
1191
			}
1192
1193
		} else {
1194
			ast_log(LOG_ERROR, "LDAP RealTime: Not all Parameters of \"res_ldap.conf\" are set!\n");
1195
			connected = 0;
1196
			ast_mutex_unlock(&ldap_lock);
1197
			free(ldap);
1198
			return NULL;
1199
		}
1200
1201
	/*} else {
1202
		ldap_err = ldap_simple_bind_s(ldap, ldapuser, ldappass);
1203
		if(ldap_err != LDAP_SUCCESS) {
1204
			connected = 0;
1205
			ast_log(LOG_ERROR, "LDAP RealTime: Server Error: %s\n", ldap_err2string(ldap_err));
1206
			ast_mutex_unlock(&ldap_lock);
1207
			return 0;
1208
		}
1209
1210
		connected = 1;
1211
1212
		ast_log(LOG_WARNING, "LDAP RealTime: Everything is fine.\n");
1213
		ast_mutex_unlock(&ldap_lock);
1214
		return 1;
1215
	}*/
1216
}
1217
1218
static int realtime_ldap_status(int fd, int argc, char **argv)
1219
{
1220
	char status[256], status2[100] = "";
1221
	int ctime = time(NULL) - connect_time;
1222
1223
	if(ldap_reconnect()) {
1224
		if ( ldapuri && ldapbasedn ) {
1225
			snprintf(status, 255, "Connected to %s base dn=%s", ldapuri, ldapbasedn);
1226
		}
1227
1228
		if(ldapuser && *ldapuser) {
1229
			snprintf(status2, 99, " with username %s", ldapuser);
1230
		}
1231
1232
		if (ctime > 31536000) {
1233
			ast_cli(fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 31536000, (ctime % 31536000) / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
1234
		} else if (ctime > 86400) {
1235
			ast_cli(fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
1236
		} else if (ctime > 3600) {
1237
			ast_cli(fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 3600, (ctime % 3600) / 60, ctime % 60);
1238
		} else if (ctime > 60) {
1239
			ast_cli(fd, "%s%s for %d minutes, %d seconds.\n", status, status2, ctime / 60, ctime % 60);
1240
		} else {
1241
			ast_cli(fd, "%s%s for %d seconds.\n", status, status2, ctime);
1242
		}
1243
1244
		return RESULT_SUCCESS;
1245
	} else {
1246
		return RESULT_FAILURE;
1247
	}
1248
}

Return to bug 183095