]> granicus.if.org Git - apache/blob - server/vhost.c
Fix wrong condition that may lead to NULL being set as 'Vary' header
[apache] / server / vhost.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * @file  vhost.c
19  * @brief functions pertaining to virtual host addresses
20  *        (configuration and run-time)
21  */
22
23 #include "apr.h"
24 #include "apr_strings.h"
25 #include "apr_lib.h"
26
27 #define APR_WANT_STRFUNC
28 #include "apr_want.h"
29
30 #include "ap_config.h"
31 #include "httpd.h"
32 #include "http_config.h"
33 #include "http_log.h"
34 #include "http_vhost.h"
35 #include "http_protocol.h"
36 #include "http_core.h"
37
38 #if APR_HAVE_ARPA_INET_H
39 #include <arpa/inet.h>
40 #endif
41
42 APLOG_USE_MODULE(core);
43
44 /*
45  * After all the definitions there's an explanation of how it's all put
46  * together.
47  */
48
49 /* meta-list of name-vhosts.  Each server_rec can be in possibly multiple
50  * lists of name-vhosts.
51  */
52 typedef struct name_chain name_chain;
53 struct name_chain {
54     name_chain *next;
55     server_addr_rec *sar;       /* the record causing it to be in
56                                  * this chain (needed for port comparisons) */
57     server_rec *server;         /* the server to use on a match */
58 };
59
60 /* meta-list of ip addresses.  Each server_rec can be in possibly multiple
61  * hash chains since it can have multiple ips.
62  */
63 typedef struct ipaddr_chain ipaddr_chain;
64 struct ipaddr_chain {
65     ipaddr_chain *next;
66     server_addr_rec *sar;       /* the record causing it to be in
67                                  * this chain (need for both ip addr and port
68                                  * comparisons) */
69     server_rec *server;         /* the server to use if this matches */
70     name_chain *names;          /* if non-NULL then a list of name-vhosts
71                                  * sharing this address */
72     name_chain *initialnames;   /* no runtime use, temporary storage of first 
73                                  * NVH'es names */
74 };
75
76 /* This defines the size of the hash table used for hashing ip addresses
77  * of virtual hosts.  It must be a power of two.
78  */
79 #ifndef IPHASH_TABLE_SIZE
80 #define IPHASH_TABLE_SIZE 256
81 #endif
82
83 /* A (n) bucket hash table, each entry has a pointer to a server rec and
84  * a pointer to the other entries in that bucket.  Each individual address,
85  * even for virtualhosts with multiple addresses, has an entry in this hash
86  * table.  There are extra buckets for _default_, and name-vhost entries.
87  *
88  * Note that after config time this is constant, so it is thread-safe.
89  */
90 static ipaddr_chain *iphash_table[IPHASH_TABLE_SIZE];
91
92 /* dump out statistics about the hash function */
93 /* #define IPHASH_STATISTICS */
94
95 /* list of the _default_ servers */
96 static ipaddr_chain *default_list;
97
98 /* whether a config error was seen */
99 static int config_error = 0;
100
101 /* config check function */
102 static int vhost_check_config(apr_pool_t *p, apr_pool_t *plog,
103                               apr_pool_t *ptemp, server_rec *s);
104
105 /*
106  * How it's used:
107  *
108  * The ip address determines which chain in iphash_table is interesting, then
109  * a comparison is done down that chain to find the first ipaddr_chain whose
110  * sar matches the address:port pair.
111  *
112  * If that ipaddr_chain has names == NULL then you're done, it's an ip-vhost.
113  *
114  * Otherwise it's a name-vhost list, and the default is the server in the
115  * ipaddr_chain record.  We tuck away the ipaddr_chain record in the
116  * conn_rec field vhost_lookup_data.  Later on after the headers we get a
117  * second chance, and we use the name_chain to figure out what name-vhost
118  * matches the headers.
119  *
120  * If there was no ip address match in the iphash_table then do a lookup
121  * in the default_list.
122  *
123  * How it's put together ... well you should be able to figure that out
124  * from how it's used.  Or something like that.
125  */
126
127
128 /* called at the beginning of the config */
129 AP_DECLARE(void) ap_init_vhost_config(apr_pool_t *p)
130 {
131     memset(iphash_table, 0, sizeof(iphash_table));
132     default_list = NULL;
133     ap_hook_check_config(vhost_check_config, NULL, NULL, APR_HOOK_MIDDLE);
134 }
135
136
137 /*
138  * Parses a host of the form <address>[:port]
139  * paddr is used to create a list in the order of input
140  * **paddr is the ->next pointer of the last entry (or s->addrs)
141  * *paddr is the variable used to keep track of **paddr between calls
142  * port is the default port to assume
143  */
144 static const char *get_addresses(apr_pool_t *p, const char *w_,
145                                  server_addr_rec ***paddr,
146                                  apr_port_t default_port)
147 {
148     apr_sockaddr_t *my_addr;
149     server_addr_rec *sar;
150     char *w, *host, *scope_id;
151     int wild_port;
152     apr_size_t wlen;
153     apr_port_t port;
154     apr_status_t rv;
155
156     if (*w_ == '\0')
157         return NULL;
158
159     w = apr_pstrdup(p, w_);
160     /* apr_parse_addr_port() doesn't understand ":*" so handle that first. */
161     wlen = strlen(w);                    /* wlen must be > 0 at this point */
162     wild_port = 0;
163     if (w[wlen - 1] == '*') {
164         if (wlen < 2) {
165             wild_port = 1;
166         }
167         else if (w[wlen - 2] == ':') {
168             w[wlen - 2] = '\0';
169             wild_port = 1;
170         }
171     }
172     rv = apr_parse_addr_port(&host, &scope_id, &port, w, p);
173     /* If the string is "80", apr_parse_addr_port() will be happy and set
174      * host to NULL and port to 80, so watch out for that.
175      */
176     if (rv != APR_SUCCESS) {
177         return "The address or port is invalid";
178     }
179     if (!host) {
180         return "Missing address for VirtualHost";
181     }
182     if (scope_id) {
183         return "Scope ids are not supported";
184     }
185     if (!port && !wild_port) {
186         port = default_port;
187     }
188
189     if (strcmp(host, "*") == 0 || strcasecmp(host, "_default_") == 0) {
190         rv = apr_sockaddr_info_get(&my_addr, "0.0.0.0", APR_INET, port, 0, p);
191         if (rv) {
192             return "Could not resolve address '0.0.0.0' -- "
193                 "check resolver configuration.";
194         }
195     }
196     else {
197         rv = apr_sockaddr_info_get(&my_addr, host, APR_UNSPEC, port, 0, p);
198         if (rv != APR_SUCCESS) {
199             ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
200                 "Could not resolve host name %s -- ignoring!", host);
201             return NULL;
202         }
203     }
204
205     /* Remember all addresses for the host */
206
207     do {
208         sar = apr_pcalloc(p, sizeof(server_addr_rec));
209         **paddr = sar;
210         *paddr = &sar->next;
211         sar->host_addr = my_addr;
212         sar->host_port = port;
213         sar->virthost = host;
214         my_addr = my_addr->next;
215     } while (my_addr);
216
217     return NULL;
218 }
219
220
221 /* parse the <VirtualHost> addresses */
222 const char *ap_parse_vhost_addrs(apr_pool_t *p,
223                                  const char *hostname,
224                                  server_rec *s)
225 {
226     server_addr_rec **addrs;
227     const char *err;
228
229     /* start the list of addreses */
230     addrs = &s->addrs;
231     while (hostname[0]) {
232         err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port);
233         if (err) {
234             *addrs = NULL;
235             return err;
236         }
237     }
238     /* terminate the list */
239     *addrs = NULL;
240     if (s->addrs) {
241         if (s->addrs->host_port) {
242             /* override the default port which is inherited from main_server */
243             s->port = s->addrs->host_port;
244         }
245     }
246     return NULL;
247 }
248
249
250 AP_DECLARE_NONSTD(const char *)ap_set_name_virtual_host(cmd_parms *cmd,
251                                                         void *dummy,
252                                                         const char *arg)
253 {
254     static int warnonce = 0;
255     if (++warnonce == 1) { 
256         ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_STARTUP, APR_SUCCESS, NULL, 
257                      "NameVirtualHost has no effect and will be removed in the " 
258                      "next release %s:%d", 
259                      cmd->directive->filename, 
260                      cmd->directive->line_num);
261     }
262
263     return NULL;
264 }
265
266
267 /* hash table statistics, keep this in here for the beta period so
268  * we can find out if the hash function is ok
269  */
270 #ifdef IPHASH_STATISTICS
271 static int iphash_compare(const void *a, const void *b)
272 {
273     return (*(const int *) b - *(const int *) a);
274 }
275
276
277 static void dump_iphash_statistics(server_rec *main_s)
278 {
279     unsigned count[IPHASH_TABLE_SIZE];
280     int i;
281     ipaddr_chain *src;
282     unsigned total;
283     char buf[HUGE_STRING_LEN];
284     char *p;
285
286     total = 0;
287     for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
288         count[i] = 0;
289         for (src = iphash_table[i]; src; src = src->next) {
290             ++count[i];
291             if (i < IPHASH_TABLE_SIZE) {
292                 /* don't count the slop buckets in the total */
293                 ++total;
294             }
295         }
296     }
297     qsort(count, IPHASH_TABLE_SIZE, sizeof(count[0]), iphash_compare);
298     p = buf + apr_snprintf(buf, sizeof(buf),
299                            "iphash: total hashed = %u, avg chain = %u, "
300                            "chain lengths (count x len):",
301                            total, total / IPHASH_TABLE_SIZE);
302     total = 1;
303     for (i = 1; i < IPHASH_TABLE_SIZE; ++i) {
304         if (count[i - 1] != count[i]) {
305             p += apr_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
306                               total, count[i - 1]);
307             total = 1;
308         }
309         else {
310             ++total;
311         }
312     }
313     p += apr_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
314                       total, count[IPHASH_TABLE_SIZE - 1]);
315     ap_log_error(APLOG_MARK, APLOG_DEBUG, main_s, buf);
316 }
317 #endif
318
319
320 /* This hashing function is designed to get good distribution in the cases
321  * where the server is handling entire "networks" of servers.  i.e. a
322  * whack of /24s.  This is probably the most common configuration for
323  * ISPs with large virtual servers.
324  *
325  * NOTE: This function is symmetric (i.e. collapses all 4 octets
326  * into one), so machine byte order (big/little endianness) does not matter.
327  *
328  * Hash function provided by David Hankins.
329  */
330 static APR_INLINE unsigned hash_inaddr(unsigned key)
331 {
332     key ^= (key >> 16);
333     return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE;
334 }
335
336 static APR_INLINE unsigned hash_addr(struct apr_sockaddr_t *sa)
337 {
338     unsigned key;
339
340     /* The key is the last four bytes of the IP address.
341      * For IPv4, this is the entire address, as always.
342      * For IPv6, this is usually part of the MAC address.
343      */
344     key = *(unsigned *)((char *)sa->ipaddr_ptr + sa->ipaddr_len - 4);
345     return hash_inaddr(key);
346 }
347
348 static ipaddr_chain *new_ipaddr_chain(apr_pool_t *p,
349                                       server_rec *s, server_addr_rec *sar)
350 {
351     ipaddr_chain *new;
352
353     new = apr_palloc(p, sizeof(*new));
354     new->names = NULL;
355     new->initialnames = NULL;
356     new->server = s;
357     new->sar = sar;
358     new->next = NULL;
359     return new;
360 }
361
362
363 static name_chain *new_name_chain(apr_pool_t *p,
364                                   server_rec *s, server_addr_rec *sar)
365 {
366     name_chain *new;
367
368     new = apr_palloc(p, sizeof(*new));
369     new->server = s;
370     new->sar = sar;
371     new->next = NULL;
372     return new;
373 }
374
375
376 static APR_INLINE ipaddr_chain *find_ipaddr(apr_sockaddr_t *sa)
377 {
378     unsigned bucket;
379     ipaddr_chain *trav = NULL;
380     ipaddr_chain *wild_match = NULL;
381
382     /* scan the hash table for an exact match first */
383     bucket = hash_addr(sa);
384     for (trav = iphash_table[bucket]; trav; trav = trav->next) {
385         server_addr_rec *sar = trav->sar;
386         apr_sockaddr_t *cur = sar->host_addr;
387
388         if (cur->port == sa->port) {
389             if (apr_sockaddr_equal(cur, sa)) {
390                 return trav;
391             }
392         }
393         if (wild_match == NULL && (cur->port == 0 || sa->port == 0)) {
394             if (apr_sockaddr_equal(cur, sa)) {
395                 /* don't break, continue looking for an exact match */
396                 wild_match = trav; 
397             }
398         }
399     }
400     return wild_match;
401 }
402
403 static ipaddr_chain *find_default_server(apr_port_t port)
404 {
405     server_addr_rec *sar;
406     ipaddr_chain *trav = NULL;
407     ipaddr_chain *wild_match = NULL;
408
409     for (trav = default_list; trav; trav = trav->next) {
410         sar = trav->sar;
411         if (sar->host_port == port) {
412             /* match! */
413             return trav;
414         }
415         if (wild_match == NULL && sar->host_port == 0) {
416             /* don't break, continue looking for an exact match */
417             wild_match = trav;
418         } 
419     }
420     return wild_match;
421 }
422
423 static void dump_a_vhost(apr_file_t *f, ipaddr_chain *ic)
424 {
425     name_chain *nc;
426     int len;
427     char buf[MAX_STRING_LEN];
428     apr_sockaddr_t *ha = ic->sar->host_addr;
429
430     if (ha->family == APR_INET &&
431              ha->sa.sin.sin_addr.s_addr == INADDR_ANY) {
432         len = apr_snprintf(buf, sizeof(buf), "*:%u",
433                            ic->sar->host_port);
434     }
435     else {
436         len = apr_snprintf(buf, sizeof(buf), "%pI", ha);
437     }
438     if (ic->sar->host_port == 0) {
439         buf[len-1] = '*';
440     }
441     if (ic->names == NULL) {
442         apr_file_printf(f, "%-22s %s (%s:%u)\n", buf,
443                         ic->server->server_hostname,
444                         ic->server->defn_name, ic->server->defn_line_number);
445         return;
446     }
447     apr_file_printf(f, "%-22s is a NameVirtualHost\n"
448                     "%8s default server %s (%s:%u)\n",
449                     buf, "", ic->server->server_hostname,
450                     ic->server->defn_name, ic->server->defn_line_number);
451     for (nc = ic->names; nc; nc = nc->next) {
452         if (nc->sar->host_port) {
453             apr_file_printf(f, "%8s port %u ", "", nc->sar->host_port);
454         }
455         else {
456             apr_file_printf(f, "%8s port * ", "");
457         }
458         apr_file_printf(f, "namevhost %s (%s:%u)\n",
459                         nc->server->server_hostname,
460                         nc->server->defn_name, nc->server->defn_line_number);
461         if (nc->server->names) {
462             apr_array_header_t *names = nc->server->names;
463             char **name = (char **)names->elts;
464             int i;
465             for (i = 0; i < names->nelts; ++i) {
466                 if (name[i]) {
467                     apr_file_printf(f, "%16s alias %s\n", "", name[i]);
468                 }
469             }
470         }
471         if (nc->server->wild_names) {
472             apr_array_header_t *names = nc->server->wild_names;
473             char **name = (char **)names->elts;
474             int i;
475             for (i = 0; i < names->nelts; ++i) {
476                 if (name[i]) {
477                     apr_file_printf(f, "%16s wild alias %s\n", "", name[i]);
478                 }
479             }
480         }
481     }
482 }
483
484 static void dump_vhost_config(apr_file_t *f)
485 {
486     ipaddr_chain *ic;
487     int i;
488
489     apr_file_printf(f, "VirtualHost configuration:\n");
490
491     /* non-wildcard servers */
492     for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
493         for (ic = iphash_table[i]; ic; ic = ic->next) {
494             dump_a_vhost(f, ic);
495         }
496     }
497
498     /* wildcard servers */
499     for (ic = default_list; ic; ic = ic->next) {
500         dump_a_vhost(f, ic);
501     }
502 }
503
504
505 /*
506  * When a second or later virtual host maps to the same IP chain,
507  * add the relevant server names to the chain.  Special care is taken
508  * to avoid adding ic->names until we're sure there are multiple VH'es.
509  */
510 static void add_name_vhost_config(apr_pool_t *p, server_rec *main_s,
511                                  server_rec *s, server_addr_rec *sar,
512                                  ipaddr_chain *ic)
513 {
514
515    name_chain *nc = new_name_chain(p, s, sar);
516    nc->next = ic->names;
517
518    /* iterating backwards, so each one we see becomes the current default server */
519    ic->server = s; 
520
521    if (ic->names == NULL) { 
522        if (ic->initialnames == NULL) { 
523            /* first pass, set these names aside in case we see another VH.
524             * Until then, this looks like an IP-based VH to runtime.
525             */
526            ic->initialnames = nc;
527        }
528        else { 
529            /* second pass through this chain -- this really is an NVH, and we
530             * have two sets of names to link in.
531             */
532            nc->next = ic->initialnames;
533            ic->names = nc;
534            ic->initialnames = NULL;
535        }
536    }
537    else { 
538        /* 3rd or more -- just keep stacking the names */
539        ic->names = nc;
540    }
541 }
542
543 /* compile the tables and such we need to do the run-time vhost lookups */
544 AP_DECLARE(void) ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s)
545 {
546     server_addr_rec *sar;
547     int has_default_vhost_addr;
548     server_rec *s;
549     int i;
550     ipaddr_chain **iphash_table_tail[IPHASH_TABLE_SIZE];
551
552     /* Main host first */
553     s = main_s;
554
555     if (!s->server_hostname) {
556         s->server_hostname = ap_get_local_host(p);
557     }
558
559     /* initialize the tails */
560     for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
561         iphash_table_tail[i] = &iphash_table[i];
562     }
563
564     /* The next things to go into the hash table are the virtual hosts
565      * themselves.  They're listed off of main_s->next in the reverse
566      * order they occured in the config file, so we insert them at
567      * the iphash_table_tail but don't advance the tail.
568      */
569
570     for (s = main_s->next; s; s = s->next) {
571         has_default_vhost_addr = 0;
572         for (sar = s->addrs; sar; sar = sar->next) {
573             ipaddr_chain *ic;
574             char inaddr_any[16] = {0}; /* big enough to handle IPv4 or IPv6 */
575
576             if (!memcmp(sar->host_addr->ipaddr_ptr, inaddr_any, sar->host_addr->ipaddr_len)) {
577                 ic = find_default_server(sar->host_port);
578                 if (!ic || sar->host_port != ic->sar->host_port) { 
579                     /* No default server, or we found a default server but 
580                     ** exactly one of us is a wildcard port, which means we want
581                     ** two ip-based vhosts not an NVH with two names
582                     */
583                     ic = new_ipaddr_chain(p, s, sar);
584                     ic->next = default_list;
585                     default_list = ic;
586                 }
587                 has_default_vhost_addr = 1;
588             }
589             else {
590                 /* see if it matches something we've already got */
591                 ic = find_ipaddr(sar->host_addr);
592
593                 if (!ic || sar->host_port != ic->sar->host_port) { 
594                     /* No matching server, or we found a matching server but 
595                     ** exactly one of us is a wildcard port, which means we want
596                     ** two ip-based vhosts not an NVH with two names
597                     */
598                     unsigned bucket = hash_addr(sar->host_addr);
599                     ic = new_ipaddr_chain(p, s, sar);
600                     ic->next = *iphash_table_tail[bucket];
601                     *iphash_table_tail[bucket] = ic;
602                 }
603             }
604             add_name_vhost_config(p, main_s, s, sar, ic);
605         }
606
607         /* Ok now we want to set up a server_hostname if the user was
608          * silly enough to forget one.
609          * XXX: This is silly we should just crash and burn.
610          */
611         if (!s->server_hostname) {
612             if (has_default_vhost_addr) {
613                 s->server_hostname = main_s->server_hostname;
614             }
615             else if (!s->addrs) {
616                 /* what else can we do?  at this point this vhost has
617                     no configured name, probably because they used
618                     DNS in the VirtualHost statement.  It's disabled
619                     anyhow by the host matching code.  -djg */
620                 s->server_hostname =
621                     apr_pstrdup(p, "bogus_host_without_forward_dns");
622             }
623             else {
624                 apr_status_t rv;
625                 char *hostname;
626
627                 rv = apr_getnameinfo(&hostname, s->addrs->host_addr, 0);
628                 if (rv == APR_SUCCESS) {
629                     s->server_hostname = apr_pstrdup(p, hostname);
630                 }
631                 else {
632                     /* again, what can we do?  They didn't specify a
633                        ServerName, and their DNS isn't working. -djg */
634                     char *ipaddr_str;
635
636                     apr_sockaddr_ip_get(&ipaddr_str, s->addrs->host_addr);
637                     ap_log_error(APLOG_MARK, APLOG_ERR, rv, main_s,
638                                  "Failed to resolve server name "
639                                  "for %s (check DNS) -- or specify an explicit "
640                                  "ServerName",
641                                  ipaddr_str);
642                     s->server_hostname =
643                         apr_pstrdup(p, "bogus_host_without_reverse_dns");
644                 }
645             }
646         }
647     }
648
649 #ifdef IPHASH_STATISTICS
650     dump_iphash_statistics(main_s);
651 #endif
652     if (ap_exists_config_define("DUMP_VHOSTS")) {
653         apr_file_t *thefile = NULL;
654         apr_file_open_stdout(&thefile, p);
655         dump_vhost_config(thefile);
656     }
657 }
658
659 static int vhost_check_config(apr_pool_t *p, apr_pool_t *plog,
660                               apr_pool_t *ptemp, server_rec *s)
661 {
662     return config_error ? !OK : OK;
663 }
664
665 /*****************************************************************************
666  * run-time vhost matching functions
667  */
668
669 /* Lowercase and remove any trailing dot and/or :port from the hostname,
670  * and check that it is sane.
671  *
672  * In most configurations the exact syntax of the hostname isn't
673  * important so strict sanity checking isn't necessary. However, in
674  * mass hosting setups (using mod_vhost_alias or mod_rewrite) where
675  * the hostname is interpolated into the filename, we need to be sure
676  * that the interpolation doesn't expose parts of the filesystem.
677  * We don't do strict RFC 952 / RFC 1123 syntax checking in order
678  * to support iDNS and people who erroneously use underscores.
679  * Instead we just check for filesystem metacharacters: directory
680  * separators / and \ and sequences of more than one dot.
681  */
682 static void fix_hostname(request_rec *r)
683 {
684     char *host, *scope_id;
685     char *dst;
686     apr_port_t port;
687     apr_status_t rv;
688     const char *c;
689
690     /* According to RFC 2616, Host header field CAN be blank. */
691     if (!*r->hostname) {
692         return;
693     }
694
695     /* apr_parse_addr_port will interpret a bare integer as a port
696      * which is incorrect in this context.  So treat it separately.
697      */
698     for (c = r->hostname; apr_isdigit(*c); ++c);
699     if (!*c) {  /* pure integer */
700         return;
701     }
702
703     rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool);
704     if (rv != APR_SUCCESS || scope_id) {
705         goto bad;
706     }
707
708     if (port) {
709         /* Don't throw the Host: header's port number away:
710            save it in parsed_uri -- ap_get_server_port() needs it! */
711         /* @@@ XXX there should be a better way to pass the port.
712          *         Like r->hostname, there should be a r->portno
713          */
714         r->parsed_uri.port = port;
715         r->parsed_uri.port_str = apr_itoa(r->pool, (int)port);
716     }
717
718     /* if the hostname is an IPv6 numeric address string, it was validated
719      * already; otherwise, further validation is needed
720      */
721     if (r->hostname[0] != '[') {
722         for (dst = host; *dst; dst++) {
723             if (apr_islower(*dst)) {
724                 /* leave char unchanged */
725             }
726             else if (*dst == '.') {
727                 if (*(dst + 1) == '.') {
728                     goto bad;
729                 }
730             }
731             else if (apr_isupper(*dst)) {
732                 *dst = apr_tolower(*dst);
733             }
734             else if (*dst == '/' || *dst == '\\') {
735                 goto bad;
736             }
737         }
738         /* strip trailing gubbins */
739         if (dst > host && dst[-1] == '.') {
740             dst[-1] = '\0';
741         }
742     }
743     r->hostname = host;
744     return;
745
746 bad:
747     r->status = HTTP_BAD_REQUEST;
748     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
749                   "Client sent malformed Host header");
750     return;
751 }
752
753
754 /* return 1 if host matches ServerName or ServerAliases */
755 static int matches_aliases(server_rec *s, const char *host)
756 {
757     int i;
758     apr_array_header_t *names;
759
760     /* match ServerName */
761     if (!strcasecmp(host, s->server_hostname)) {
762         return 1;
763     }
764
765     /* search all the aliases from ServerAlias directive */
766     names = s->names;
767     if (names) {
768         char **name = (char **) names->elts;
769         for (i = 0; i < names->nelts; ++i) {
770             if(!name[i]) continue;
771             if (!strcasecmp(host, name[i]))
772                 return 1;
773         }
774     }
775     names = s->wild_names;
776     if (names) {
777         char **name = (char **) names->elts;
778         for (i = 0; i < names->nelts; ++i) {
779             if(!name[i]) continue;
780             if (!ap_strcasecmp_match(host, name[i]))
781                 return 1;
782         }
783     }
784     return 0;
785 }
786
787
788 /* Suppose a request came in on the same socket as this r, and included
789  * a header "Host: host:port", would it map to r->server?  It's more
790  * than just that though.  When we do the normal matches for each request
791  * we don't even bother considering Host: etc on non-namevirtualhosts,
792  * we just call it a match.  But here we require the host:port to match
793  * the ServerName and/or ServerAliases.
794  */
795 AP_DECLARE(int) ap_matches_request_vhost(request_rec *r, const char *host,
796                                          apr_port_t port)
797 {
798     server_rec *s;
799     server_addr_rec *sar;
800
801     s = r->server;
802
803     /* search all the <VirtualHost> values */
804     /* XXX: If this is a NameVirtualHost then we may not be doing the Right Thing
805      * consider:
806      *
807      *     NameVirtualHost 10.1.1.1
808      *     <VirtualHost 10.1.1.1>
809      *     ServerName v1
810      *     </VirtualHost>
811      *     <VirtualHost 10.1.1.1>
812      *     ServerName v2
813      *     </VirtualHost>
814      *
815      * Suppose r->server is v2, and we're asked to match "10.1.1.1".  We'll say
816      * "yup it's v2", when really it isn't... if a request came in for 10.1.1.1
817      * it would really go to v1.
818      */
819     for (sar = s->addrs; sar; sar = sar->next) {
820         if ((sar->host_port == 0 || port == sar->host_port)
821             && !strcasecmp(host, sar->virthost)) {
822             return 1;
823         }
824     }
825
826     /* the Port has to match now, because the rest don't have ports associated
827      * with them. */
828     if (port != s->port) {
829         return 0;
830     }
831
832     return matches_aliases(s, host);
833 }
834
835
836 static void check_hostalias(request_rec *r)
837 {
838     /*
839      * Even if the request has a Host: header containing a port we ignore
840      * that port.  We always use the physical port of the socket.  There
841      * are a few reasons for this:
842      *
843      * - the default of 80 or 443 for SSL is easier to handle this way
844      * - there is less of a possibility of a security problem
845      * - it simplifies the data structure
846      * - the client may have no idea that a proxy somewhere along the way
847      *   translated the request to another ip:port
848      * - except for the addresses from the VirtualHost line, none of the other
849      *   names we'll match have ports associated with them
850      */
851     const char *host = r->hostname;
852     apr_port_t port;
853     server_rec *s;
854     server_rec *last_s;
855     name_chain *src;
856
857     last_s = NULL;
858
859     port = r->connection->local_addr->port;
860
861     /* Recall that the name_chain is a list of server_addr_recs, some of
862      * whose ports may not match.  Also each server may appear more than
863      * once in the chain -- specifically, it will appear once for each
864      * address from its VirtualHost line which matched.  We only want to
865      * do the full ServerName/ServerAlias comparisons once for each
866      * server, fortunately we know that all the VirtualHost addresses for
867      * a single server are adjacent to each other.
868      */
869
870     for (src = r->connection->vhost_lookup_data; src; src = src->next) {
871         server_addr_rec *sar;
872
873         /* We only consider addresses on the name_chain which have a matching
874          * port
875          */
876         sar = src->sar;
877         if (sar->host_port != 0 && port != sar->host_port) {
878             continue;
879         }
880
881         s = src->server;
882
883         /* does it match the virthost from the sar? */
884         if (!strcasecmp(host, sar->virthost)) {
885             goto found;
886         }
887
888         if (s == last_s) {
889             /* we've already done ServerName and ServerAlias checks for this
890              * vhost
891              */
892             continue;
893         }
894         last_s = s;
895
896         if (matches_aliases(s, host)) {
897             goto found;
898         }
899     }
900     return;
901
902 found:
903     /* s is the first matching server, we're done */
904     r->server = s;
905 }
906
907
908 static void check_serverpath(request_rec *r)
909 {
910     server_rec *s;
911     server_rec *last_s;
912     name_chain *src;
913     apr_port_t port;
914
915     port = r->connection->local_addr->port;
916
917     /*
918      * This is in conjunction with the ServerPath code in http_core, so we
919      * get the right host attached to a non- Host-sending request.
920      *
921      * See the comment in check_hostalias about how each vhost can be
922      * listed multiple times.
923      */
924
925     last_s = NULL;
926     for (src = r->connection->vhost_lookup_data; src; src = src->next) {
927         /* We only consider addresses on the name_chain which have a matching
928          * port
929          */
930         if (src->sar->host_port != 0 && port != src->sar->host_port) {
931             continue;
932         }
933
934         s = src->server;
935         if (s == last_s) {
936             continue;
937         }
938         last_s = s;
939
940         if (s->path && !strncmp(r->uri, s->path, s->pathlen) &&
941             (s->path[s->pathlen - 1] == '/' ||
942              r->uri[s->pathlen] == '/' ||
943              r->uri[s->pathlen] == '\0')) {
944             r->server = s;
945             return;
946         }
947     }
948 }
949
950
951 AP_DECLARE(void) ap_update_vhost_from_headers(request_rec *r)
952 {
953     /* must set this for HTTP/1.1 support */
954     if (r->hostname || (r->hostname = apr_table_get(r->headers_in, "Host"))) {
955         fix_hostname(r);
956         if (r->status != HTTP_OK)
957             return;
958     }
959     /* check if we tucked away a name_chain */
960     if (r->connection->vhost_lookup_data) {
961         if (r->hostname)
962             check_hostalias(r);
963         else
964             check_serverpath(r);
965     }
966 }
967
968 /**
969  * For every virtual host on this connection, call func_cb.
970  */
971 AP_DECLARE(int) ap_vhost_iterate_given_conn(conn_rec *conn,
972                                             ap_vhost_iterate_conn_cb func_cb,
973                                             void* baton)
974 {
975     server_rec *s;
976     server_rec *last_s;
977     name_chain *src;
978     apr_port_t port;
979     int rv = 0;
980
981     if (conn->vhost_lookup_data) {
982         last_s = NULL;
983         port = conn->local_addr->port;
984
985         for (src = conn->vhost_lookup_data; src; src = src->next) {
986             server_addr_rec *sar;
987
988             /* We only consider addresses on the name_chain which have a
989              * matching port.
990              */
991             sar = src->sar;
992             if (sar->host_port != 0 && port != sar->host_port) {
993                 continue;
994             }
995
996             s = src->server;
997
998             if (s == last_s) {
999                 /* we've already done a callback for this vhost. */
1000                 continue;
1001             }
1002
1003             last_s = s;
1004
1005             rv = func_cb(baton, conn, s);
1006
1007             if (rv != 0) {
1008                 break;
1009             }
1010         }
1011     }
1012     else {
1013         rv = func_cb(baton, conn, conn->base_server);
1014     }
1015
1016     return rv;
1017 }
1018
1019 /* Called for a new connection which has a known local_addr.  Note that the
1020  * new connection is assumed to have conn->server == main server.
1021  */
1022 AP_DECLARE(void) ap_update_vhost_given_ip(conn_rec *conn)
1023 {
1024     ipaddr_chain *trav;
1025     apr_port_t port;
1026
1027     /* scan the hash table for an exact match first */
1028     trav = find_ipaddr(conn->local_addr);
1029
1030     if (trav) {
1031         /* save the name_chain for later in case this is a name-vhost */
1032         conn->vhost_lookup_data = trav->names;
1033         conn->base_server = trav->server;
1034         return;
1035     }
1036
1037     /* maybe there's a default server or wildcard name-based vhost
1038      * matching this port
1039      */
1040     port = conn->local_addr->port;
1041
1042     trav = find_default_server(port);
1043     if (trav) {
1044         conn->vhost_lookup_data = trav->names;
1045         conn->base_server = trav->server;
1046         return;
1047     }
1048
1049     /* otherwise we're stuck with just the main server
1050      * and no name-based vhosts
1051      */
1052     conn->vhost_lookup_data = NULL;
1053 }