Project

General

Profile

Feature #1936 » mod_lvhost.c

hazzadous, 2009-03-16 14:54

 
1
/*
2
 *
3
 * mod_lvhost.c
4
 * Copyright (c) 2008, Stephane Camberlin
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions 
9
 * are met:
10
 *
11
 * - Redistributions of source code must retain the above copyright notice, 
12
 *   this list of conditions and the following disclaimer.
13
 *
14
 * - Redistributions in binary form must reproduce the above copyright 
15
 *   notice, this list of conditions and the following disclaimer in the 
16
 *   documentation and/or other materials provided with the distribution.
17
 *
18
 * - Neither the name of the 'incremental' nor the names of its 
19
 *   contributors may be used to endorse or promote products derived 
20
 *   from this software without specific prior written permission.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
23
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
24
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
25
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
26
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
27
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (
28
 * INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
31
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33
 * THE POSSIBILITY OF SUCH DAMAGE.
34
 *
35
 */
36

    
37
#include <ctype.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <errno.h>
41
#include <time.h>
42
#include <assert.h>
43

    
44
#include "base.h"
45
#include "log.h"
46
#include "buffer.h"
47
#include "stat_cache.h"
48

    
49
#include "plugin.h"
50

    
51
#ifdef HAVE_CONFIG_H
52
#include "config.h"
53
#endif
54

    
55
#include <ldap.h>
56
#include <lber.h>
57

    
58
#define DEBUG 2
59
#define CACHE_LIFETIME 60
60

    
61
#define PATCH_OPTION(x) \
62
        p->conf.x = s->x;
63

    
64
/** 
65
 * Common lvhost related data.
66
 * 
67
 * Configuration shared by all handled requests within a config_context.
68
 */
69
typedef struct
70
{
71
	LDAP	*ldap_c;	/** LDAP session handle used for all queries. */
72
	buffer	*ldap_uri;	/** URI in form that openldap library expects it. */
73
	unsigned short	ldap_starttls;
74
	buffer	*sasl_user;	/** SASL auth user ( = authz user). */
75
	buffer	*sasl_pass;	
76
	buffer	*sasl_realm;
77
	buffer	*sasl_mech;
78
	buffer	*ldap_binddn;	/** If set, use simple binds. */
79
	buffer	*ldap_password;	/** Simple bind password. */
80
	buffer	*ldap_base;		/** The search root.  Scope is sub */
81

    
82
	/** The filter used to search for document root,
83
	 *  given an input of server name.  
84
	 *  Default: (&(objectClass=vhost)(serverName=?))
85
	 */
86
	buffer	*ldap_filter;
87

    
88
	/** The attribute representing docroot.
89
	 *  Default: documentRoot
90
	 */
91
	buffer	*ldap_attribute;
92

    
93
	unsigned short ldap_persist;	/** If use, use refreshAndPersist */
94
  
95
	buffer	*ldap_pre;
96
	buffer	*ldap_post;
97
  
98
	int		free_me;
99

    
100
} lvhost_plugin_config;
101

    
102
/* cache struct.  Maybe use lightys arrays later */
103
typedef struct {
104

    
105
	buffer* server_name;
106
	buffer* docroot;
107
	time_t birth;
108

    
109
} doc_cache_t;
110

    
111
typedef struct {
112

    
113
	PLUGIN_DATA;
114
  
115
	buffer  *docroot;
116
	buffer  *tmp_buf;
117
	doc_cache_t **doc_cache;
118
	unsigned int cache_size;
119

    
120
	lvhost_plugin_config **config_storage;
121
	lvhost_plugin_config conf;
122

    
123
} plugin_data;
124

    
125
INIT_FUNC(mod_lvhost_init) {
126

    
127
	plugin_data *p;
128

    
129
	p = (plugin_data*)malloc( sizeof(*p) );
130

    
131
	if( p )
132
	{
133
		p->tmp_buf = buffer_init();
134
		p->docroot = buffer_init();
135
		p->doc_cache = malloc( 0 );
136
		p->cache_size = 0;
137
	}
138

    
139
	return p;
140
}
141

    
142
FREE_FUNC(mod_lvhost_cleanup) {
143

    
144
	plugin_data *p = p_d;
145

    
146
	UNUSED(srv);
147

    
148
	if (!p) return HANDLER_GO_ON;
149

    
150
	if (p->config_storage) {
151
    
152
		size_t i, j;
153

    
154
		for (i = 0; i < srv->config_context->used; i++)
155
		{  
156
			lvhost_plugin_config *s = p->config_storage[i];
157
      
158
			if (!s) continue;
159
 
160
			if (s->free_me) ldap_unbind_ext(s->ldap_c, NULL, NULL);
161

    
162
	        /* Free all the buffers for this config_context */
163
    	    buffer *bufs[] = {	s->ldap_uri,		s->sasl_user,
164
								s->sasl_pass,		s->sasl_mech,
165
								s->sasl_realm,		s->ldap_binddn,
166
            	                s->ldap_password,	s->ldap_base,
167
								s->ldap_filter,		s->ldap_attribute,
168
								s->ldap_pre,		s->ldap_post };
169

    
170
			for(j = 0; j * sizeof(buffer*) < sizeof(bufs); j++)
171
				buffer_free(bufs[j]);
172
	      
173
			free(s);
174
		} 
175
	      
176
		free(p->config_storage);
177
	}
178

    
179
	buffer_free(p->docroot);
180
	free(p->doc_cache);
181

    
182
	free(p);
183

    
184
	return HANDLER_GO_ON;
185
}
186

    
187
SETDEFAULTS_FUNC(mod_lvhost_set_defaults) {
188

    
189
	plugin_data *p = p_d;
190
  
191
	size_t i, j, k;
192
	int err;
193
  
194
	struct berval cred;
195

    
196
	int ldap_version = LDAP_VERSION3;
197

    
198
	/* 
199
	 * List of config values to be read from the lighttpd configfile.
200
	 * Format is { confstring, destination memory, type, scope }
201
	 * Please place T_CONFIG_STRINGs at top.
202
	 */
203
	config_values_t cv[] = {
204
  
205
		{ "lvhost.uri",				NULL,
206
									T_CONFIG_STRING,
207
									T_CONFIG_SCOPE_SERVER },
208

    
209
		{ "lvhost.sasl_mech",		NULL,
210
									T_CONFIG_STRING, 
211
									T_CONFIG_SCOPE_SERVER },
212

    
213
	 	{ "lvhost.sasl_user",		NULL,
214
									T_CONFIG_STRING, 
215
									T_CONFIG_SCOPE_SERVER },
216

    
217
		{ "lvhost.sasl_realm",		NULL,
218
									T_CONFIG_STRING,
219
									T_CONFIG_SCOPE_SERVER },
220

    
221
	    { "lvhost.sasl_pass",		NULL,
222
    	                            T_CONFIG_STRING,
223
        	                        T_CONFIG_SCOPE_SERVER },
224

    
225
		{ "lvhost.binddn",			NULL,
226
									T_CONFIG_STRING,
227
									T_CONFIG_SCOPE_SERVER },
228

    
229
		{ "lvhost.password",		NULL,
230
									T_CONFIG_STRING,
231
									T_CONFIG_SCOPE_SERVER },
232

    
233
		{ "lvhost.base",			NULL,
234
									T_CONFIG_STRING,
235
									T_CONFIG_SCOPE_SERVER },
236

    
237
		{ "lvhost.filter",			NULL,
238
									T_CONFIG_STRING,
239
									T_CONFIG_SCOPE_SERVER },
240

    
241
		{ "lvhost.attribute",		NULL,
242
									T_CONFIG_STRING,
243
									T_CONFIG_SCOPE_SERVER },
244

    
245
        { "lvhost.starttls",        NULL,
246
                                    T_CONFIG_BOOLEAN,
247
                                    T_CONFIG_SCOPE_SERVER },
248

    
249
		{ "lvhost.persistent",		NULL,
250
									T_CONFIG_BOOLEAN,
251
									T_CONFIG_SCOPE_SERVER },
252

    
253
		{ NULL,						NULL,
254
									T_CONFIG_UNSET,
255
									T_CONFIG_SCOPE_UNSET }
256

    
257
	};
258
  
259
	if ( !p ) return HANDLER_ERROR;
260
  
261
	/* 
262
	 * Allocate memory for pointers to instances of lvhost_plugin_config
263
	 * that will be created one per config_context.
264
	 */
265
	p->config_storage = 
266
			(lvhost_plugin_config**)malloc(	srv->config_context->used
267
											* sizeof(lvhost_plugin_config*) );
268

    
269
	if( !(p->config_storage) ) return HANDLER_ERROR;
270

    
271
	/*
272
	 * If we managed to allocate space for the config points,
273
	 * continue with initiate these pointers.
274
	 */
275
	for (i = 0; i < srv->config_context->used; i++)
276
	{
277
		buffer *myfilter = buffer_init();
278
		char *qmark = 0;
279
 
280
		/* The lvhost plugin config for the i-th config_context */
281

    
282
		lvhost_plugin_config *s;
283
		s = (lvhost_plugin_config *)malloc( sizeof(*s) );
284
		if( !s ) return HANDLER_ERROR;
285

    
286
		/* Initialize all the buffers for this config_context */
287
		buffer **bufs[] = {	&s->ldap_uri, 		&s->sasl_mech, 	&s->sasl_user,
288
							&s->sasl_realm,		&s->sasl_pass, 	&s->ldap_binddn,
289
							&s->ldap_password,	&s->ldap_base,	&s->ldap_filter,
290
							&s->ldap_attribute };
291

    
292
		/* Init these separately */
293
		s->ldap_pre = buffer_init();
294
		s->ldap_post = buffer_init();
295

    
296
		for(j = 0; j * sizeof(buffer**) < sizeof(bufs); j++)
297
		{
298
#if DEBUG==2
299
			log_error_write(	srv, __FILE__, __LINE__, "ss",
300
								"Initializing buffer for", cv[j].key );
301
#endif
302
			*bufs[j] = buffer_init();
303
		}
304

    
305
		/*
306
		 * Point the destinations of cv to our config storage to
307
		 * be filled by config_insert_values_global.  dests must be the same
308
		 * order as they are in cv, so make sure bufs and bools are correct
309
		 */
310
		unsigned short *bools[] = { &s->ldap_starttls, &s->ldap_persist };
311
		void** dests = (void**)malloc( sizeof(bufs) + sizeof(bools) );
312
		if(!dests) return HANDLER_ERROR;
313

    
314
		/* Append bools to the buffers */
315
		for(j = 0; j * sizeof(buffer**) < sizeof(bufs); j++)
316
			dests[j] = *bufs[j];
317
		memcpy(	dests + j, bools, sizeof(bools) );
318

    
319
		/* nDests should be the same as the length of cv - 1 */
320
		size_t nDests = sizeof(cv) / sizeof(config_values_t) - 1;
321
		assert( (nDests * sizeof(void*)) == (sizeof(bools) + sizeof(bufs)) );
322

    
323
		for(j = 0; cv[j].key; j++)
324
		{
325
#if DEBUG==2
326
			log_error_write(	srv, __FILE__, __LINE__, "ss",
327
								"Setting destination for", cv[j].key );
328
#endif
329
			assert( dests[j] );
330
			cv[j].destination = dests[j];
331
		}
332

    
333
		p->config_storage[i] = s;
334

    
335
		if (config_insert_values_global(srv, 
336
				((data_config *)srv->config_context->data[i])->value, cv))
337
		{
338
			return HANDLER_ERROR;
339
		}
340

    
341
#if DEBUG
342
		/* Print what we got from lighttpd config. */
343
		for(j = 0; cv[j].key; j++)
344
		{
345
			switch( cv[j].type )
346
			{
347
				case T_CONFIG_STRING:
348
					log_error_write(	srv, __FILE__, __LINE__, "ssb",
349
										"lvhost config: ", cv[j].key, 
350
										(buffer*)dests[j] 				);
351
					break;
352

    
353
				case T_CONFIG_BOOLEAN:
354
					log_error_write(	srv, __FILE__, __LINE__, "ssd",
355
										"lvhost config: ", cv[j].key,
356
										*((unsigned short*)cv[j].destination) );
357
					break;
358
			default:
359
					log_error_write(	srv, __FILE__, __LINE__, "ssd",
360
										"lvhost config: ", cv[j].key,
361
										*((int*)cv[j].destination)		);
362
			};
363
		}
364
#endif /* DEBUG */
365

    
366
		/*
367
		 * Initiate default values for certain buffers
368
		 */
369

    
370
		/**
371
		 * Structure containing a buffer - stringi default pairing
372
		 */
373
		typedef struct { buffer* b; const char* d; } buffer_default_t;
374
		buffer_default_t defaults[] = 
375
			{
376
				{ s->ldap_filter,		"(&(objectClass=vhost)(serverName=?))" 	},
377
				{ s->ldap_attribute,	"documentRoot"							},
378
				{ s->sasl_mech,			"PLAIN"									}
379
			};
380

    
381
		for(j = 0; j * sizeof(buffer_default_t) < sizeof(defaults); j++)
382
			if( buffer_is_empty(defaults[j].b) )
383
				buffer_copy_string( defaults[j].b, defaults[j].d );
384

    
385
		/*
386
		 * Check that we have none empty buffers on
387
		 * the following variables.
388
		 */
389
		buffer* required_buffers[] = { 	s->ldap_uri, s->ldap_base,
390
										s->ldap_filter, s->ldap_attribute };
391

    
392
		for(j = 0; j * sizeof(buffer*) < sizeof(required_buffers); j++)
393
		{
394
			/* Get the index of required_buffers, as seen in cv */
395
			for( k = 0; k < nDests; k++ )
396
				if( required_buffers[j] == dests[k] ) break;
397

    
398
			/* Should have gotten a match */
399
			assert( k < nDests );
400

    
401
			if( buffer_is_empty(required_buffers[j]) )
402
			{
403
				log_error_write(	srv, __FILE__, __LINE__, "ss", 
404
									"Missing required option:", cv[k].key );
405
				/* TODO: readd this line maybe
406
				 * I don't seem to understand config_contexts 
407
				 * yet to leave this out
408
				 * return HANDLER_ERROR;
409
				 */
410

    
411
				return HANDLER_GO_ON;
412
			}
413
		}
414

    
415
		/*
416
		 * Next we split the ldap_filter string in two
417
		 * at the contained question mark if it has one,
418
		 * and put the two halfs in ldap_pre and ldap_post maybe
419
		 */
420
		buffer_copy_string_buffer(myfilter, s->ldap_filter);
421

    
422
		if( (qmark = index(myfilter->ptr, '?')) )
423
		{
424
			*qmark = '\0';
425
			buffer_copy_string(s->ldap_pre, myfilter->ptr);
426
			buffer_copy_string(s->ldap_post, qmark+1);
427
		}
428
		else
429
		{
430
			buffer_copy_string_buffer(s->ldap_pre, myfilter);
431
		}
432
    
433
		buffer_free(myfilter);
434
 
435
		s->free_me = 0;
436

    
437
		/*
438
		 * Now we setup the ldap session to be referenced by ldap_c
439
		 */
440
		if ((err = ldap_initialize( &s->ldap_c,
441
									s->ldap_uri->ptr )) != LDAP_SUCCESS) {
442
			log_error_write(	srv, __FILE__, __LINE__, "ss", 
443
								"ldap_initialize() failed, exiting... :", 
444
								ldap_err2string(err)						);
445
			return HANDLER_ERROR;
446
		}
447
    
448
		s->free_me = 1;
449

    
450
		ldap_set_option( s->ldap_c, LDAP_OPT_PROTOCOL_VERSION, &ldap_version );
451

    
452
		/*
453
		 * If binddn was given, assume we want  a simple bind.
454
		 * For now let us perform all ldap operations syncronously.
455
		 */
456
		if( !buffer_is_empty(s->ldap_binddn) )
457
		{
458
	        if ((err = ldap_simple_bind_s(  s->ldap_c,
459
    	                                    s->ldap_binddn->ptr,
460
			                                s->ldap_password->ptr)) != LDAP_SUCCESS)
461
			{
462
        	    log_error_write(    srv, __FILE__, __LINE__, "ss",
463
	                                "ldap_simple_bind_s() failed, exiting... :",
464
    	                            ldap_err2string(err)                        );
465
        	    return HANDLER_ERROR;
466
			}
467

    
468
			/* We were successful.  No need to do anything else */
469
			return HANDLER_GO_ON;
470
		}
471

    
472
		if( !buffer_is_empty(s->sasl_pass) )
473
		{
474
			cred.bv_val = strdup(s->sasl_pass->ptr);
475
			cred.bv_len = strlen(s->sasl_pass->ptr);
476
		} else {
477
			cred.bv_val = NULL;
478
			cred.bv_len = 0;
479
		}
480
  
481
		if ((err = ldap_sasl_bind_s(	s->ldap_c, 
482
										s->sasl_user->ptr,
483
										s->sasl_mech->ptr,
484
										&cred, NULL, NULL, NULL	)) != LDAP_SUCCESS)
485
		{
486
			log_error_write(	srv, __FILE__, __LINE__, "ss", 
487
								"ldap_sasl_bind_s() failed, exiting... :", 
488
								ldap_err2string(err)						);
489
			return HANDLER_ERROR;
490
		}
491
	}
492

    
493
	return HANDLER_GO_ON;
494
}
495

    
496
static int mod_lvhost_patch_connection(	server *srv, 
497
										connection *con, 
498
										plugin_data *p	)
499
{
500
	size_t i;
501
	lvhost_plugin_config *s = p->config_storage[0];
502

    
503
	PATCH_OPTION(ldap_base);
504
	PATCH_OPTION(ldap_attribute);
505
	PATCH_OPTION(ldap_pre);
506
	PATCH_OPTION(ldap_post);
507
	PATCH_OPTION(ldap_c);
508

    
509
	for (i = 1; i < srv->config_context->used; i++)
510
	{
511
		data_config *dc = (data_config *)srv->config_context->data[i];
512
		s = p->config_storage[i];
513

    
514
		if (!config_check_cond(srv, con, dc)) continue;
515

    
516
		PATCH_OPTION(ldap_base);
517
		PATCH_OPTION(ldap_attribute);
518
		PATCH_OPTION(ldap_pre);
519
		PATCH_OPTION(ldap_post);
520
		PATCH_OPTION(ldap_c);
521
	}
522

    
523
	return 0;
524
}
525

    
526
CONNECTION_FUNC(mod_lvhost_handle_docroot)
527
{
528
	plugin_data *p = p_d;
529

    
530
	int n;
531
	size_t i;
532
  
533
	LDAPMessage *msg, *entry;
534
	struct berval **vals;
535
	int ldap_scope = LDAP_SCOPE_SUBTREE;
536

    
537
	/* Fold if no host specified */
538
	if (!con->uri.authority->used)
539
	{
540
		log_error_write(	srv, __FILE__, __LINE__, 
541
							"s", "Exiting: no host header."	);
542
		return HANDLER_GO_ON;
543
	}
544

    
545
	/* Find the requested server name in cache */
546
	doc_cache_t *cache_entry = 0;
547

    
548
#ifdef DEBUG
549
	log_error_write( 	srv, __FILE__, __LINE__, "sd",
550
						"Checking cache of size", p->cache_size );
551
#endif
552

    
553
	for(i = 0; i < p->cache_size; i++)
554
	{
555
		if(buffer_is_equal(p->doc_cache[i]->server_name, con->uri.authority))
556
		{
557
			cache_entry = p->doc_cache[i];
558
			break;
559
		}
560
	}
561

    
562
	if( cache_entry && ( (time(0) - cache_entry->birth ) < CACHE_LIFETIME ) )
563
	{
564
		log_error_write(	srv, __FILE__, __LINE__, "sb", 
565
							"Using cache for", cache_entry->server_name	);
566
        buffer_copy_string_buffer(con->server_name, cache_entry->server_name);
567
        buffer_copy_string_buffer(con->physical.doc_root, cache_entry->docroot);
568
		return HANDLER_GO_ON;
569
	}
570

    
571
	mod_lvhost_patch_connection(srv, con, p);
572

    
573
	/* Perhaps ldap_c has become invalid?  Create a new session? */
574
	if (!p->conf.ldap_c)
575
	{
576
		log_error_write(	srv, __FILE__, __LINE__, "s", 
577
							"Exiting: no ldap handler..."	);
578
		return HANDLER_GO_ON;
579
	}
580
  
581
	buffer_copy_string_buffer(p->tmp_buf, p->conf.ldap_pre);
582
  
583
	if (p->conf.ldap_post->used)
584
	{
585
		buffer_append_string_buffer(p->tmp_buf, con->uri.authority);
586
		buffer_append_string_buffer(p->tmp_buf, p->conf.ldap_post);
587
	}
588

    
589
	if (ldap_search_ext_s(	p->conf.ldap_c, p->conf.ldap_base->ptr,
590
							ldap_scope,	p->tmp_buf->ptr, NULL,
591
							0, NULL, NULL, NULL, 0, &msg	) != LDAP_SUCCESS)
592
	{
593
		log_error_write(	srv, __FILE__, __LINE__, "sb", 
594
							"Exiting: ldap_search_ext_s failed:", p->tmp_buf);
595
		return HANDLER_GO_ON;
596
	}
597

    
598
	n = ldap_count_entries(p->conf.ldap_c, msg);
599

    
600
	if (n!=1)
601
	{
602
		log_error_write(	srv, __FILE__, __LINE__, "sbs", 
603
							"Duplicate entry for filter:", p->tmp_buf,
604
							": Just using the first"					);
605
	}
606

    
607
	entry = ldap_first_entry(p->conf.ldap_c, msg);
608

    
609
	vals = ldap_get_values_len(	p->conf.ldap_c, entry, 
610
								p->conf.ldap_attribute->ptr );
611

    
612
	if( vals )
613
	{
614
		stat_cache_entry *sce;
615
		buffer_copy_string(p->docroot, vals[0]->bv_val);
616

    
617
		if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->docroot, &sce))
618
		{
619
			log_error_write(	srv, __FILE__, __LINE__, "sb", 
620
								strerror(errno), p->docroot		);
621
			return HANDLER_GO_ON;
622
		}
623

    
624
		if (!S_ISDIR(sce->st.st_mode))
625
		{
626
			log_error_write(	srv, __FILE__, __LINE__, "sb", 
627
								"Not a directory", p->docroot	);
628
	    	return HANDLER_GO_ON;
629
		}
630

    
631

    
632
		if( !cache_entry )
633
		{
634
			cache_entry = malloc( sizeof(doc_cache_t) );
635
			if(!cache_entry) return HANDLER_ERROR;
636

    
637
			cache_entry->server_name = buffer_init();
638
			cache_entry->docroot = buffer_init();
639

    
640
			buffer_copy_string_buffer( 	cache_entry->server_name, 
641
										con->uri.authority );
642

    
643
			p->doc_cache = realloc( p->doc_cache, 
644
									(p->cache_size + 1) * sizeof(doc_cache_t*) );
645

    
646
			if(!p->doc_cache) return HANDLER_ERROR;
647

    
648
			p->doc_cache[p->cache_size] = cache_entry;
649
			p->cache_size = p->cache_size + 1;
650

    
651
#ifdef DEBUG
652
			log_error_write( 	srv, __FILE__, __LINE__, "sd", 
653
								"Adding doc root to cache, new size:", 
654
								p->cache_size							);
655
#endif
656

    
657
		}
658

    
659
		cache_entry->birth = time(0);
660
		buffer_copy_string_buffer(cache_entry->docroot, p->docroot);
661

    
662
		buffer_copy_string_buffer(con->server_name, con->uri.authority);
663
		buffer_copy_string_buffer(con->physical.doc_root, p->docroot);
664

    
665
#ifdef DEBUG
666
        log_error_write(    srv, __FILE__, __LINE__, "sb",
667
                            "Server name:", con->server_name    );
668
		log_error_write(	srv, __FILE__, __LINE__, "sb", 
669
							"Document root:", con->physical.doc_root	);
670
#endif
671

    
672
	}
673
  
674

    
675
	ldap_value_free_len(vals);
676
	ldap_msgfree(msg);
677

    
678
	return HANDLER_GO_ON;
679
}
680

    
681
int mod_lvhost_plugin_init(plugin *p) {
682

    
683
	p->version                  = LIGHTTPD_VERSION_ID;
684
	p->name                     = buffer_init_string("lvhost");
685
	p->init                     = mod_lvhost_init;
686
	p->cleanup                  = mod_lvhost_cleanup;
687
	p->set_defaults             = mod_lvhost_set_defaults;
688
	p->handle_docroot           = mod_lvhost_handle_docroot;
689

    
690
	p->data                     = NULL;
691

    
692
	return 0;
693

    
694
}
695

    
(1-1/2)