diff options
author | Arno Töll <arno@debian.org> | 2013-10-15 20:19:04 +0200 |
---|---|---|
committer | Arno Töll <arno@debian.org> | 2013-10-15 20:19:04 +0200 |
commit | 1380410981681f011377225708e9c530330fd5a0 (patch) | |
tree | 7dd371bc4cac8910130e4ee0f4508bc519f1778d /src | |
parent | 5b23e76990e58208a01c2a5362362575bc12b397 (diff) | |
download | lighttpd-upstream.tar.gz |
Imported Upstream version 1.4.33upstream/1.4.33upstream
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.in | 252 | ||||
-rw-r--r-- | src/base.h | 9 | ||||
-rw-r--r-- | src/buffer.c | 75 | ||||
-rw-r--r-- | src/buffer.h | 1 | ||||
-rw-r--r-- | src/configfile.c | 49 | ||||
-rw-r--r-- | src/connections.c | 40 | ||||
-rw-r--r-- | src/fdevent_libev.c | 19 | ||||
-rw-r--r-- | src/http-header-glue.c | 82 | ||||
-rw-r--r-- | src/http_auth.c | 193 | ||||
-rw-r--r-- | src/http_auth.h | 5 | ||||
-rw-r--r-- | src/keyvalue.c | 43 | ||||
-rw-r--r-- | src/keyvalue.h | 71 | ||||
-rw-r--r-- | src/lemon.c | 10 | ||||
-rw-r--r-- | src/log.c | 166 | ||||
-rw-r--r-- | src/log.h | 1 | ||||
-rw-r--r-- | src/mod_accesslog.c | 52 | ||||
-rw-r--r-- | src/mod_alias.c | 3 | ||||
-rw-r--r-- | src/mod_auth.c | 61 | ||||
-rw-r--r-- | src/mod_cgi.c | 11 | ||||
-rw-r--r-- | src/mod_extforward.c | 66 | ||||
-rw-r--r-- | src/mod_fastcgi.c | 11 | ||||
-rw-r--r-- | src/mod_proxy.c | 2 | ||||
-rw-r--r-- | src/mod_redirect.c | 4 | ||||
-rw-r--r-- | src/mod_scgi.c | 12 | ||||
-rw-r--r-- | src/mod_simple_vhost.c | 61 | ||||
-rw-r--r-- | src/mod_ssi.c | 5 | ||||
-rw-r--r-- | src/mod_trigger_b4_dl.c | 4 | ||||
-rw-r--r-- | src/mod_userdir.c | 13 | ||||
-rw-r--r-- | src/network.c | 28 | ||||
-rw-r--r-- | src/network_openssl.c | 4 | ||||
-rw-r--r-- | src/network_writev.c | 33 | ||||
-rw-r--r-- | src/proc_open.c | 1 | ||||
-rw-r--r-- | src/request.c | 73 | ||||
-rw-r--r-- | src/response.c | 19 | ||||
-rw-r--r-- | src/server.c | 90 |
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 @@ -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; @@ -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; +} @@ -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; |