Project

General

Profile

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