summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in252
-rw-r--r--src/base.h9
-rw-r--r--src/buffer.c75
-rw-r--r--src/buffer.h1
-rw-r--r--src/configfile.c49
-rw-r--r--src/connections.c40
-rw-r--r--src/fdevent_libev.c19
-rw-r--r--src/http-header-glue.c82
-rw-r--r--src/http_auth.c193
-rw-r--r--src/http_auth.h5
-rw-r--r--src/keyvalue.c43
-rw-r--r--src/keyvalue.h71
-rw-r--r--src/lemon.c10
-rw-r--r--src/log.c166
-rw-r--r--src/log.h1
-rw-r--r--src/mod_accesslog.c52
-rw-r--r--src/mod_alias.c3
-rw-r--r--src/mod_auth.c61
-rw-r--r--src/mod_cgi.c11
-rw-r--r--src/mod_extforward.c66
-rw-r--r--src/mod_fastcgi.c11
-rw-r--r--src/mod_proxy.c2
-rw-r--r--src/mod_redirect.c4
-rw-r--r--src/mod_scgi.c12
-rw-r--r--src/mod_simple_vhost.c61
-rw-r--r--src/mod_ssi.c5
-rw-r--r--src/mod_trigger_b4_dl.c4
-rw-r--r--src/mod_userdir.c13
-rw-r--r--src/network.c28
-rw-r--r--src/network_openssl.c4
-rw-r--r--src/network_writev.c33
-rw-r--r--src/proc_open.c1
-rw-r--r--src/request.c73
-rw-r--r--src/response.c19
-rw-r--r--src/server.c90
35 files changed, 848 insertions, 721 deletions
diff --git a/src/Makefile.in b/src/Makefile.in
index 705e7ef..72a68b6 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,9 +1,8 @@
-# Makefile.in generated by automake 1.11.6 from Makefile.am.
+# Makefile.in generated by automake 1.14 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
-# Foundation, Inc.
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -18,23 +17,51 @@
VPATH = @srcdir@
-am__make_dryrun = \
- { \
- am__dry=no; \
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
- *) \
- for am__flg in $$MAKEFLAGS; do \
- case $$am__flg in \
- *=*|--*) ;; \
- *n*) am__dry=yes; break;; \
- esac; \
- done;; \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
- test $$am__dry = yes; \
- }
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -63,8 +90,8 @@ sbin_PROGRAMS = lighttpd$(EXEEXT) lighttpd-angel$(EXEEXT)
@NO_RDYNAMIC_TRUE@am__append_1 = liblightcomp.la
@NO_RDYNAMIC_FALSE@am__append_2 = $(common_src)
subdir = src
-DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
- $(srcdir)/Makefile.in
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp $(noinst_HEADERS)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
@@ -154,6 +181,7 @@ liblightcomp_la_OBJECTS = $(am_liblightcomp_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
+am__v_lt_1 =
liblightcomp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(liblightcomp_la_CFLAGS) $(CFLAGS) $(liblightcomp_la_LDFLAGS) \
@@ -442,6 +470,18 @@ am_proc_open_OBJECTS = proc_open-proc_open.$(OBJEXT) \
proc_open-buffer.$(OBJEXT)
proc_open_OBJECTS = $(am_proc_open_OBJECTS)
proc_open_LDADD = $(LDADD)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -454,20 +494,16 @@ LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo " CC " $@;
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo " CCLD " $@;
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
SOURCES = $(liblightcomp_la_SOURCES) $(mod_access_la_SOURCES) \
$(mod_accesslog_la_SOURCES) $(mod_alias_la_SOURCES) \
$(mod_auth_la_SOURCES) $(mod_cgi_la_SOURCES) \
@@ -511,6 +547,23 @@ am__can_run_installinfo = \
*) (install-info --version) >/dev/null 2>&1;; \
esac
HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -882,6 +935,7 @@ $(top_srcdir)/configure: $(am__configure_deps)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
+
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
@@ -908,76 +962,111 @@ uninstall-libLTLIBRARIES:
clean-libLTLIBRARIES:
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
- @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
- test "$$dir" != "$$p" || dir=.; \
- echo "rm -f \"$${dir}/so_locations\""; \
- rm -f "$${dir}/so_locations"; \
- done
+ @list='$(lib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
liblightcomp.la: $(liblightcomp_la_OBJECTS) $(liblightcomp_la_DEPENDENCIES) $(EXTRA_liblightcomp_la_DEPENDENCIES)
$(AM_V_CCLD)$(liblightcomp_la_LINK) $(am_liblightcomp_la_rpath) $(liblightcomp_la_OBJECTS) $(liblightcomp_la_LIBADD) $(LIBS)
+
mod_access.la: $(mod_access_la_OBJECTS) $(mod_access_la_DEPENDENCIES) $(EXTRA_mod_access_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_access_la_LINK) -rpath $(libdir) $(mod_access_la_OBJECTS) $(mod_access_la_LIBADD) $(LIBS)
+
mod_accesslog.la: $(mod_accesslog_la_OBJECTS) $(mod_accesslog_la_DEPENDENCIES) $(EXTRA_mod_accesslog_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_accesslog_la_LINK) -rpath $(libdir) $(mod_accesslog_la_OBJECTS) $(mod_accesslog_la_LIBADD) $(LIBS)
+
mod_alias.la: $(mod_alias_la_OBJECTS) $(mod_alias_la_DEPENDENCIES) $(EXTRA_mod_alias_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_alias_la_LINK) -rpath $(libdir) $(mod_alias_la_OBJECTS) $(mod_alias_la_LIBADD) $(LIBS)
+
mod_auth.la: $(mod_auth_la_OBJECTS) $(mod_auth_la_DEPENDENCIES) $(EXTRA_mod_auth_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_auth_la_LINK) -rpath $(libdir) $(mod_auth_la_OBJECTS) $(mod_auth_la_LIBADD) $(LIBS)
+
mod_cgi.la: $(mod_cgi_la_OBJECTS) $(mod_cgi_la_DEPENDENCIES) $(EXTRA_mod_cgi_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_cgi_la_LINK) -rpath $(libdir) $(mod_cgi_la_OBJECTS) $(mod_cgi_la_LIBADD) $(LIBS)
+
mod_cml.la: $(mod_cml_la_OBJECTS) $(mod_cml_la_DEPENDENCIES) $(EXTRA_mod_cml_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_cml_la_LINK) -rpath $(libdir) $(mod_cml_la_OBJECTS) $(mod_cml_la_LIBADD) $(LIBS)
+
mod_compress.la: $(mod_compress_la_OBJECTS) $(mod_compress_la_DEPENDENCIES) $(EXTRA_mod_compress_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_compress_la_LINK) -rpath $(libdir) $(mod_compress_la_OBJECTS) $(mod_compress_la_LIBADD) $(LIBS)
+
mod_dirlisting.la: $(mod_dirlisting_la_OBJECTS) $(mod_dirlisting_la_DEPENDENCIES) $(EXTRA_mod_dirlisting_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_dirlisting_la_LINK) -rpath $(libdir) $(mod_dirlisting_la_OBJECTS) $(mod_dirlisting_la_LIBADD) $(LIBS)
+
mod_evasive.la: $(mod_evasive_la_OBJECTS) $(mod_evasive_la_DEPENDENCIES) $(EXTRA_mod_evasive_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_evasive_la_LINK) -rpath $(libdir) $(mod_evasive_la_OBJECTS) $(mod_evasive_la_LIBADD) $(LIBS)
+
mod_evhost.la: $(mod_evhost_la_OBJECTS) $(mod_evhost_la_DEPENDENCIES) $(EXTRA_mod_evhost_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_evhost_la_LINK) -rpath $(libdir) $(mod_evhost_la_OBJECTS) $(mod_evhost_la_LIBADD) $(LIBS)
+
mod_expire.la: $(mod_expire_la_OBJECTS) $(mod_expire_la_DEPENDENCIES) $(EXTRA_mod_expire_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_expire_la_LINK) -rpath $(libdir) $(mod_expire_la_OBJECTS) $(mod_expire_la_LIBADD) $(LIBS)
+
mod_extforward.la: $(mod_extforward_la_OBJECTS) $(mod_extforward_la_DEPENDENCIES) $(EXTRA_mod_extforward_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_extforward_la_LINK) -rpath $(libdir) $(mod_extforward_la_OBJECTS) $(mod_extforward_la_LIBADD) $(LIBS)
+
mod_fastcgi.la: $(mod_fastcgi_la_OBJECTS) $(mod_fastcgi_la_DEPENDENCIES) $(EXTRA_mod_fastcgi_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_fastcgi_la_LINK) -rpath $(libdir) $(mod_fastcgi_la_OBJECTS) $(mod_fastcgi_la_LIBADD) $(LIBS)
+
mod_flv_streaming.la: $(mod_flv_streaming_la_OBJECTS) $(mod_flv_streaming_la_DEPENDENCIES) $(EXTRA_mod_flv_streaming_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_flv_streaming_la_LINK) -rpath $(libdir) $(mod_flv_streaming_la_OBJECTS) $(mod_flv_streaming_la_LIBADD) $(LIBS)
+
mod_indexfile.la: $(mod_indexfile_la_OBJECTS) $(mod_indexfile_la_DEPENDENCIES) $(EXTRA_mod_indexfile_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_indexfile_la_LINK) -rpath $(libdir) $(mod_indexfile_la_OBJECTS) $(mod_indexfile_la_LIBADD) $(LIBS)
+
mod_magnet.la: $(mod_magnet_la_OBJECTS) $(mod_magnet_la_DEPENDENCIES) $(EXTRA_mod_magnet_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_magnet_la_LINK) -rpath $(libdir) $(mod_magnet_la_OBJECTS) $(mod_magnet_la_LIBADD) $(LIBS)
+
mod_mysql_vhost.la: $(mod_mysql_vhost_la_OBJECTS) $(mod_mysql_vhost_la_DEPENDENCIES) $(EXTRA_mod_mysql_vhost_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_mysql_vhost_la_LINK) -rpath $(libdir) $(mod_mysql_vhost_la_OBJECTS) $(mod_mysql_vhost_la_LIBADD) $(LIBS)
+
mod_proxy.la: $(mod_proxy_la_OBJECTS) $(mod_proxy_la_DEPENDENCIES) $(EXTRA_mod_proxy_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_proxy_la_LINK) -rpath $(libdir) $(mod_proxy_la_OBJECTS) $(mod_proxy_la_LIBADD) $(LIBS)
+
mod_redirect.la: $(mod_redirect_la_OBJECTS) $(mod_redirect_la_DEPENDENCIES) $(EXTRA_mod_redirect_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_redirect_la_LINK) -rpath $(libdir) $(mod_redirect_la_OBJECTS) $(mod_redirect_la_LIBADD) $(LIBS)
+
mod_rewrite.la: $(mod_rewrite_la_OBJECTS) $(mod_rewrite_la_DEPENDENCIES) $(EXTRA_mod_rewrite_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_rewrite_la_LINK) -rpath $(libdir) $(mod_rewrite_la_OBJECTS) $(mod_rewrite_la_LIBADD) $(LIBS)
+
mod_rrdtool.la: $(mod_rrdtool_la_OBJECTS) $(mod_rrdtool_la_DEPENDENCIES) $(EXTRA_mod_rrdtool_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_rrdtool_la_LINK) -rpath $(libdir) $(mod_rrdtool_la_OBJECTS) $(mod_rrdtool_la_LIBADD) $(LIBS)
+
mod_scgi.la: $(mod_scgi_la_OBJECTS) $(mod_scgi_la_DEPENDENCIES) $(EXTRA_mod_scgi_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_scgi_la_LINK) -rpath $(libdir) $(mod_scgi_la_OBJECTS) $(mod_scgi_la_LIBADD) $(LIBS)
+
mod_secdownload.la: $(mod_secdownload_la_OBJECTS) $(mod_secdownload_la_DEPENDENCIES) $(EXTRA_mod_secdownload_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_secdownload_la_LINK) -rpath $(libdir) $(mod_secdownload_la_OBJECTS) $(mod_secdownload_la_LIBADD) $(LIBS)
+
mod_setenv.la: $(mod_setenv_la_OBJECTS) $(mod_setenv_la_DEPENDENCIES) $(EXTRA_mod_setenv_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_setenv_la_LINK) -rpath $(libdir) $(mod_setenv_la_OBJECTS) $(mod_setenv_la_LIBADD) $(LIBS)
+
mod_simple_vhost.la: $(mod_simple_vhost_la_OBJECTS) $(mod_simple_vhost_la_DEPENDENCIES) $(EXTRA_mod_simple_vhost_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_simple_vhost_la_LINK) -rpath $(libdir) $(mod_simple_vhost_la_OBJECTS) $(mod_simple_vhost_la_LIBADD) $(LIBS)
+
mod_ssi.la: $(mod_ssi_la_OBJECTS) $(mod_ssi_la_DEPENDENCIES) $(EXTRA_mod_ssi_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_ssi_la_LINK) -rpath $(libdir) $(mod_ssi_la_OBJECTS) $(mod_ssi_la_LIBADD) $(LIBS)
+
mod_staticfile.la: $(mod_staticfile_la_OBJECTS) $(mod_staticfile_la_DEPENDENCIES) $(EXTRA_mod_staticfile_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_staticfile_la_LINK) -rpath $(libdir) $(mod_staticfile_la_OBJECTS) $(mod_staticfile_la_LIBADD) $(LIBS)
+
mod_status.la: $(mod_status_la_OBJECTS) $(mod_status_la_DEPENDENCIES) $(EXTRA_mod_status_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_status_la_LINK) -rpath $(libdir) $(mod_status_la_OBJECTS) $(mod_status_la_LIBADD) $(LIBS)
+
mod_trigger_b4_dl.la: $(mod_trigger_b4_dl_la_OBJECTS) $(mod_trigger_b4_dl_la_DEPENDENCIES) $(EXTRA_mod_trigger_b4_dl_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_trigger_b4_dl_la_LINK) -rpath $(libdir) $(mod_trigger_b4_dl_la_OBJECTS) $(mod_trigger_b4_dl_la_LIBADD) $(LIBS)
+
mod_userdir.la: $(mod_userdir_la_OBJECTS) $(mod_userdir_la_DEPENDENCIES) $(EXTRA_mod_userdir_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_userdir_la_LINK) -rpath $(libdir) $(mod_userdir_la_OBJECTS) $(mod_userdir_la_LIBADD) $(LIBS)
+
mod_usertrack.la: $(mod_usertrack_la_OBJECTS) $(mod_usertrack_la_DEPENDENCIES) $(EXTRA_mod_usertrack_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_usertrack_la_LINK) -rpath $(libdir) $(mod_usertrack_la_OBJECTS) $(mod_usertrack_la_LIBADD) $(LIBS)
+
mod_webdav.la: $(mod_webdav_la_OBJECTS) $(mod_webdav_la_DEPENDENCIES) $(EXTRA_mod_webdav_la_DEPENDENCIES)
$(AM_V_CCLD)$(mod_webdav_la_LINK) -rpath $(libdir) $(mod_webdav_la_OBJECTS) $(mod_webdav_la_LIBADD) $(LIBS)
@@ -998,10 +1087,12 @@ install-sbinPROGRAMS: $(sbin_PROGRAMS)
fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
- while read p p1; do if test -f $$p || test -f $$p1; \
- then echo "$$p"; echo "$$p"; else :; fi; \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
done | \
- sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
@@ -1022,7 +1113,8 @@ uninstall-sbinPROGRAMS:
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
- -e 's/$$/$(EXEEXT)/' `; \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(sbindir)" && rm -f $$files
@@ -1035,15 +1127,19 @@ clean-sbinPROGRAMS:
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
+
lemon$(EXEEXT): $(lemon_OBJECTS) $(lemon_DEPENDENCIES) $(EXTRA_lemon_DEPENDENCIES)
@rm -f lemon$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(lemon_OBJECTS) $(lemon_LDADD) $(LIBS)
+
lighttpd$(EXEEXT): $(lighttpd_OBJECTS) $(lighttpd_DEPENDENCIES) $(EXTRA_lighttpd_DEPENDENCIES)
@rm -f lighttpd$(EXEEXT)
$(AM_V_CCLD)$(lighttpd_LINK) $(lighttpd_OBJECTS) $(lighttpd_LDADD) $(LIBS)
+
lighttpd-angel$(EXEEXT): $(lighttpd_angel_OBJECTS) $(lighttpd_angel_DEPENDENCIES) $(EXTRA_lighttpd_angel_DEPENDENCIES)
@rm -f lighttpd-angel$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(lighttpd_angel_OBJECTS) $(lighttpd_angel_LDADD) $(LIBS)
+
proc_open$(EXEEXT): $(proc_open_OBJECTS) $(proc_open_DEPENDENCIES) $(EXTRA_proc_open_DEPENDENCIES)
@rm -f proc_open$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(proc_open_OBJECTS) $(proc_open_LDADD) $(LIBS)
@@ -1190,14 +1286,14 @@ distclean-compile:
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -1569,26 +1665,15 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- mkid -fID $$unique
-tags: TAGS
-
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
+ $(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
@@ -1600,15 +1685,11 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$$unique; \
fi; \
fi
-ctags: CTAGS
-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
@@ -1617,6 +1698,21 @@ GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
@@ -1766,20 +1862,20 @@ uninstall-am: uninstall-libLTLIBRARIES uninstall-sbinPROGRAMS
.MAKE: all check install install-am install-strip
-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-libLTLIBRARIES clean-libtool clean-noinstPROGRAMS \
- clean-sbinPROGRAMS ctags distclean distclean-compile \
- distclean-generic distclean-libtool distclean-tags distdir dvi \
- dvi-am html html-am info info-am install install-am \
- install-data install-data-am install-dvi install-dvi-am \
- install-exec install-exec-am install-html install-html-am \
- install-info install-info-am install-libLTLIBRARIES \
- install-man install-pdf install-pdf-am install-ps \
- install-ps-am install-sbinPROGRAMS install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
+ clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-libLTLIBRARIES install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-sbinPROGRAMS install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-libLTLIBRARIES \
+ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES \
uninstall-sbinPROGRAMS
diff --git a/src/base.h b/src/base.h
index 9c75cc9..66710f1 100644
--- a/src/base.h
+++ b/src/base.h
@@ -278,6 +278,7 @@ typedef struct {
buffer *ssl_dh_file;
buffer *ssl_ec_curve;
unsigned short ssl_honor_cipher_order; /* determine SSL cipher in server-preferred order, not client-order */
+ unsigned short ssl_empty_fragments; /* whether to not set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */
unsigned short ssl_use_sslv2;
unsigned short ssl_use_sslv3;
unsigned short ssl_verifyclient;
@@ -289,7 +290,7 @@ typedef struct {
unsigned short use_ipv6, set_v6only; /* set_v6only is only a temporary option */
unsigned short defer_accept;
- unsigned short is_ssl;
+ unsigned short ssl_enabled; /* only interesting for setting up listening sockets. don't use at runtime */
unsigned short allow_http11;
unsigned short etag_use_inode;
unsigned short etag_use_mtime;
@@ -410,7 +411,6 @@ typedef struct {
size_t header_len;
- buffer *authed_user;
array *environment; /* used to pass lighttpd internal stuff to the FastCGI/CGI apps, setenv does that */
/* response */
@@ -432,7 +432,7 @@ typedef struct {
int error_handler_saved_status;
int in_error_handler;
- void *srv_socket; /* reference to the server-socket (typecast to server_socket) */
+ struct server_socket *srv_socket; /* reference to the server-socket */
#ifdef USE_OPENSSL
SSL *ssl;
@@ -525,7 +525,7 @@ typedef struct {
unsigned short reject_expect_100_with_417;
} server_config;
-typedef struct {
+typedef struct server_socket {
sock_addr addr;
int fd;
int fde_ndx;
@@ -545,7 +545,6 @@ typedef struct {
#ifdef USE_OPENSSL
SSL_CTX *ssl_ctx;
#endif
- unsigned short is_proxy_ssl;
} server_socket;
typedef struct {
diff --git a/src/buffer.c b/src/buffer.c
index cff44fe..eea7041 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -7,6 +7,11 @@
#include <assert.h>
#include <ctype.h>
+#if defined HAVE_STDINT_H
+# include <stdint.h>
+#elif defined HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
static const char hex_chars[] = "0123456789abcdef";
@@ -533,60 +538,38 @@ int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) {
return buffer_is_equal(a, &b);
}
-/* simple-assumption:
- *
- * most parts are equal and doing a case conversion needs time
- *
- */
-int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) {
- size_t ndx = 0, max_ndx;
- size_t *al, *bl;
- size_t mask = sizeof(*al) - 1;
-
- al = (size_t *)a;
- bl = (size_t *)b;
+/* buffer_is_equal_caseless_string(b, CONST_STR_LEN("value")) */
+int buffer_is_equal_caseless_string(buffer *a, const char *s, size_t b_len) {
+ if (a->used != b_len + 1) return 0;
- /* is the alignment correct ? */
- if ( ((size_t)al & mask) == 0 &&
- ((size_t)bl & mask) == 0 ) {
-
- max_ndx = ((a_len < b_len) ? a_len : b_len) & ~mask;
-
- for (; ndx < max_ndx; ndx += sizeof(*al)) {
- if (*al != *bl) break;
- al++; bl++;
-
- }
-
- }
-
- a = (char *)al;
- b = (char *)bl;
-
- max_ndx = ((a_len < b_len) ? a_len : b_len);
+ return (0 == strcasecmp(a->ptr, s));
+}
- for (; ndx < max_ndx; ndx++) {
- int a1 = *a++, b1 = *b++;
+int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) {
+ size_t const len = (a_len < b_len) ? a_len : b_len;
+ size_t i;
- if (a1 != b1) {
- /* always lowercase for transitive results */
- if (a1 >= 'A' && a1 <= 'Z') a1 |= 32;
- if (b1 >= 'A' && b1 <= 'Z') b1 |= 32;
+ for (i = 0; i < len; ++i) {
+ unsigned char ca = a[i], cb = b[i];
+ if (ca == cb) continue;
+
+ /* always lowercase for transitive results */
+#if 1
+ if (ca >= 'A' && ca <= 'Z') ca |= 32;
+ if (cb >= 'A' && cb <= 'Z') cb |= 32;
+#else
+ /* try to produce code without branching (jumps) */
+ ca |= ((unsigned char)(ca - (unsigned char)'A') <= (unsigned char)('Z' - 'A')) ? 32 : 0;
+ cb |= ((unsigned char)(cb - (unsigned char)'A') <= (unsigned char)('Z' - 'A')) ? 32 : 0;
+#endif
- if ((a1 - b1) != 0) return (a1 - b1);
- }
+ if (ca == cb) continue;
+ return ca - cb;
}
-
- /* all chars are the same, and the length match too
- *
- * they are the same */
if (a_len == b_len) return 0;
-
- /* if a is shorter then b, then b is larger */
- return (a_len - b_len);
+ return a_len - b_len;
}
-
/**
* check if the rightmost bytes of the string are equal.
*
diff --git a/src/buffer.h b/src/buffer.h
index bda0424..c381652 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -82,6 +82,7 @@ int buffer_is_empty(buffer *b);
int buffer_is_equal(buffer *a, buffer *b);
int buffer_is_equal_right_len(buffer *a, buffer *b, size_t len);
int buffer_is_equal_string(buffer *a, const char *s, size_t b_len);
+int buffer_is_equal_caseless_string(buffer *a, const char *s, size_t b_len);
int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len);
typedef enum {
diff --git a/src/configfile.c b/src/configfile.c
index bb71b95..7408ed0 100644
--- a/src/configfile.c
+++ b/src/configfile.c
@@ -107,6 +107,7 @@ static int config_insert(server *srv) {
{ "ssl.ec-curve", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 64 */
{ "ssl.disable-client-renegotiation", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },/* 65 */
{ "ssl.honor-cipher-order", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 66 */
+ { "ssl.empty-fragments", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 67 */
{ "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
{ "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
@@ -177,8 +178,9 @@ static int config_insert(server *srv) {
s->max_read_idle = 60;
s->max_write_idle = 360;
s->use_xattr = 0;
- s->is_ssl = 0;
+ s->ssl_enabled = 0;
s->ssl_honor_cipher_order = 1;
+ s->ssl_empty_fragments = 0;
s->ssl_use_sslv2 = 0;
s->ssl_use_sslv3 = 1;
s->use_ipv6 = 0;
@@ -231,7 +233,7 @@ static int config_insert(server *srv) {
cv[27].destination = &(s->use_xattr);
cv[28].destination = s->mimetypes;
cv[29].destination = s->ssl_pemfile;
- cv[30].destination = &(s->is_ssl);
+ cv[30].destination = &(s->ssl_enabled);
cv[31].destination = &(s->log_file_not_found);
cv[32].destination = &(s->log_request_handling);
@@ -250,6 +252,7 @@ static int config_insert(server *srv) {
cv[63].destination = s->ssl_dh_file;
cv[64].destination = s->ssl_ec_curve;
cv[66].destination = &(s->ssl_honor_cipher_order);
+ cv[67].destination = &(s->ssl_empty_fragments);
cv[49].destination = &(s->etag_use_inode);
cv[50].destination = &(s->etag_use_mtime);
@@ -332,7 +335,7 @@ int config_setup_connection(server *srv, connection *con) {
PATCH(range_requests);
PATCH(force_lowercase_filenames);
- PATCH(is_ssl);
+ PATCH(ssl_enabled);
PATCH(ssl_pemfile);
#ifdef USE_OPENSSL
@@ -343,6 +346,7 @@ int config_setup_connection(server *srv, connection *con) {
PATCH(ssl_dh_file);
PATCH(ssl_ec_curve);
PATCH(ssl_honor_cipher_order);
+ PATCH(ssl_empty_fragments);
PATCH(ssl_use_sslv2);
PATCH(ssl_use_sslv3);
PATCH(etag_use_inode);
@@ -411,6 +415,8 @@ int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
PATCH(ssl_ca_file);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.honor-cipher-order"))) {
PATCH(ssl_honor_cipher_order);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.empty-fragments"))) {
+ PATCH(ssl_empty_fragments);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv2"))) {
PATCH(ssl_use_sslv2);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv3"))) {
@@ -418,7 +424,7 @@ int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.cipher-list"))) {
PATCH(ssl_cipher_list);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.engine"))) {
- PATCH(is_ssl);
+ PATCH(ssl_enabled);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.dh-file"))) {
PATCH(ssl_dh_file);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ec-curve"))) {
@@ -1235,33 +1241,24 @@ int config_set_defaults(server *srv) {
{ FDEVENT_HANDLER_UNSET, NULL }
};
-
- if (buffer_is_empty(s->document_root)) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "a default document-root has to be set");
-
- return -1;
- }
-
- if (buffer_is_empty(srv->srvconf.changeroot)) {
- if (-1 == stat(s->document_root->ptr, &st1)) {
+ if (!buffer_is_empty(srv->srvconf.changeroot)) {
+ if (-1 == stat(srv->srvconf.changeroot->ptr, &st1)) {
log_error_write(srv, __FILE__, __LINE__, "sb",
- "base-docroot doesn't exist:",
- s->document_root);
+ "server.chroot doesn't exist:", srv->srvconf.changeroot);
return -1;
}
-
- } else {
- buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.changeroot);
- buffer_append_string_buffer(srv->tmp_buf, s->document_root);
-
- if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
+ if (!S_ISDIR(st1.st_mode)) {
log_error_write(srv, __FILE__, __LINE__, "sb",
- "base-docroot doesn't exist:",
- srv->tmp_buf);
+ "server.chroot isn't a directory:", srv->srvconf.changeroot);
return -1;
}
+ }
+
+ if (buffer_is_empty(s->document_root)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "a default document-root has to be set");
+ return -1;
}
buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
@@ -1306,7 +1303,7 @@ int config_set_defaults(server *srv) {
}
if (srv->srvconf.port == 0) {
- srv->srvconf.port = s->is_ssl ? 443 : 80;
+ srv->srvconf.port = s->ssl_enabled ? 443 : 80;
}
if (srv->srvconf.event_handler->used == 0) {
@@ -1344,7 +1341,7 @@ int config_set_defaults(server *srv) {
}
}
- if (s->is_ssl) {
+ if (s->ssl_enabled) {
if (buffer_is_empty(s->ssl_pemfile)) {
/* PEM file is require */
diff --git a/src/connections.c b/src/connections.c
index 48ca60f..8a2774d 100644
--- a/src/connections.c
+++ b/src/connections.c
@@ -200,7 +200,7 @@ static int connection_handle_read_ssl(server *srv, connection *con) {
int r, ssl_err, len, count = 0, read_offset, toread;
buffer *b = NULL;
- if (!con->conf.is_ssl) return -1;
+ if (!con->srv_socket->is_ssl) return -1;
ERR_clear_error();
do {
@@ -224,8 +224,8 @@ static int connection_handle_read_ssl(server *srv, connection *con) {
len = SSL_read(con->ssl, b->ptr + read_offset, toread);
if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection");
connection_set_state(srv, con, CON_STATE_ERROR);
- log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client");
return -1;
}
@@ -334,7 +334,7 @@ static int connection_handle_read(server *srv, connection *con) {
buffer *b;
int toread, read_offset;
- if (con->conf.is_ssl) {
+ if (con->srv_socket->is_ssl) {
return connection_handle_read_ssl(srv, con);
}
@@ -419,16 +419,6 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
case HTTP_METHOD_GET:
case HTTP_METHOD_POST:
case HTTP_METHOD_HEAD:
- case HTTP_METHOD_PUT:
- case HTTP_METHOD_PATCH:
- case HTTP_METHOD_MKCOL:
- case HTTP_METHOD_DELETE:
- case HTTP_METHOD_COPY:
- case HTTP_METHOD_MOVE:
- case HTTP_METHOD_PROPFIND:
- case HTTP_METHOD_PROPPATCH:
- case HTTP_METHOD_LOCK:
- case HTTP_METHOD_UNLOCK:
break;
case HTTP_METHOD_OPTIONS:
/*
@@ -450,16 +440,8 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
}
break;
default:
- switch(con->http_status) {
- case 400: /* bad request */
- case 401: /* authorization required */
- case 414: /* overload request header */
- case 505: /* unknown protocol */
- case 207: /* this was webdav */
- break;
- default:
+ if (0 == con->http_status) {
con->http_status = 501;
- break;
}
break;
}
@@ -694,7 +676,6 @@ connection *connection_init(server *srv) {
CLEAN(physical.etag);
CLEAN(parse_request);
- CLEAN(authed_user);
CLEAN(server_name);
CLEAN(error_handler);
CLEAN(dst_addr_buf);
@@ -761,7 +742,6 @@ void connections_free(server *srv) {
CLEAN(physical.rel_path);
CLEAN(parse_request);
- CLEAN(authed_user);
CLEAN(server_name);
CLEAN(error_handler);
CLEAN(dst_addr_buf);
@@ -835,7 +815,6 @@ int connection_reset(server *srv, connection *con) {
CLEAN(parse_request);
- CLEAN(authed_user);
CLEAN(server_name);
CLEAN(error_handler);
#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
@@ -1192,7 +1171,7 @@ static handler_t connection_handle_fdevent(server *srv, void *context, int reven
joblist_append(srv, con);
- if (con->conf.is_ssl) {
+ if (con->srv_socket->is_ssl) {
/* ssl may read and write for both reads and writes */
if (revents & (FDEVENT_IN | FDEVENT_OUT)) {
con->is_readable = 1;
@@ -1363,7 +1342,6 @@ connection *connection_accept(server *srv, server_socket *srv_socket) {
con->renegotiations = 0;
SSL_set_app_data(con->ssl, con);
SSL_set_accept_state(con->ssl);
- con->conf.is_ssl=1;
if (1 != (SSL_set_fd(con->ssl, cnt))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
@@ -1408,12 +1386,6 @@ int connection_state_machine(server *srv, connection *con) {
connection_set_state(srv, con, CON_STATE_READ);
- /* patch con->conf.is_ssl if the connection is a ssl-socket already */
-
-#ifdef USE_OPENSSL
- con->conf.is_ssl = srv_sock->is_ssl;
-#endif
-
break;
case CON_STATE_REQUEST_END: /* transient */
if (srv->srvconf.log_state_handling) {
@@ -1736,8 +1708,8 @@ int connection_state_machine(server *srv, connection *con) {
break;
}
}
+ ERR_clear_error();
}
- ERR_clear_error();
#endif
switch(con->mode) {
diff --git a/src/fdevent_libev.c b/src/fdevent_libev.c
index de62676..f6f6b63 100644
--- a/src/fdevent_libev.c
+++ b/src/fdevent_libev.c
@@ -87,19 +87,28 @@ static void timeout_watcher_cb(struct ev_loop *loop, ev_timer *w, int revents) {
UNUSED(loop);
UNUSED(w);
UNUSED(revents);
+
+ ev_timer_stop(loop, w);
}
static int fdevent_libev_poll(fdevents *ev, int timeout_ms) {
- ev_timer timeout_watcher;
+ union {
+ struct ev_watcher w;
+ struct ev_timer timer;
+ } timeout_watcher;
+
+ if (!timeout_ms) timeout_ms = 1;
- ev_init(&timeout_watcher, timeout_watcher_cb);
- ev_timer_set(&timeout_watcher, ((ev_tstamp) timeout_ms)/1000.0, 0.0);
- ev_timer_start(ev->libev_loop, &timeout_watcher);
+ ev_init(&timeout_watcher.w, NULL);
+ ev_set_cb(&timeout_watcher.timer, timeout_watcher_cb);
+ timeout_watcher.timer.repeat = ((ev_tstamp) timeout_ms)/1000.0;
+ assert(timeout_watcher.timer.repeat);
+ ev_timer_again(ev->libev_loop, &timeout_watcher.timer);
ev_loop(ev->libev_loop, EVLOOP_ONESHOT);
- ev_timer_stop(ev->libev_loop, &timeout_watcher);
+ ev_timer_stop(ev->libev_loop, &timeout_watcher.timer);
return 0;
}
diff --git a/src/http-header-glue.c b/src/http-header-glue.c
index a33ed3b..fe2f4fb 100644
--- a/src/http-header-glue.c
+++ b/src/http-header-glue.c
@@ -123,11 +123,8 @@ int http_response_redirect_to_directory(server *srv, connection *con) {
o = buffer_init();
- if (con->conf.is_ssl) {
- buffer_copy_string_len(o, CONST_STR_LEN("https://"));
- } else {
- buffer_copy_string_len(o, CONST_STR_LEN("http://"));
- }
+ buffer_copy_string_buffer(o, con->uri.scheme);
+ buffer_append_string_len(o, CONST_STR_LEN("://"));
if (con->uri.authority->used) {
buffer_append_string_buffer(o, con->uri.authority);
} else {
@@ -193,10 +190,15 @@ int http_response_redirect_to_directory(server *srv, connection *con) {
return -1;
}
- if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
- (con->conf.is_ssl == 1 && srv->srvconf.port == 443))) {
- buffer_append_string_len(o, CONST_STR_LEN(":"));
- buffer_append_long(o, srv->srvconf.port);
+ {
+ unsigned short default_port = 80;
+ if (buffer_is_equal_caseless_string(con->uri.scheme, CONST_STR_LEN("https"))) {
+ default_port = 443;
+ }
+ if (default_port != srv->srvconf.port) {
+ buffer_append_string_len(o, CONST_STR_LEN(":"));
+ buffer_append_long(o, srv->srvconf.port);
+ }
}
}
buffer_append_string_buffer(o, con->uri.path);
@@ -245,6 +247,7 @@ buffer * strftime_cache_get(server *srv, time_t last_mod) {
int http_response_handle_cachable(server *srv, connection *con, buffer *mtime) {
+ UNUSED(srv);
/*
* 14.26 If-None-Match
* [...]
@@ -261,68 +264,17 @@ int http_response_handle_cachable(server *srv, connection *con, buffer *mtime) {
if (con->request.http_method == HTTP_METHOD_GET ||
con->request.http_method == HTTP_METHOD_HEAD) {
- /* check if etag + last-modified */
- if (con->request.http_if_modified_since) {
- size_t used_len;
- char *semicolon;
-
- if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
- used_len = strlen(con->request.http_if_modified_since);
- } else {
- used_len = semicolon - con->request.http_if_modified_since;
- }
-
- if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
- if ('\0' == mtime->ptr[used_len]) con->http_status = 304;
- return HANDLER_FINISHED;
- } else {
- char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
- time_t t_header, t_file;
- struct tm tm;
-
- /* check if we can safely copy the string */
- if (used_len >= sizeof(buf)) {
- log_error_write(srv, __FILE__, __LINE__, "ssdd",
- "DEBUG: Last-Modified check failed as the received timestamp was too long:",
- con->request.http_if_modified_since, used_len, sizeof(buf) - 1);
-
- con->http_status = 412;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
-
- strncpy(buf, con->request.http_if_modified_since, used_len);
- buf[used_len] = '\0';
-
- if (NULL == strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm)) {
- con->http_status = 412;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
- tm.tm_isdst = 0;
- t_header = mktime(&tm);
-
- strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
- tm.tm_isdst = 0;
- t_file = mktime(&tm);
-
- if (t_file > t_header) return HANDLER_GO_ON;
-
- con->http_status = 304;
- return HANDLER_FINISHED;
- }
- } else {
- con->http_status = 304;
- return HANDLER_FINISHED;
- }
+ con->http_status = 304;
+ return HANDLER_FINISHED;
} else {
con->http_status = 412;
con->mode = DIRECT;
return HANDLER_FINISHED;
}
}
- } else if (con->request.http_if_modified_since) {
+ } else if (con->request.http_if_modified_since &&
+ (con->request.http_method == HTTP_METHOD_GET ||
+ con->request.http_method == HTTP_METHOD_HEAD)) {
size_t used_len;
char *semicolon;
diff --git a/src/http_auth.c b/src/http_auth.c
index d7d246b..f8fb3fc 100644
--- a/src/http_auth.c
+++ b/src/http_auth.c
@@ -29,6 +29,10 @@
#include "md5.h"
+#ifdef USE_OPENSSL
+#include <openssl/sha.h>
+#endif
+
#define HASHLEN 16
#define HASHHEXLEN 32
typedef unsigned char HASH[HASHLEN];
@@ -87,7 +91,8 @@ static const short base64_reverse_table[256] = {
static unsigned char * base64_decode(buffer *out, const char *in) {
unsigned char *result;
- int ch, j = 0, k;
+ unsigned int j = 0; /* current output character (position) that is decoded. can contain partial result */
+ unsigned int group = 0; /* how many base64 digits in the current group were decoded already. each group has up to 4 digits */
size_t i;
size_t in_len = strlen(in);
@@ -96,51 +101,64 @@ static unsigned char * base64_decode(buffer *out, const char *in) {
result = (unsigned char *)out->ptr;
- ch = in[0];
/* run through the whole string, converting as we go */
for (i = 0; i < in_len; i++) {
- ch = (unsigned char) in[i];
+ unsigned char c = (unsigned char) in[i];
+ short ch;
- if (ch == '\0') break;
+ if (c == '\0') break;
- if (ch == base64_pad) break;
+ if (c == base64_pad) {
+ /* pad character can only come after 2 base64 digits in a group */
+ if (group < 2) return NULL;
+ break;
+ }
- ch = base64_reverse_table[ch];
- if (ch < 0) continue;
+ ch = base64_reverse_table[c];
+ if (ch < 0) continue; /* skip invalid characters */
- switch(i % 4) {
+ switch(group) {
case 0:
result[j] = ch << 2;
+ group = 1;
break;
case 1:
result[j++] |= ch >> 4;
result[j] = (ch & 0x0f) << 4;
+ group = 2;
break;
case 2:
result[j++] |= ch >>2;
result[j] = (ch & 0x03) << 6;
+ group = 3;
break;
case 3:
result[j++] |= ch;
+ group = 0;
break;
}
}
- k = j;
- /* mop things up if we ended on a boundary */
- if (ch == base64_pad) {
- switch(i % 4) {
- case 0:
- case 1:
- return NULL;
- case 2:
- k++;
- case 3:
- result[k++] = 0;
- }
+
+ switch(group) {
+ case 0:
+ /* ended on boundary */
+ break;
+ case 1:
+ /* need at least 2 base64 digits per group */
+ return NULL;
+ case 2:
+ /* have 2 base64 digits in last group => one real octect, two zeroes padded */
+ case 3:
+ /* have 3 base64 digits in last group => two real octects, one zero padded */
+
+ /* for both cases the current index already is on the first zero padded octet
+ * - check it really is zero (overlapping bits) */
+ if (0 != result[j]) return NULL;
+ break;
}
- result[k] = '\0';
- out->used = k;
+ result[j] = '\0';
+ out->used = j;
return result;
}
@@ -304,32 +322,14 @@ static int http_auth_get_password(server *srv, mod_auth_plugin_data *p, buffer *
return ret;
}
-static int http_auth_match_rules(server *srv, mod_auth_plugin_data *p, const char *url, const char *username, const char *group, const char *host) {
+int http_auth_match_rules(server *srv, array *req, const char *username, const char *group, const char *host) {
const char *r = NULL, *rules = NULL;
- size_t i;
int username_len;
data_string *require;
- array *req;
UNUSED(group);
UNUSED(host);
- /* check what has to be match to fullfil the request */
- /* search auth-directives for path */
- for (i = 0; i < p->conf.auth_require->used; i++) {
- if (p->conf.auth_require->data[i]->key->used == 0) continue;
-
- if (0 == strncmp(url, p->conf.auth_require->data[i]->key->ptr, p->conf.auth_require->data[i]->key->used - 1)) {
- break;
- }
- }
-
- if (i == p->conf.auth_require->used) {
- return -1;
- }
-
- req = ((data_array *)(p->conf.auth_require->data[i]))->value;
-
require = (data_string *)array_get_element(req, "require");
/* if we get here, the user we got a authed user */
@@ -599,6 +599,35 @@ static void apr_md5_encode(const char *pw, const char *salt, char *result, size_
apr_cpystrn(result, passwd, nbytes - 1);
}
+#ifdef USE_OPENSSL
+static void apr_sha_encode(const char *pw, char *result, size_t nbytes) {
+ static const unsigned char base64_data[65] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ unsigned char digest[21]; /* multiple of 3 for base64 encoding */
+ int i;
+
+ memset(result, 0, nbytes);
+
+ /* need 5 bytes for "{SHA}", 28 for base64 (3 bytes -> 4 bytes) of SHA1 (20 bytes), 1 terminating */
+ if (nbytes < 5 + 28 + 1) return;
+
+ SHA1((const unsigned char*) pw, strlen(pw), digest);
+ digest[20] = 0;
+
+ strcpy(result, "{SHA}");
+ result = result + 5;
+ for (i = 0; i < 21; i += 3) {
+ unsigned int v = (digest[i] << 16) | (digest[i+1] << 8) | digest[i+2];
+ result[3] = base64_data[v & 0x3f]; v >>= 6;
+ result[2] = base64_data[v & 0x3f]; v >>= 6;
+ result[1] = base64_data[v & 0x3f]; v >>= 6;
+ result[0] = base64_data[v & 0x3f];
+ result += 4;
+ }
+ result[-1] = '='; /* last digest character was already end of string, pad it */
+ *result = '\0';
+}
+#endif
/**
*
@@ -643,58 +672,30 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p
*/
apr_md5_encode(pw, password->ptr, sample, sizeof(sample));
return (strcmp(sample, password->ptr) == 0) ? 0 : 1;
+#ifdef USE_OPENSSL
+ } else if (0 == strncmp(password->ptr, "{SHA}", 5)) {
+ apr_sha_encode(pw, sample, sizeof(sample));
+ return (strcmp(sample, password->ptr) == 0) ? 0 : 1;
+#endif
} else {
#ifdef HAVE_CRYPT
- char salt[32];
- char *crypted;
- size_t salt_len = 0;
- /*
- * htpasswd format
- *
- * user:crypted password
- */
-
- /*
- * Algorithm Salt
- * CRYPT_STD_DES 2-character (Default)
- * CRYPT_EXT_DES 9-character
- * CRYPT_MD5 12-character beginning with $1$
- * CRYPT_BLOWFISH 16-character beginning with $2$
- */
-
- if (password->used < 13 + 1) {
- return -1;
- }
-
- if (password->used == 13 + 1) {
- /* a simple DES password is 2 + 11 characters */
- salt_len = 2;
- } else if (password->ptr[0] == '$' && password->ptr[2] == '$') {
- char *dollar = NULL;
+ char *crypted;
- if (NULL == (dollar = strchr(password->ptr + 3, '$'))) {
+ /* a simple DES password is 2 + 11 characters. everything else should be longer. */
+ if (password->used < 13 + 1) {
return -1;
}
- salt_len = dollar - password->ptr;
- }
-
- if (salt_len > sizeof(salt) - 1) {
- return -1;
- }
-
- strncpy(salt, password->ptr, salt_len);
-
- salt[salt_len] = '\0';
-
- crypted = crypt(pw, salt);
-
- if (0 == strcmp(password->ptr, crypted)) {
- return 0;
- }
+ if (0 == (crypted = crypt(pw, password->ptr))) {
+ /* crypt failed. */
+ return -1;
+ }
+ if (0 == strcmp(password->ptr, crypted)) {
+ return 0;
+ }
#endif
- }
+ }
} else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
if (0 == strcmp(password->ptr, pw)) {
return 0;
@@ -836,7 +837,7 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p
return -1;
}
-int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
+int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, const char *realm_str) {
buffer *username, *password;
char *pw;
@@ -891,7 +892,7 @@ int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p,
}
/* value is our allow-rules */
- if (http_auth_match_rules(srv, p, url->ptr, username->ptr, NULL, NULL)) {
+ if (http_auth_match_rules(srv, req, username->ptr, NULL, NULL)) {
buffer_free(username);
buffer_free(password);
@@ -915,7 +916,8 @@ typedef struct {
char **ptr;
} digest_kv;
-int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
+/* return values: -1: error/bad request, 0: failed, 1: success */
+int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, const char *realm_str) {
char a1[256];
char a2[256];
@@ -1052,6 +1054,14 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p
return -1;
}
+ if (qop && strcasecmp(qop, "auth-int") == 0) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "digest: qop=auth-int not supported");
+
+ buffer_free(b);
+ return -1;
+ }
+
m = get_http_method_name(con->request.http_method);
/* password-string == HA1 */
@@ -1112,10 +1122,13 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p
li_MD5_Update(&Md5Ctx, (unsigned char *)m, strlen(m));
li_MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
li_MD5_Update(&Md5Ctx, (unsigned char *)uri, strlen(uri));
+ /* qop=auth-int not supported, already checked above */
+/*
if (qop && strcasecmp(qop, "auth-int") == 0) {
li_MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
- li_MD5_Update(&Md5Ctx, (unsigned char *)"", HASHHEXLEN);
+ li_MD5_Update(&Md5Ctx, (unsigned char *) [body checksum], HASHHEXLEN);
}
+*/
li_MD5_Final(HA2, &Md5Ctx);
CvtHex(HA2, HA2Hex);
@@ -1153,7 +1166,7 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p
}
/* value is our allow-rules */
- if (http_auth_match_rules(srv, p, url->ptr, username, NULL, NULL)) {
+ if (http_auth_match_rules(srv, req, username, NULL, NULL)) {
buffer_free(b);
log_error_write(srv, __FILE__, __LINE__, "s",
diff --git a/src/http_auth.h b/src/http_auth.h
index 5828a7e..081cef3 100644
--- a/src/http_auth.h
+++ b/src/http_auth.h
@@ -66,8 +66,9 @@ typedef struct {
mod_auth_plugin_config conf, *anon_conf; /* this is only used as long as no handler_ctx is setup */
} mod_auth_plugin_data;
-int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str);
-int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str);
+int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, const char *realm_str);
+int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, const char *realm_str);
int http_auth_digest_generate_nonce(server *srv, mod_auth_plugin_data *p, buffer *fn, char hh[33]);
+int http_auth_match_rules(server *srv, array *req, const char *username, const char *group, const char *host);
#endif
diff --git a/src/keyvalue.c b/src/keyvalue.c
index ba37611..5f15c28 100644
--- a/src/keyvalue.c
+++ b/src/keyvalue.c
@@ -13,29 +13,44 @@ static keyvalue http_versions[] = {
};
static keyvalue http_methods[] = {
- { HTTP_METHOD_GET, "GET" },
- { HTTP_METHOD_POST, "POST" },
+ { HTTP_METHOD_GET, "GET" },
{ HTTP_METHOD_HEAD, "HEAD" },
- { HTTP_METHOD_PROPFIND, "PROPFIND" },
- { HTTP_METHOD_PROPPATCH, "PROPPATCH" },
- { HTTP_METHOD_REPORT, "REPORT" },
- { HTTP_METHOD_OPTIONS, "OPTIONS" },
- { HTTP_METHOD_MKCOL, "MKCOL" },
+ { HTTP_METHOD_POST, "POST" },
{ HTTP_METHOD_PUT, "PUT" },
- { HTTP_METHOD_PATCH, "PATCH" },
{ HTTP_METHOD_DELETE, "DELETE" },
+ { HTTP_METHOD_CONNECT, "CONNECT" },
+ { HTTP_METHOD_OPTIONS, "OPTIONS" },
+ { HTTP_METHOD_TRACE, "TRACE" },
+ { HTTP_METHOD_ACL, "ACL" },
+ { HTTP_METHOD_BASELINE_CONTROL, "BASELINE-CONTROL" },
+ { HTTP_METHOD_BIND, "BIND" },
+ { HTTP_METHOD_CHECKIN, "CHECKIN" },
+ { HTTP_METHOD_CHECKOUT, "CHECKOUT" },
{ HTTP_METHOD_COPY, "COPY" },
- { HTTP_METHOD_MOVE, "MOVE" },
{ HTTP_METHOD_LABEL, "LABEL" },
- { HTTP_METHOD_CHECKOUT, "CHECKOUT" },
- { HTTP_METHOD_CHECKIN, "CHECKIN" },
- { HTTP_METHOD_MERGE, "MERGE" },
+ { HTTP_METHOD_LINK, "LINK" },
{ HTTP_METHOD_LOCK, "LOCK" },
- { HTTP_METHOD_UNLOCK, "UNLOCK" },
+ { HTTP_METHOD_MERGE, "MERGE" },
{ HTTP_METHOD_MKACTIVITY, "MKACTIVITY" },
+ { HTTP_METHOD_MKCALENDAR, "MKCALENDAR" },
+ { HTTP_METHOD_MKCOL, "MKCOL" },
+ { HTTP_METHOD_MKREDIRECTREF, "MKREDIRECTREF" },
+ { HTTP_METHOD_MKWORKSPACE, "MKWORKSPACE" },
+ { HTTP_METHOD_MOVE, "MOVE" },
+ { HTTP_METHOD_ORDERPATCH, "ORDERPATCH" },
+ { HTTP_METHOD_PATCH, "PATCH" },
+ { HTTP_METHOD_PROPFIND, "PROPFIND" },
+ { HTTP_METHOD_PROPPATCH, "PROPPATCH" },
+ { HTTP_METHOD_REBIND, "REBIND" },
+ { HTTP_METHOD_REPORT, "REPORT" },
+ { HTTP_METHOD_SEARCH, "SEARCH" },
+ { HTTP_METHOD_UNBIND, "UNBIND" },
{ HTTP_METHOD_UNCHECKOUT, "UNCHECKOUT" },
+ { HTTP_METHOD_UNLINK, "UNLINK" },
+ { HTTP_METHOD_UNLOCK, "UNLOCK" },
+ { HTTP_METHOD_UPDATE, "UPDATE" },
+ { HTTP_METHOD_UPDATEREDIRECTREF, "UPDATEREDIRECTREF" },
{ HTTP_METHOD_VERSION_CONTROL, "VERSION-CONTROL" },
- { HTTP_METHOD_CONNECT, "CONNECT" },
{ HTTP_METHOD_UNSET, NULL }
};
diff --git a/src/keyvalue.h b/src/keyvalue.h
index 43ef99b..3a08e02 100644
--- a/src/keyvalue.h
+++ b/src/keyvalue.h
@@ -11,31 +11,56 @@
struct server;
+/* sources:
+ * - [RFC2616], Section 9
+ * (or http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-22)
+ * - http://tools.ietf.org/html/draft-ietf-httpbis-method-registrations-11, Appendix A
+ *
+ * http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-22, Section 8.1 defines
+ * a new registry (not available yet):
+ * http://www.iana.org/assignments/http-methods
+ */
+
typedef enum {
HTTP_METHOD_UNSET = -1,
- HTTP_METHOD_GET,
- HTTP_METHOD_POST,
- HTTP_METHOD_HEAD,
- HTTP_METHOD_OPTIONS,
- HTTP_METHOD_PROPFIND, /* WebDAV */
- HTTP_METHOD_MKCOL,
- HTTP_METHOD_PUT,
- HTTP_METHOD_PATCH,
- HTTP_METHOD_DELETE,
- HTTP_METHOD_COPY,
- HTTP_METHOD_MOVE,
- HTTP_METHOD_PROPPATCH,
- HTTP_METHOD_REPORT, /* DeltaV */
- HTTP_METHOD_CHECKOUT,
- HTTP_METHOD_CHECKIN,
- HTTP_METHOD_VERSION_CONTROL,
- HTTP_METHOD_UNCHECKOUT,
- HTTP_METHOD_MKACTIVITY,
- HTTP_METHOD_MERGE,
- HTTP_METHOD_LOCK,
- HTTP_METHOD_UNLOCK,
- HTTP_METHOD_LABEL,
- HTTP_METHOD_CONNECT
+ HTTP_METHOD_GET, /* [RFC2616], Section 9.3 */
+ HTTP_METHOD_HEAD, /* [RFC2616], Section 9.4 */
+ HTTP_METHOD_POST, /* [RFC2616], Section 9.5 */
+ HTTP_METHOD_PUT, /* [RFC2616], Section 9.6 */
+ HTTP_METHOD_DELETE, /* [RFC2616], Section 9.7 */
+ HTTP_METHOD_CONNECT, /* [RFC2616], Section 9.9 */
+ HTTP_METHOD_OPTIONS, /* [RFC2616], Section 9.2 */
+ HTTP_METHOD_TRACE, /* [RFC2616], Section 9.8 */
+ HTTP_METHOD_ACL, /* [RFC3744], Section 8.1 */
+ HTTP_METHOD_BASELINE_CONTROL, /* [RFC3253], Section 12.6 */
+ HTTP_METHOD_BIND, /* [RFC5842], Section 4 */
+ HTTP_METHOD_CHECKIN, /* [RFC3253], Section 4.4 and [RFC3253], Section 9.4 */
+ HTTP_METHOD_CHECKOUT, /* [RFC3253], Section 4.3 and [RFC3253], Section 8.8 */
+ HTTP_METHOD_COPY, /* [RFC4918], Section 9.8 */
+ HTTP_METHOD_LABEL, /* [RFC3253], Section 8.2 */
+ HTTP_METHOD_LINK, /* [RFC2068], Section 19.6.1.2 */
+ HTTP_METHOD_LOCK, /* [RFC4918], Section 9.10 */
+ HTTP_METHOD_MERGE, /* [RFC3253], Section 11.2 */
+ HTTP_METHOD_MKACTIVITY, /* [RFC3253], Section 13.5 */
+ HTTP_METHOD_MKCALENDAR, /* [RFC4791], Section 5.3.1 */
+ HTTP_METHOD_MKCOL, /* [RFC4918], Section 9.3 */
+ HTTP_METHOD_MKREDIRECTREF, /* [RFC4437], Section 6 */
+ HTTP_METHOD_MKWORKSPACE, /* [RFC3253], Section 6.3 */
+ HTTP_METHOD_MOVE, /* [RFC4918], Section 9.9 */
+ HTTP_METHOD_ORDERPATCH, /* [RFC3648], Section 7 */
+ HTTP_METHOD_PATCH, /* [RFC5789], Section 2 */
+ HTTP_METHOD_PROPFIND, /* [RFC4918], Section 9.1 */
+ HTTP_METHOD_PROPPATCH, /* [RFC4918], Section 9.2 */
+ HTTP_METHOD_REBIND, /* [RFC5842], Section 6 */
+ HTTP_METHOD_REPORT, /* [RFC3253], Section 3.6 */
+ HTTP_METHOD_SEARCH, /* [RFC5323], Section 2 */
+ HTTP_METHOD_UNBIND, /* [RFC5842], Section 5 */
+ HTTP_METHOD_UNCHECKOUT, /* [RFC3253], Section 4.5 */
+ HTTP_METHOD_UNLINK, /* [RFC2068], Section 19.6.1.3 */
+ HTTP_METHOD_UNLOCK, /* [RFC4918], Section 9.11 */
+ HTTP_METHOD_UPDATE, /* [RFC3253], Section 7.1 */
+ HTTP_METHOD_UPDATEREDIRECTREF, /* [RFC4437], Section 7 */
+ HTTP_METHOD_VERSION_CONTROL /* [RFC3253], Section 3.5 */
} http_method_t;
typedef enum { HTTP_VERSION_UNSET = -1, HTTP_VERSION_1_0, HTTP_VERSION_1_1 } http_version_t;
diff --git a/src/lemon.c b/src/lemon.c
index c3d72eb..8751737 100644
--- a/src/lemon.c
+++ b/src/lemon.c
@@ -3105,7 +3105,7 @@ int mhflag; /* True if generating makeheaders output */
stddt[j] = 0;
hash = 0;
for(j=0; stddt[j]; j++){
- hash = hash*53 + stddt[j];
+ hash = (unsigned int)hash*53u + (unsigned int) stddt[j];
}
hash = (hash & 0x7fffffff)%arraysize;
while( types[hash] ){
@@ -3751,8 +3751,8 @@ char *s2;
PRIVATE int strhash(x)
char *x;
{
- int h = 0;
- while( *x) h = h*13 + *(x++);
+ unsigned int h = 0;
+ while( *x) h = h*13u + (unsigned int) *(x++);
return h;
}
@@ -4124,9 +4124,9 @@ struct config *b;
PRIVATE int statehash(a)
struct config *a;
{
- int h=0;
+ unsigned int h=0;
while( a ){
- h = h*571 + a->rp->index*37 + a->dot;
+ h = h*571u + (unsigned int)a->rp->index*37u + (unsigned int)a->dot;
a = a->bp;
}
return h;
diff --git a/src/log.c b/src/log.c
index 10db635..4778ee8 100644
--- a/src/log.c
+++ b/src/log.c
@@ -263,39 +263,9 @@ int log_error_close(server *srv) {
return 0;
}
-int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
- va_list ap;
-
- switch(srv->errorlog_mode) {
- case ERRORLOG_PIPE:
- case ERRORLOG_FILE:
- case ERRORLOG_FD:
- if (-1 == srv->errorlog_fd) return 0;
- /* cache the generated timestamp */
- if (srv->cur_ts != srv->last_generated_debug_ts) {
- buffer_prepare_copy(srv->ts_debug_str, 255);
- strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
- srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;
-
- srv->last_generated_debug_ts = srv->cur_ts;
- }
-
- buffer_copy_string_buffer(srv->errorlog_buf, srv->ts_debug_str);
- buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(": ("));
- break;
- case ERRORLOG_SYSLOG:
- /* syslog is generating its own timestamps */
- buffer_copy_string_len(srv->errorlog_buf, CONST_STR_LEN("("));
- break;
- }
-
- buffer_append_string(srv->errorlog_buf, filename);
- buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("."));
- buffer_append_long(srv->errorlog_buf, line);
- buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(") "));
-
-
- for(va_start(ap, fmt); *fmt; fmt++) {
+/* lowercase: append space, uppercase: don't */
+static void log_buffer_append_printf(buffer *out, const char *fmt, va_list ap) {
+ for(; *fmt; fmt++) {
int d;
char *s;
buffer *b;
@@ -304,50 +274,50 @@ int log_error_write(server *srv, const char *filename, unsigned int line, const
switch(*fmt) {
case 's': /* string */
s = va_arg(ap, char *);
- buffer_append_string(srv->errorlog_buf, s);
- buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
+ buffer_append_string(out, s);
+ buffer_append_string_len(out, CONST_STR_LEN(" "));
break;
case 'b': /* buffer */
b = va_arg(ap, buffer *);
- buffer_append_string_buffer(srv->errorlog_buf, b);
- buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
+ buffer_append_string_buffer(out, b);
+ buffer_append_string_len(out, CONST_STR_LEN(" "));
break;
case 'd': /* int */
d = va_arg(ap, int);
- buffer_append_long(srv->errorlog_buf, d);
- buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
+ buffer_append_long(out, d);
+ buffer_append_string_len(out, CONST_STR_LEN(" "));
break;
case 'o': /* off_t */
o = va_arg(ap, off_t);
- buffer_append_off_t(srv->errorlog_buf, o);
- buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
+ buffer_append_off_t(out, o);
+ buffer_append_string_len(out, CONST_STR_LEN(" "));
break;
case 'x': /* int (hex) */
d = va_arg(ap, int);
- buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("0x"));
- buffer_append_long_hex(srv->errorlog_buf, d);
- buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
+ buffer_append_string_len(out, CONST_STR_LEN("0x"));
+ buffer_append_long_hex(out, d);
+ buffer_append_string_len(out, CONST_STR_LEN(" "));
break;
case 'S': /* string */
s = va_arg(ap, char *);
- buffer_append_string(srv->errorlog_buf, s);
+ buffer_append_string(out, s);
break;
case 'B': /* buffer */
b = va_arg(ap, buffer *);
- buffer_append_string_buffer(srv->errorlog_buf, b);
+ buffer_append_string_buffer(out, b);
break;
case 'D': /* int */
d = va_arg(ap, int);
- buffer_append_long(srv->errorlog_buf, d);
+ buffer_append_long(out, d);
break;
case 'O': /* off_t */
o = va_arg(ap, off_t);
- buffer_append_off_t(srv->errorlog_buf, o);
+ buffer_append_off_t(out, o);
break;
case 'X': /* int (hex) */
d = va_arg(ap, int);
- buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("0x"));
- buffer_append_long_hex(srv->errorlog_buf, d);
+ buffer_append_string_len(out, CONST_STR_LEN("0x"));
+ buffer_append_long_hex(out, d);
break;
case '(':
case ')':
@@ -355,24 +325,110 @@ int log_error_write(server *srv, const char *filename, unsigned int line, const
case '>':
case ',':
case ' ':
- buffer_append_string_len(srv->errorlog_buf, fmt, 1);
+ buffer_append_string_len(out, fmt, 1);
break;
}
}
- va_end(ap);
+}
+static int log_buffer_prepare(buffer *b, server *srv, const char *filename, unsigned int line) {
switch(srv->errorlog_mode) {
case ERRORLOG_PIPE:
case ERRORLOG_FILE:
case ERRORLOG_FD:
- buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("\n"));
- write(srv->errorlog_fd, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
+ if (-1 == srv->errorlog_fd) return -1;
+ /* cache the generated timestamp */
+ if (srv->cur_ts != srv->last_generated_debug_ts) {
+ buffer_prepare_copy(srv->ts_debug_str, 255);
+ strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
+ srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;
+
+ srv->last_generated_debug_ts = srv->cur_ts;
+ }
+
+ buffer_copy_string_buffer(b, srv->ts_debug_str);
+ buffer_append_string_len(b, CONST_STR_LEN(": ("));
break;
case ERRORLOG_SYSLOG:
- syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
+ /* syslog is generating its own timestamps */
+ buffer_copy_string_len(b, CONST_STR_LEN("("));
break;
}
+ buffer_append_string(b, filename);
+ buffer_append_string_len(b, CONST_STR_LEN("."));
+ buffer_append_long(b, line);
+ buffer_append_string_len(b, CONST_STR_LEN(") "));
+
return 0;
}
+static void log_write(server *srv, buffer *b) {
+ switch(srv->errorlog_mode) {
+ case ERRORLOG_PIPE:
+ case ERRORLOG_FILE:
+ case ERRORLOG_FD:
+ buffer_append_string_len(b, CONST_STR_LEN("\n"));
+ write(srv->errorlog_fd, b->ptr, b->used - 1);
+ break;
+ case ERRORLOG_SYSLOG:
+ syslog(LOG_ERR, "%s", b->ptr);
+ break;
+ }
+}
+
+int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
+ va_list ap;
+
+ if (-1 == log_buffer_prepare(srv->errorlog_buf, srv, filename, line)) return 0;
+
+ va_start(ap, fmt);
+ log_buffer_append_printf(srv->errorlog_buf, fmt, ap);
+ va_end(ap);
+
+ log_write(srv, srv->errorlog_buf);
+
+ return 0;
+}
+
+int log_error_write_multiline_buffer(server *srv, const char *filename, unsigned int line, buffer *multiline, const char *fmt, ...) {
+ va_list ap;
+ size_t prefix_used;
+ buffer *b = srv->errorlog_buf;
+ char *pos, *end, *current_line;
+
+ if (multiline->used < 2) return 0;
+
+ if (-1 == log_buffer_prepare(b, srv, filename, line)) return 0;
+
+ va_start(ap, fmt);
+ log_buffer_append_printf(b, fmt, ap);
+ va_end(ap);
+
+ prefix_used = b->used;
+
+ current_line = pos = multiline->ptr;
+ end = multiline->ptr + multiline->used;
+
+ for ( ; pos < end ; ++pos) {
+ switch (*pos) {
+ case '\n':
+ case '\r':
+ case '\0': /* handles end of string */
+ if (current_line < pos) {
+ /* truncate to prefix */
+ b->used = prefix_used;
+ b->ptr[b->used - 1] = '\0';
+
+ buffer_append_string_len(b, current_line, pos - current_line);
+ log_write(srv, b);
+ }
+ current_line = pos + 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/log.h b/src/log.h
index 583288b..b19f6b3 100644
--- a/src/log.h
+++ b/src/log.h
@@ -15,6 +15,7 @@ int open_logfile_or_pipe(server *srv, const char* logfile);
int log_error_open(server *srv);
int log_error_close(server *srv);
int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...);
+int log_error_write_multiline_buffer(server *srv, const char *filename, unsigned int line, buffer *multiline, const char *fmt, ...);
int log_error_cycle(server *srv);
#endif
diff --git a/src/mod_accesslog.c b/src/mod_accesslog.c
index 6d6c173..5484f55 100644
--- a/src/mod_accesslog.c
+++ b/src/mod_accesslog.c
@@ -124,16 +124,17 @@ typedef struct {
typedef struct {
buffer *access_logfile;
- buffer *format;
- unsigned short use_syslog;
+ int log_access_fd;
+ buffer *access_logbuffer; /* each logfile has a separate buffer */
+ unsigned short use_syslog; /* syslog has global buffer */
+ unsigned short syslog_level;
+
+ buffer *format;
- int log_access_fd;
time_t last_generated_accesslog_ts;
time_t *last_generated_accesslog_ts_ptr;
-
- buffer *access_logbuffer;
buffer *ts_accesslog_str;
buffer *ts_accesslog_fmt_str;
unsigned short append_tz_offset;
@@ -146,12 +147,15 @@ typedef struct {
plugin_config **config_storage;
plugin_config conf;
+
+ buffer *syslog_logbuffer; /* syslog has global buffer. no caching, always written directly */
} plugin_data;
INIT_FUNC(mod_accesslog_init) {
plugin_data *p;
p = calloc(1, sizeof(*p));
+ p->syslog_logbuffer = buffer_init();
return p;
}
@@ -413,13 +417,7 @@ FREE_FUNC(mod_accesslog_free) {
if (!s) continue;
if (s->access_logbuffer->used) {
- if (s->use_syslog) {
-# ifdef HAVE_SYSLOG_H
- if (s->access_logbuffer->used > 2) {
- syslog(LOG_INFO, "%*s", (int) s->access_logbuffer->used - 2, s->access_logbuffer->ptr);
- }
-# endif
- } else if (s->log_access_fd != -1) {
+ if (s->log_access_fd != -1) {
write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
}
}
@@ -449,6 +447,7 @@ FREE_FUNC(mod_accesslog_free) {
}
free(p);
+ if (p->syslog_logbuffer) buffer_free(p->syslog_logbuffer);
return HANDLER_GO_ON;
}
@@ -461,6 +460,7 @@ SETDEFAULTS_FUNC(log_access_open) {
{ "accesslog.filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
{ "accesslog.use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
{ "accesslog.format", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+ { "accesslog.syslog-level", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
};
@@ -480,11 +480,13 @@ SETDEFAULTS_FUNC(log_access_open) {
s->log_access_fd = -1;
s->last_generated_accesslog_ts = 0;
s->last_generated_accesslog_ts_ptr = &(s->last_generated_accesslog_ts);
+ s->syslog_level = LOG_INFO;
cv[0].destination = s->access_logfile;
cv[1].destination = &(s->use_syslog);
cv[2].destination = s->format;
+ cv[3].destination = &(s->syslog_level);
p->config_storage[i] = s;
@@ -590,14 +592,7 @@ SIGHUP_FUNC(log_access_cycle) {
plugin_config *s = p->config_storage[i];
if (s->access_logbuffer->used) {
- if (s->use_syslog) {
-#ifdef HAVE_SYSLOG_H
- if (s->access_logbuffer->used > 2) {
- /* syslog appends a \n on its own */
- syslog(LOG_INFO, "%*s", (int) s->access_logbuffer->used - 2, s->access_logbuffer->ptr);
- }
-#endif
- } else if (s->log_access_fd != -1) {
+ if (s->log_access_fd != -1) {
write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
}
@@ -642,6 +637,7 @@ static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_d
PATCH(append_tz_offset);
PATCH(parsed_format);
PATCH(use_syslog);
+ PATCH(syslog_level);
/* skip the first, the global context */
for (i = 1; i < srv->config_context->used; i++) {
@@ -668,7 +664,8 @@ static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_d
PATCH(append_tz_offset);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.use-syslog"))) {
PATCH(use_syslog);
- PATCH(access_logbuffer);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.syslog-level"))) {
+ PATCH(syslog_level);
}
}
}
@@ -690,7 +687,12 @@ REQUESTDONE_FUNC(log_access_write) {
/* No output device, nothing to do */
if (!p->conf.use_syslog && p->conf.log_access_fd == -1) return HANDLER_GO_ON;
- b = p->conf.access_logbuffer;
+ if (p->conf.use_syslog) {
+ b = p->syslog_logbuffer;
+ } else {
+ b = p->conf.access_logbuffer;
+ }
+
if (b->used == 0) {
buffer_copy_string_len(b, CONST_STR_LEN(""));
}
@@ -765,8 +767,8 @@ REQUESTDONE_FUNC(log_access_write) {
buffer_append_string_len(b, CONST_STR_LEN("-"));
break;
case FORMAT_REMOTE_USER:
- if (con->authed_user->used > 1) {
- buffer_append_string_buffer(b, con->authed_user);
+ if (NULL != (ds = (data_string *)array_get_element(con->environment, "REMOTE_USER")) && ds->value->used > 1) {
+ accesslog_append_escaped(b, ds->value);
} else {
buffer_append_string_len(b, CONST_STR_LEN("-"));
}
@@ -911,7 +913,7 @@ REQUESTDONE_FUNC(log_access_write) {
#ifdef HAVE_SYSLOG_H
if (b->used > 2) {
/* syslog appends a \n on its own */
- syslog(LOG_INFO, "%*s", (int) b->used - 2, b->ptr);
+ syslog(p->conf.syslog_level, "%*s", (int) b->used - 2, b->ptr);
}
#endif
} else if (p->conf.log_access_fd != -1) {
diff --git a/src/mod_alias.c b/src/mod_alias.c
index 5b7b510..0bac56b 100644
--- a/src/mod_alias.c
+++ b/src/mod_alias.c
@@ -156,7 +156,8 @@ PHYSICALPATH_FUNC(mod_alias_physical_handler) {
mod_alias_patch_connection(srv, con, p);
/* not to include the tailing slash */
- basedir_len = (con->physical.basedir->used - 1) - 1;
+ basedir_len = (con->physical.basedir->used - 1);
+ if ('/' == con->physical.basedir->ptr[basedir_len-1]) --basedir_len;
uri_len = con->physical.path->used - 1 - basedir_len;
uri_ptr = con->physical.path->ptr + basedir_len;
diff --git a/src/mod_auth.c b/src/mod_auth.c
index d981892..99ddbbd 100644
--- a/src/mod_auth.c
+++ b/src/mod_auth.c
@@ -185,6 +185,7 @@ static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
data_string *ds;
mod_auth_plugin_data *p = p_d;
array *req;
+ data_string *req_method;
/* select the right config */
mod_auth_patch_connection(srv, con, p);
@@ -227,18 +228,30 @@ static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
if (auth_required == 0) return HANDLER_GO_ON;
req = ((data_array *)(p->conf.auth_require->data[k]))->value;
+ req_method = (data_string *)array_get_element(req, "method");
+
+ if (0 == strcmp(req_method->value->ptr, "extern")) {
+ /* require REMOTE_USER to be already set */
+ if (NULL == (ds = (data_string *)array_get_element(con->environment, "REMOTE_USER"))) {
+ con->http_status = 401;
+ con->mode = DIRECT;
+ return HANDLER_FINISHED;
+ } else if (http_auth_match_rules(srv, req, ds->value->ptr, NULL, NULL)) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "rules didn't match");
+ con->http_status = 401;
+ con->mode = DIRECT;
+ return HANDLER_FINISHED;
+ } else {
+ return HANDLER_GO_ON;
+ }
+ }
/* try to get Authorization-header */
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) {
- http_authorization = ds->value->ptr;
- }
-
- if (ds && ds->value && ds->value->used) {
+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization")) && ds->value->used) {
char *auth_realm;
- data_string *method;
- method = (data_string *)array_get_element(req, "method");
+ http_authorization = ds->value->ptr;
/* parse auth-header */
if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
@@ -248,14 +261,14 @@ static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
(0 == strncasecmp(http_authorization, "Basic", auth_type_len))) {
auth_type = "Basic";
- if (0 == strcmp(method->value->ptr, "basic")) {
- auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1);
+ if (0 == strcmp(req_method->value->ptr, "basic")) {
+ auth_satisfied = http_auth_basic_check(srv, con, p, req, auth_realm+1);
}
} else if ((auth_type_len == 6) &&
(0 == strncasecmp(http_authorization, "Digest", auth_type_len))) {
auth_type = "Digest";
- if (0 == strcmp(method->value->ptr, "digest")) {
- if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) {
+ if (0 == strcmp(req_method->value->ptr, "digest")) {
+ if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, auth_realm+1))) {
con->http_status = 400;
con->mode = DIRECT;
@@ -304,18 +317,25 @@ static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
} else {
/* the REMOTE_USER header */
- buffer_copy_string_buffer(con->authed_user, p->auth_user);
+ if (NULL == (ds = (data_string *)array_get_element(con->environment, "REMOTE_USER"))) {
+ if (NULL == (ds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
+ ds = data_string_init();
+ }
+ buffer_copy_string(ds->key, "REMOTE_USER");
+ array_insert_unique(con->environment, (data_unset *)ds);
+ }
+ buffer_copy_string_buffer(ds->value, p->auth_user);
/* AUTH_TYPE environment */
- if (NULL == (ds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
- ds = data_string_init();
+ if (NULL == (ds = (data_string *)array_get_element(con->environment, "AUTH_TYPE"))) {
+ if (NULL == (ds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
+ ds = data_string_init();
+ }
+ buffer_copy_string(ds->key, "AUTH_TYPE");
+ array_insert_unique(con->environment, (data_unset *)ds);
}
-
- buffer_copy_string(ds->key, "AUTH_TYPE");
buffer_copy_string(ds->value, auth_type);
-
- array_insert_unique(con->environment, (data_unset *)ds);
}
return HANDLER_GO_ON;
@@ -487,9 +507,10 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) {
return HANDLER_ERROR;
} else {
if (0 != strcmp(method, "basic") &&
- 0 != strcmp(method, "digest")) {
+ 0 != strcmp(method, "digest") &&
+ 0 != strcmp(method, "extern")) {
log_error_write(srv, __FILE__, __LINE__, "ss",
- "method has to be either \"basic\" or \"digest\" in",
+ "method has to be either \"basic\", \"digest\" or \"extern\" in",
"auth.require = ( \"...\" => ( ..., \"method\" => \"...\") )");
return HANDLER_ERROR;
}
diff --git a/src/mod_cgi.c b/src/mod_cgi.c
index 5e65f4b..fad5d5b 100644
--- a/src/mod_cgi.c
+++ b/src/mod_cgi.c
@@ -918,17 +918,10 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *
);
cgi_env_add(&env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
- if (!buffer_is_empty(con->authed_user)) {
- cgi_env_add(&env, CONST_STR_LEN("REMOTE_USER"),
- CONST_BUF_LEN(con->authed_user));
+ if (buffer_is_equal_caseless_string(con->uri.scheme, CONST_STR_LEN("https"))) {
+ cgi_env_add(&env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
}
-#ifdef USE_OPENSSL
- if (srv_sock->is_ssl) {
- cgi_env_add(&env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
- }
-#endif
-
/* request.content_length < SSIZE_MAX, see request.c */
LI_ltostr(buf, con->request.content_length);
cgi_env_add(&env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
diff --git a/src/mod_extforward.c b/src/mod_extforward.c
index 828bbfe..dd52f31 100644
--- a/src/mod_extforward.c
+++ b/src/mod_extforward.c
@@ -11,6 +11,7 @@
#include "config.h"
#endif
+#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
@@ -303,11 +304,14 @@ static const char *last_not_in_array(array *a, plugin_data *p)
return NULL;
}
-static struct addrinfo *ipstr_to_sockaddr(server *srv, const char *host) {
- struct addrinfo hints, *res0;
+#ifdef HAVE_IPV6
+static void ipstr_to_sockaddr(server *srv, const char *host, sock_addr *sock) {
+ struct addrinfo hints, *addrlist = NULL;
int result;
memset(&hints, 0, sizeof(hints));
+ sock->plain.sa_family = AF_UNSPEC;
+
#ifndef AI_NUMERICSERV
/**
* quoting $ man getaddrinfo
@@ -321,22 +325,31 @@ static struct addrinfo *ipstr_to_sockaddr(server *srv, const char *host) {
hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
errno = 0;
- result = getaddrinfo(host, NULL, &hints, &res0);
+ result = getaddrinfo(host, NULL, &hints, &addrlist);
if (result != 0) {
log_error_write(srv, __FILE__, __LINE__, "SSSs(S)",
- "could not resolve hostname ", host, " because ", gai_strerror(result), strerror(errno));
-
- return NULL;
- } else if (res0 == NULL) {
+ "could not parse ip address ", host, " because ", gai_strerror(result), strerror(errno));
+ } else if (addrlist == NULL) {
+ log_error_write(srv, __FILE__, __LINE__, "SSS",
+ "Problem in parsing ip address ", host, ": succeeded, but no information returned");
+ } else switch (addrlist->ai_family) {
+ case AF_INET:
+ memcpy(&sock->ipv4, addrlist->ai_addr, sizeof(sock->ipv4));
+ assert(AF_INET == sock->plain.sa_family);
+ break;
+ case AF_INET6:
+ memcpy(&sock->ipv6, addrlist->ai_addr, sizeof(sock->ipv6));
+ assert(AF_INET6 == sock->plain.sa_family);
+ break;
+ default:
log_error_write(srv, __FILE__, __LINE__, "SSS",
- "Problem in resolving hostname ", host, ": succeeded, but no information returned");
+ "Problem in parsing ip address ", host, ": succeeded, but unknown family");
}
- return res0;
+ freeaddrinfo(addrlist);
}
-
-
+#endif
static void clean_cond_cache(server *srv, connection *con) {
config_cond_cache_reset_item(srv, con, COMP_HTTP_REMOTE_IP);
@@ -347,7 +360,6 @@ URIHANDLER_FUNC(mod_extforward_uri_handler) {
data_string *forwarded = NULL;
#ifdef HAVE_IPV6
char b2[INET6_ADDRSTRLEN + 1];
- struct addrinfo *addrlist = NULL;
#endif
const char *dst_addr_str = NULL;
array *forward_array = NULL;
@@ -411,32 +423,21 @@ URIHANDLER_FUNC(mod_extforward_uri_handler) {
if (real_remote_addr != NULL) { /* parsed */
sock_addr sock;
- struct addrinfo *addrs_left;
- server_socket *srv_sock = con->srv_socket;
data_string *forwarded_proto = (data_string *)array_get_element(con->request.headers, "X-Forwarded-Proto");
- if (forwarded_proto && !strcmp(forwarded_proto->value->ptr, "https")) {
- srv_sock->is_proxy_ssl = 1;
- } else {
- srv_sock->is_proxy_ssl = 0;
+ if (NULL != forwarded_proto) {
+ if (buffer_is_equal_caseless_string(forwarded_proto->value, CONST_STR_LEN("https"))) {
+ buffer_copy_string_len(con->uri.scheme, CONST_STR_LEN("https"));
+ } else if (buffer_is_equal_caseless_string(forwarded_proto->value, CONST_STR_LEN("http"))) {
+ buffer_copy_string_len(con->uri.scheme, CONST_STR_LEN("http"));
+ }
}
if (con->conf.log_request_handling) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "using address:", real_remote_addr);
+ log_error_write(srv, __FILE__, __LINE__, "ss", "using address:", real_remote_addr);
}
#ifdef HAVE_IPV6
- addrlist = ipstr_to_sockaddr(srv, real_remote_addr);
- sock.plain.sa_family = AF_UNSPEC;
- for (addrs_left = addrlist; addrs_left != NULL; addrs_left = addrs_left -> ai_next) {
- sock.plain.sa_family = addrs_left->ai_family;
- if (sock.plain.sa_family == AF_INET) {
- sock.ipv4.sin_addr = ((struct sockaddr_in*)addrs_left->ai_addr)->sin_addr;
- break;
- } else if (sock.plain.sa_family == AF_INET6) {
- sock.ipv6.sin6_addr = ((struct sockaddr_in6*)addrs_left->ai_addr)->sin6_addr;
- break;
- }
- }
+ ipstr_to_sockaddr(srv, real_remote_addr, &sock);
#else
UNUSED(addrs_left);
sock.ipv4.sin_addr.s_addr = inet_addr(real_remote_addr);
@@ -464,9 +465,6 @@ URIHANDLER_FUNC(mod_extforward_uri_handler) {
/* Now, clean the conf_cond cache, because we may have changed the results of tests */
clean_cond_cache(srv, con);
}
-#ifdef HAVE_IPV6
- if (addrlist != NULL ) freeaddrinfo(addrlist);
-#endif
}
array_free(forward_array);
diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c
index de6bfd1..bcd36a2 100644
--- a/src/mod_fastcgi.c
+++ b/src/mod_fastcgi.c
@@ -1275,6 +1275,7 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
}
host = fastcgi_host_init();
+ buffer_reset(fcgi_mode);
buffer_copy_string_buffer(host->id, da_host->key);
@@ -1915,10 +1916,6 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s)),con)
- if (!buffer_is_empty(con->authed_user)) {
- FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"), CONST_BUF_LEN(con->authed_user)),con)
- }
-
if (con->request.content_length > 0 && host->mode != FCGI_AUTHORIZER) {
/* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
@@ -2031,7 +2028,7 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
s = get_http_version_name(con->request.http_version);
FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s)),con)
- if (srv_sock->is_ssl || srv_sock->is_proxy_ssl) {
+ if (buffer_is_equal_caseless_string(con->uri.scheme, CONST_STR_LEN("https"))) {
FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on")),con)
}
@@ -2673,8 +2670,8 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
case FCGI_STDERR:
if (packet.len == 0) break;
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "FastCGI-stderr:", packet.b);
+ log_error_write_multiline_buffer(srv, __FILE__, __LINE__, packet.b, "s",
+ "FastCGI-stderr:");
break;
case FCGI_END_REQUEST:
diff --git a/src/mod_proxy.c b/src/mod_proxy.c
index 09d4fc1..57156ba 100644
--- a/src/mod_proxy.c
+++ b/src/mod_proxy.c
@@ -463,7 +463,7 @@ static int proxy_create_env(server *srv, handler_ctx *hctx) {
!buffer_is_empty(con->request.http_host)) {
proxy_set_header(con, "X-Host", con->request.http_host->ptr);
}
- proxy_set_header(con, "X-Forwarded-Proto", con->conf.is_ssl ? "https" : "http");
+ proxy_set_header(con, "X-Forwarded-Proto", con->uri.scheme->ptr);
/* request header */
for (i = 0; i < con->request.headers->used; i++) {
diff --git a/src/mod_redirect.c b/src/mod_redirect.c
index 5d51b86..e83f378 100644
--- a/src/mod_redirect.c
+++ b/src/mod_redirect.c
@@ -65,7 +65,6 @@ FREE_FUNC(mod_redirect_free) {
SETDEFAULTS_FUNC(mod_redirect_set_defaults) {
plugin_data *p = p_d;
- data_unset *du;
size_t i = 0;
config_values_t cv[] = {
@@ -83,7 +82,8 @@ SETDEFAULTS_FUNC(mod_redirect_set_defaults) {
plugin_config *s;
size_t j;
array *ca;
- data_array *da = (data_array *)du;
+ data_unset *du;
+ data_array *da;
s = calloc(1, sizeof(plugin_config));
s->redirect = pcre_keyvalue_buffer_init();
diff --git a/src/mod_scgi.c b/src/mod_scgi.c
index 6ae0782..56b0aa9 100644
--- a/src/mod_scgi.c
+++ b/src/mod_scgi.c
@@ -1542,12 +1542,6 @@ static int scgi_create_env(server *srv, handler_ctx *hctx) {
s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
- if (!buffer_is_empty(con->authed_user)) {
- scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_USER"),
- CONST_BUF_LEN(con->authed_user));
- }
-
-
/*
* SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to
* http://cgi-spec.golux.com/draft-coar-cgi-v11-03-clean.html
@@ -1614,7 +1608,7 @@ static int scgi_create_env(server *srv, handler_ctx *hctx) {
scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
#ifdef USE_OPENSSL
- if (srv_sock->is_ssl) {
+ if (buffer_is_equal_caseless_string(con->uri.scheme, CONST_STR_LEN("https"))) {
scgi_env_add(p->scgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
}
#endif
@@ -2813,7 +2807,7 @@ static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, i
if (con->conf.log_request_handling) {
log_error_write(srv, __FILE__, __LINE__, "s",
- "handling it in mod_fastcgi");
+ "handling it in mod_scgi");
}
/* the prefix is the SCRIPT_NAME,
@@ -2871,7 +2865,7 @@ static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, i
con->mode = p->id;
if (con->conf.log_request_handling) {
- log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
+ log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_scgi");
}
}
diff --git a/src/mod_simple_vhost.c b/src/mod_simple_vhost.c
index bbb61d5..69227bd 100644
--- a/src/mod_simple_vhost.c
+++ b/src/mod_simple_vhost.c
@@ -5,6 +5,7 @@
#include "plugin.h"
+#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
@@ -123,36 +124,31 @@ SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
stat_cache_entry *sce = NULL;
+ assert(p->conf.server_root->used > 1);
buffer_prepare_copy(out, 128);
+ buffer_copy_string_buffer(out, p->conf.server_root);
- if (p->conf.server_root->used) {
- buffer_copy_string_buffer(out, p->conf.server_root);
+ if (host->used) {
+ /* a hostname has to start with a alpha-numerical character
+ * and must not contain a slash "/"
+ */
+ char *dp;
- if (host->used) {
- /* a hostname has to start with a alpha-numerical character
- * and must not contain a slash "/"
- */
- char *dp;
-
- BUFFER_APPEND_SLASH(out);
-
- if (NULL == (dp = strchr(host->ptr, ':'))) {
- buffer_append_string_buffer(out, host);
- } else {
- buffer_append_string_len(out, host->ptr, dp - host->ptr);
- }
- }
BUFFER_APPEND_SLASH(out);
- if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
- buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
+ if (NULL == (dp = strchr(host->ptr, ':'))) {
+ buffer_append_string_buffer(out, host);
} else {
- buffer_append_string_buffer(out, p->conf.document_root);
- BUFFER_APPEND_SLASH(out);
+ buffer_append_string_len(out, host->ptr, dp - host->ptr);
}
+ }
+ BUFFER_APPEND_SLASH(out);
+
+ if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
+ buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
} else {
- buffer_copy_string_buffer(out, con->conf.document_root);
+ buffer_append_string_buffer(out, p->conf.document_root);
BUFFER_APPEND_SLASH(out);
}
@@ -228,38 +224,41 @@ static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_
mod_simple_vhost_patch_connection(srv, con, p);
+ /* build_doc_root() requires a server_root; skip module if simple-vhost.server-root is not set
+ * or set to an empty string (especially don't cache any results!)
+ */
+ if (p->conf.server_root->used < 2) return HANDLER_GO_ON;
+
if (p->conf.docroot_cache_key->used &&
con->uri.authority->used &&
buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
/* cache hit */
- buffer_copy_string_buffer(con->physical.doc_root, p->conf.docroot_cache_value);
buffer_copy_string_buffer(con->server_name, p->conf.docroot_cache_servername);
+ buffer_copy_string_buffer(con->physical.doc_root, p->conf.docroot_cache_value);
} else {
/* build document-root */
if ((con->uri.authority->used == 0) ||
build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
/* not found, fallback the default-host */
- if (build_doc_root(srv, con, p,
+ if (0 == build_doc_root(srv, con, p,
p->doc_root,
p->conf.default_host)) {
- return HANDLER_GO_ON;
- } else {
+ /* default host worked */
buffer_copy_string_buffer(con->server_name, p->conf.default_host);
buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
-
/* do not cache default host */
- return HANDLER_GO_ON;
}
- } else {
- buffer_copy_string_buffer(con->server_name, con->uri.authority);
+ return HANDLER_GO_ON;
}
+ /* found host */
+ buffer_copy_string_buffer(con->server_name, con->uri.authority);
+ buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
+
/* copy to cache */
buffer_copy_string_buffer(p->conf.docroot_cache_key, con->uri.authority);
buffer_copy_string_buffer(p->conf.docroot_cache_value, p->doc_root);
buffer_copy_string_buffer(p->conf.docroot_cache_servername, con->server_name);
-
- buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
}
return HANDLER_GO_ON;
diff --git a/src/mod_ssi.c b/src/mod_ssi.c
index 897f49e..1d77a7b 100644
--- a/src/mod_ssi.c
+++ b/src/mod_ssi.c
@@ -276,11 +276,6 @@ static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) {
ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_ADDR"),
inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
- if (con->authed_user->used) {
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_USER"),
- con->authed_user->ptr);
- }
-
if (con->request.content_length > 0) {
/* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
diff --git a/src/mod_trigger_b4_dl.c b/src/mod_trigger_b4_dl.c
index f813413..4adaa5f 100644
--- a/src/mod_trigger_b4_dl.c
+++ b/src/mod_trigger_b4_dl.c
@@ -437,7 +437,7 @@ URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) {
return HANDLER_FINISHED;
}
- last_hit = *(time_t *)(val.dptr);
+ memcpy(&last_hit, val.dptr, sizeof(time_t));
free(val.dptr);
@@ -555,7 +555,7 @@ TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) {
val = gdbm_fetch(s->db, key);
- last_hit = *(time_t *)(val.dptr);
+ memcpy(&last_hit, val.dptr, sizeof(time_t));
free(val.dptr);
diff --git a/src/mod_userdir.c b/src/mod_userdir.c
index 4a1967f..5333003 100644
--- a/src/mod_userdir.c
+++ b/src/mod_userdir.c
@@ -22,6 +22,7 @@ typedef struct {
buffer *path;
buffer *basepath;
unsigned short letterhomes;
+ unsigned short active;
} plugin_config;
typedef struct {
@@ -88,7 +89,8 @@ SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
{ "userdir.exclude-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
{ "userdir.include-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
{ "userdir.basepath", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
- { "userdir.letterhomes", NULL, T_CONFIG_BOOLEAN,T_CONFIG_SCOPE_CONNECTION }, /* 4 */
+ { "userdir.letterhomes", NULL, T_CONFIG_BOOLEAN,T_CONFIG_SCOPE_CONNECTION }, /* 4 */
+ { "userdir.active", NULL, T_CONFIG_BOOLEAN,T_CONFIG_SCOPE_CONNECTION }, /* 5 */
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
};
@@ -105,12 +107,16 @@ SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
s->path = buffer_init();
s->basepath = buffer_init();
s->letterhomes = 0;
+ /* enabled by default for backward compatibility; if userdir.path isn't set userdir is disabled too,
+ * but you can't disable it by setting it to an empty string. */
+ s->active = 1;
cv[0].destination = s->path;
cv[1].destination = s->exclude_user;
cv[2].destination = s->include_user;
cv[3].destination = s->basepath;
cv[4].destination = &(s->letterhomes);
+ cv[5].destination = &(s->active);
p->config_storage[i] = s;
@@ -133,6 +139,7 @@ static int mod_userdir_patch_connection(server *srv, connection *con, plugin_dat
PATCH(include_user);
PATCH(basepath);
PATCH(letterhomes);
+ PATCH(active);
/* skip the first, the global context */
for (i = 1; i < srv->config_context->used; i++) {
@@ -156,6 +163,8 @@ static int mod_userdir_patch_connection(server *srv, connection *con, plugin_dat
PATCH(basepath);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.letterhomes"))) {
PATCH(letterhomes);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.active"))) {
+ PATCH(active);
}
}
}
@@ -179,7 +188,7 @@ URIHANDLER_FUNC(mod_userdir_docroot_handler) {
/* enforce the userdir.path to be set in the config, ugly fix for #1587;
* should be replaced with a clean .enabled option in 1.5
*/
- if (p->conf.path->used == 0) return HANDLER_GO_ON;
+ if (!p->conf.active || p->conf.path->used == 0) return HANDLER_GO_ON;
/* /~user/foo.html -> /home/user/public_html/foo.html */
diff --git a/src/network.c b/src/network.c
index f59f60d..395dfae 100644
--- a/src/network.c
+++ b/src/network.c
@@ -25,7 +25,9 @@
# include <openssl/ssl.h>
# include <openssl/err.h>
# include <openssl/rand.h>
-# include <openssl/dh.h>
+# ifndef OPENSSL_NO_DH
+# include <openssl/dh.h>
+# endif
# include <openssl/bn.h>
# if OPENSSL_VERSION_NUMBER >= 0x0090800fL
@@ -42,8 +44,6 @@ static void ssl_info_callback(const SSL *ssl, int where, int ret) {
if (0 != (where & SSL_CB_HANDSHAKE_START)) {
connection *con = SSL_get_app_data(ssl);
++con->renegotiations;
- } else if (0 != (where & SSL_CB_HANDSHAKE_DONE)) {
- ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
}
}
#endif
@@ -389,7 +389,7 @@ static int network_server_init(server *srv, buffer *host_token, specific_config
goto error_free_socket;
}
- if (s->is_ssl) {
+ if (s->ssl_enabled) {
#ifdef USE_OPENSSL
if (NULL == (srv_socket->ssl_ctx = s->ssl_ctx)) {
log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
@@ -423,7 +423,7 @@ static int network_server_init(server *srv, buffer *host_token, specific_config
#endif
}
- srv_socket->is_ssl = s->is_ssl;
+ srv_socket->is_ssl = s->ssl_enabled;
if (srv->srv_sockets.size == 0) {
srv->srv_sockets.size = 4;
@@ -505,7 +505,9 @@ int network_init(server *srv) {
#endif
#ifdef USE_OPENSSL
+# ifndef OPENSSL_NO_DH
DH *dh;
+# endif
BIO *bio;
/* 1024-bit MODP Group with 160-bit prime order subgroup (RFC5114)
@@ -611,6 +613,16 @@ int network_init(server *srv) {
return -1;
}
+ if (s->ssl_empty_fragments) {
+#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
+ ssloptions &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
+#else
+ ssloptions &= ~0x00000800L; /* hardcode constant */
+ log_error_write(srv, __FILE__, __LINE__, "ss", "WARNING: SSL:",
+ "'insert empty fragments' not supported by the openssl version used to compile lighttpd with");
+#endif
+ }
+
SSL_CTX_set_options(s->ssl_ctx, ssloptions);
SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback);
@@ -645,6 +657,7 @@ int network_init(server *srv) {
}
}
+#ifndef OPENSSL_NO_DH
/* Support for Diffie-Hellman key exchange */
if (!buffer_is_empty(s->ssl_dh_file)) {
/* DH parameters from file */
@@ -678,6 +691,11 @@ int network_init(server *srv) {
SSL_CTX_set_tmp_dh(s->ssl_ctx,dh);
SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_DH_USE);
DH_free(dh);
+#else
+ if (!buffer_is_empty(s->ssl_dh_file)) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: openssl compiled without DH support, can't load parameters from", s->ssl_dh_file->ptr);
+ }
+#endif
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH
diff --git a/src/network_openssl.c b/src/network_openssl.c
index 7bed710..5eb612d 100644
--- a/src/network_openssl.c
+++ b/src/network_openssl.c
@@ -90,7 +90,7 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu
r = SSL_write(ssl, offset, toSend);
if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
- log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client");
+ log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection");
return -1;
}
@@ -202,7 +202,7 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu
r = SSL_write(ssl, s, toSend);
if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
- log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client");
+ log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection");
return -1;
}
diff --git a/src/network_writev.c b/src/network_writev.c
index d21cc4f..4c9cb5e 100644
--- a/src/network_writev.c
+++ b/src/network_writev.c
@@ -30,6 +30,18 @@
#define LOCAL_BUFFERING 1
#endif
+#if defined(UIO_MAXIOV)
+# define MAX_CHUNKS UIO_MAXIOV
+#elif defined(IOV_MAX)
+/* new name for UIO_MAXIOV since IEEE Std 1003.1-2001 */
+# define MAX_CHUNKS IOV_MAX
+#elif defined(_XOPEN_IOV_MAX)
+/* minimum value for sysconf(_SC_IOV_MAX); posix requires this to be at least 16, which is good enough - no need to call sysconf() */
+# define MAX_CHUNKS _XOPEN_IOV_MAX
+#else
+# error neither UIO_MAXIOV nor IOV_MAX nor _XOPEN_IOV_MAX are defined
+#endif
+
int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq, off_t max_bytes) {
chunk *c;
@@ -46,30 +58,13 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq
struct iovec *chunks;
chunk *tc;
size_t num_bytes = 0;
-#if defined(_SC_IOV_MAX) /* IRIX, MacOS X, FreeBSD, Solaris, ... */
- const size_t max_chunks = sysconf(_SC_IOV_MAX);
-#elif defined(IOV_MAX) /* Linux x86 (glibc-2.3.6-3) */
- const size_t max_chunks = IOV_MAX;
-#elif defined(MAX_IOVEC) /* Linux ia64 (glibc-2.3.3-98.28) */
- const size_t max_chunks = MAX_IOVEC;
-#elif defined(UIO_MAXIOV) /* Linux x86 (glibc-2.2.5-233) */
- const size_t max_chunks = UIO_MAXIOV;
-#elif (defined(__FreeBSD__) && __FreeBSD_version < 500000) || defined(__DragonFly__) || defined(__APPLE__)
- /* - FreeBSD 4.x
- * - MacOS X 10.3.x
- * (covered in -DKERNEL)
- * */
- const size_t max_chunks = 1024; /* UIO_MAXIOV value from sys/uio.h */
-#else
-#error "sysconf() doesnt return _SC_IOV_MAX ..., check the output of 'man writev' for the EINVAL error and send the output to jan@kneschke.de"
-#endif
/* build writev list
*
- * 1. limit: num_chunks < max_chunks
+ * 1. limit: num_chunks < MAX_CHUNKS
* 2. limit: num_bytes < max_bytes
*/
- for (num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < max_chunks; num_chunks++, tc = tc->next);
+ for (num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < MAX_CHUNKS; num_chunks++, tc = tc->next);
chunks = calloc(num_chunks, sizeof(*chunks));
diff --git a/src/proc_open.c b/src/proc_open.c
index e9393e0..e28b479 100644
--- a/src/proc_open.c
+++ b/src/proc_open.c
@@ -317,6 +317,7 @@ int proc_open_buffer(const char *command, buffer *in, buffer *out, buffer *err)
proc_read_fd_to_buffer(proc.err.fd, tmp);
if (tmp->used > 0 && write(2, (void*)tmp->ptr, tmp->used) < 0) {
perror("error writing pipe");
+ buffer_free(tmp);
return -1;
}
buffer_free(tmp);
diff --git a/src/request.c b/src/request.c
index 8c6c170..6bdaf57 100644
--- a/src/request.c
+++ b/src/request.c
@@ -366,7 +366,7 @@ int http_request_parse(server *srv, connection *con) {
*(proto - 1) = '\0';
/* we got the first one :) */
- if (-1 == (r = get_http_method_key(method))) {
+ if (HTTP_METHOD_UNSET == (r = get_http_method_key(method))) {
con->http_status = 501;
con->response.keep_alive = 0;
con->keep_alive = 0;
@@ -584,7 +584,7 @@ int http_request_parse(server *srv, connection *con) {
/**
* 1*<any CHAR except CTLs or separators>
- * CTLs == 0-31 + 127
+ * CTLs == 0-31 + 127, CHAR = 7-bit ascii (0..127)
*
*/
switch(*cur) {
@@ -619,8 +619,14 @@ int http_request_parse(server *srv, connection *con) {
con->keep_alive = 0;
con->response.keep_alive = 0;
- log_error_write(srv, __FILE__, __LINE__, "sbsds",
+ if (srv->srvconf.log_request_header_on_error) {
+ log_error_write(srv, __FILE__, __LINE__, "sbsds",
"invalid character in key", con->request.request, cur, *cur, "-> 400");
+
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+ "request-header:\n",
+ con->request.request);
+ }
return 0;
case ' ':
case '\t':
@@ -678,8 +684,6 @@ int http_request_parse(server *srv, connection *con) {
i++;
done = 1;
-
- break;
} else {
if (srv->srvconf.log_request_header_on_error) {
log_error_write(srv, __FILE__, __LINE__, "s", "CR without LF -> 400");
@@ -693,53 +697,24 @@ int http_request_parse(server *srv, connection *con) {
con->response.keep_alive = 0;
return 0;
}
- /* fall thru */
- case 0: /* illegal characters (faster than a if () :) */
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 10:
- case 11:
- case 12:
- case 14:
- case 15:
- case 16:
- case 17:
- case 18:
- case 19:
- case 20:
- case 21:
- case 22:
- case 23:
- case 24:
- case 25:
- case 26:
- case 27:
- case 28:
- case 29:
- case 30:
- case 31:
- case 127:
- con->http_status = 400;
- con->keep_alive = 0;
- con->response.keep_alive = 0;
+ break;
+ default:
+ if (*cur < 32 || ((unsigned char)*cur) >= 127) {
+ con->http_status = 400;
+ con->keep_alive = 0;
+ con->response.keep_alive = 0;
- if (srv->srvconf.log_request_header_on_error) {
- log_error_write(srv, __FILE__, __LINE__, "sbsds",
- "CTL character in key", con->request.request, cur, *cur, "-> 400");
+ if (srv->srvconf.log_request_header_on_error) {
+ log_error_write(srv, __FILE__, __LINE__, "sbsds",
+ "invalid character in key", con->request.request, cur, *cur, "-> 400");
- log_error_write(srv, __FILE__, __LINE__, "Sb",
- "request-header:\n",
- con->request.request);
- }
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+ "request-header:\n",
+ con->request.request);
+ }
- return 0;
- default:
+ return 0;
+ }
/* ok */
break;
}
diff --git a/src/response.c b/src/response.c
index fd1ab19..1198d49 100644
--- a/src/response.c
+++ b/src/response.c
@@ -169,11 +169,19 @@ static void https_add_ssl_entries(connection *con) {
envds->value,
(const char *)xe->value->data, xe->value->length
);
- /* pick one of the exported values as "authed user", for example
+ /* pick one of the exported values as "REMOTE_USER", for example
* ssl.verifyclient.username = "SSL_CLIENT_S_DN_UID" or "SSL_CLIENT_S_DN_emailAddress"
*/
if (buffer_is_equal(con->conf.ssl_verifyclient_username, envds->key)) {
- buffer_copy_string_buffer(con->authed_user, envds->value);
+ data_string *ds;
+ if (NULL == (ds = (data_string *)array_get_element(con->environment, "REMOTE_USER"))) {
+ if (NULL == (ds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
+ ds = data_string_init();
+ }
+ buffer_copy_string(ds->key, "REMOTE_USER");
+ array_insert_unique(con->environment, (data_unset *)ds);
+ }
+ buffer_copy_string_buffer(ds->value, envds->value);
}
array_insert_unique(con->environment, (data_unset *)envds);
}
@@ -264,7 +272,8 @@ handler_t http_response_prepare(server *srv, connection *con) {
*
*/
- if (con->conf.is_ssl) {
+ /* initial scheme value. can be overwritten for example by mod_extforward later */
+ if (con->srv_socket->is_ssl) {
buffer_copy_string_len(con->uri.scheme, CONST_STR_LEN("https"));
} else {
buffer_copy_string_len(con->uri.scheme, CONST_STR_LEN("http"));
@@ -351,7 +360,7 @@ handler_t http_response_prepare(server *srv, connection *con) {
}
#ifdef USE_OPENSSL
- if (con->conf.is_ssl && con->conf.ssl_verifyclient) {
+ if (con->srv_socket->is_ssl && con->conf.ssl_verifyclient) {
https_add_ssl_entries(con);
}
#endif
@@ -508,8 +517,8 @@ handler_t http_response_prepare(server *srv, connection *con) {
*/
buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
- BUFFER_APPEND_SLASH(con->physical.path);
buffer_copy_string_buffer(con->physical.basedir, con->physical.path);
+ BUFFER_APPEND_SLASH(con->physical.path);
if (con->physical.rel_path->used &&
con->physical.rel_path->ptr[0] == '/') {
buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2);
diff --git a/src/server.c b/src/server.c
index 590a9d5..a779928 100644
--- a/src/server.c
+++ b/src/server.c
@@ -937,6 +937,51 @@ int main (int argc, char **argv) {
if (srv->srvconf.dont_daemonize == 0) daemonize();
#endif
+
+#ifdef HAVE_SIGACTION
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &act, NULL);
+ sigaction(SIGUSR1, &act, NULL);
+# if defined(SA_SIGINFO)
+ act.sa_sigaction = sigaction_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+# else
+ act.sa_handler = signal_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+# endif
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+ sigaction(SIGHUP, &act, NULL);
+ sigaction(SIGALRM, &act, NULL);
+ sigaction(SIGCHLD, &act, NULL);
+
+#elif defined(HAVE_SIGNAL)
+ /* ignore the SIGPIPE from sendfile() */
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGUSR1, SIG_IGN);
+ signal(SIGALRM, signal_handler);
+ signal(SIGTERM, signal_handler);
+ signal(SIGHUP, signal_handler);
+ signal(SIGCHLD, signal_handler);
+ signal(SIGINT, signal_handler);
+#endif
+
+#ifdef USE_ALARM
+ signal(SIGALRM, signal_handler);
+
+ /* setup periodic timer (1 second) */
+ if (setitimer(ITIMER_REAL, &interval, NULL)) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
+ return -1;
+ }
+
+ getitimer(ITIMER_REAL, &interval);
+#endif
+
+
srv->gid = getgid();
srv->uid = getuid();
@@ -1011,51 +1056,6 @@ int main (int argc, char **argv) {
}
-
-
-#ifdef HAVE_SIGACTION
- memset(&act, 0, sizeof(act));
- act.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &act, NULL);
- sigaction(SIGUSR1, &act, NULL);
-# if defined(SA_SIGINFO)
- act.sa_sigaction = sigaction_handler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_SIGINFO;
-# else
- act.sa_handler = signal_handler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
-# endif
- sigaction(SIGINT, &act, NULL);
- sigaction(SIGTERM, &act, NULL);
- sigaction(SIGHUP, &act, NULL);
- sigaction(SIGALRM, &act, NULL);
- sigaction(SIGCHLD, &act, NULL);
-
-#elif defined(HAVE_SIGNAL)
- /* ignore the SIGPIPE from sendfile() */
- signal(SIGPIPE, SIG_IGN);
- signal(SIGUSR1, SIG_IGN);
- signal(SIGALRM, signal_handler);
- signal(SIGTERM, signal_handler);
- signal(SIGHUP, signal_handler);
- signal(SIGCHLD, signal_handler);
- signal(SIGINT, signal_handler);
-#endif
-
-#ifdef USE_ALARM
- signal(SIGALRM, signal_handler);
-
- /* setup periodic timer (1 second) */
- if (setitimer(ITIMER_REAL, &interval, NULL)) {
- log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
- return -1;
- }
-
- getitimer(ITIMER_REAL, &interval);
-#endif
-
#ifdef HAVE_FORK
/* start watcher and workers */
num_childs = srv->srvconf.max_worker;