diff options
Diffstat (limited to '')
101 files changed, 27723 insertions, 0 deletions
diff --git a/modules/aaa/.indent.pro b/modules/aaa/.indent.pro new file mode 100644 index 0000000..a9fbe9f --- /dev/null +++ b/modules/aaa/.indent.pro @@ -0,0 +1,54 @@ +-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1 +-TBUFF +-TFILE +-TTRANS +-TUINT4 +-T_trans +-Tallow_options_t +-Tapache_sfio +-Tarray_header +-Tbool_int +-Tbuf_area +-Tbuff_struct +-Tbuffy +-Tcmd_how +-Tcmd_parms +-Tcommand_rec +-Tcommand_struct +-Tconn_rec +-Tcore_dir_config +-Tcore_server_config +-Tdir_maker_func +-Tevent +-Tglobals_s +-Thandler_func +-Thandler_rec +-Tjoblist_s +-Tlisten_rec +-Tmerger_func +-Tmode_t +-Tmodule +-Tmodule_struct +-Tmutex +-Tn_long +-Tother_child_rec +-Toverrides_t +-Tparent_score +-Tpid_t +-Tpiped_log +-Tpool +-Trequest_rec +-Trequire_line +-Trlim_t +-Tscoreboard +-Tsemaphore +-Tserver_addr_rec +-Tserver_rec +-Tserver_rec_chain +-Tshort_score +-Ttable +-Ttable_entry +-Tthread +-Tu_wide_int +-Tvtime_t +-Twide_int diff --git a/modules/aaa/Makefile.in b/modules/aaa/Makefile.in new file mode 100644 index 0000000..167b343 --- /dev/null +++ b/modules/aaa/Makefile.in @@ -0,0 +1,3 @@ + +include $(top_srcdir)/build/special.mk + diff --git a/modules/aaa/NWGNUaccesscompat b/modules/aaa/NWGNUaccesscompat new file mode 100644 index 0000000..bfa7b20 --- /dev/null +++ b/modules/aaa/NWGNUaccesscompat @@ -0,0 +1,248 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = accesscompat + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) host access control compatibility Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = AccessCompModule + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/accesscompat.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_access_compat.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + access_compat_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/aaa/NWGNUallowmethods b/modules/aaa/NWGNUallowmethods new file mode 100644 index 0000000..c2373f5 --- /dev/null +++ b/modules/aaa/NWGNUallowmethods @@ -0,0 +1,248 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = allowmethods + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) Method Restriction Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = Allowmethods Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/allowmethods.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_allowmethods.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + allowmethods_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/aaa/NWGNUauthbasc b/modules/aaa/NWGNUauthbasc new file mode 100644 index 0000000..1f43464 --- /dev/null +++ b/modules/aaa/NWGNUauthbasc @@ -0,0 +1,248 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = authbasc + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) Basic Authentication Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = AuthBasic Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/authbasc.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_auth_basic.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + auth_basic_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/aaa/NWGNUauthdigt b/modules/aaa/NWGNUauthdigt new file mode 100644 index 0000000..39738f2 --- /dev/null +++ b/modules/aaa/NWGNUauthdigt @@ -0,0 +1,248 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = authdigt + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) Digest Authentication Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = Digest Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/authdigt.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_auth_digest.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + auth_digest_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/aaa/NWGNUauthform b/modules/aaa/NWGNUauthform new file mode 100644 index 0000000..5b42ab5 --- /dev/null +++ b/modules/aaa/NWGNUauthform @@ -0,0 +1,250 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(STDMOD)/session \ + $(STDMOD)/filters \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = authform + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) Basic Authentication Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = AuthBasic Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/$(NLM_NAME).nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_auth_form.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + auth_form_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/aaa/NWGNUauthnano b/modules/aaa/NWGNUauthnano new file mode 100644 index 0000000..b115314 --- /dev/null +++ b/modules/aaa/NWGNUauthnano @@ -0,0 +1,248 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = authnano + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) Anonymous Authentication Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = AuthAnon Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/authnano.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_authn_anon.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + authn_anon_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/aaa/NWGNUauthndbd b/modules/aaa/NWGNUauthndbd new file mode 100644 index 0000000..151bc1c --- /dev/null +++ b/modules/aaa/NWGNUauthndbd @@ -0,0 +1,249 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(AP_WORK)/modules/database \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = authndbd + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) SQL Database Authentication Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = AuthnDBD Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/authndbd.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_authn_dbd.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + authn_dbd_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/aaa/NWGNUauthndbm b/modules/aaa/NWGNUauthndbm new file mode 100644 index 0000000..1f9880e --- /dev/null +++ b/modules/aaa/NWGNUauthndbm @@ -0,0 +1,248 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = authndbm + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) Database Authentication Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = AuthnDBM Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/authndbm.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_authn_dbm.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + authn_dbm_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/aaa/NWGNUauthnfil b/modules/aaa/NWGNUauthnfil new file mode 100644 index 0000000..cfab287 --- /dev/null +++ b/modules/aaa/NWGNUauthnfil @@ -0,0 +1,248 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = authnfil + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) File Authentication Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = AuthnFile Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/authnfil.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_authn_file.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + authn_file_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/aaa/NWGNUauthnsocache b/modules/aaa/NWGNUauthnsocache new file mode 100644 index 0000000..8d1b347 --- /dev/null +++ b/modules/aaa/NWGNUauthnsocache @@ -0,0 +1,248 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = authnsocache + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) Authentication Cache Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = AuthnSOCache Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/authnsocache.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_authn_socache.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + authn_socache_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/aaa/NWGNUauthnzldap b/modules/aaa/NWGNUauthnzldap new file mode 100644 index 0000000..bfe21db --- /dev/null +++ b/modules/aaa/NWGNUauthnzldap @@ -0,0 +1,264 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +#LDAP client requires the use of Winsock +# +ifdef USE_STDSOCKETS +XDEFINES += -DUSE_WINSOCK \ + $(EOLIST) +endif + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = authnzldap + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) LDAP Authentication Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = AuthnzLDAP Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/authnzldap.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_authnz_ldap.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + lldapsdk \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + util_ldap_connection_find \ + util_ldap_connection_close \ + util_ldap_cache_checkuserid \ + util_ldap_cache_getuserdn \ + util_ldap_cache_compare \ + util_ldap_cache_comparedn \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + @lldapsdk.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + authnz_ldap_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/aaa/NWGNUauthzdbd b/modules/aaa/NWGNUauthzdbd new file mode 100644 index 0000000..3ea2ba7 --- /dev/null +++ b/modules/aaa/NWGNUauthzdbd @@ -0,0 +1,249 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(STDMOD)/database \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = authzdbd + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) DBD Database Authorization Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = AuthzDBD Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/authzdbd.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_authz_dbd.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + authz_dbd_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/aaa/NWGNUauthzdbm b/modules/aaa/NWGNUauthzdbm new file mode 100644 index 0000000..3d0ed8f --- /dev/null +++ b/modules/aaa/NWGNUauthzdbm @@ -0,0 +1,248 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = authzdbm + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) Database Authorization Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = AuthzDBM Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/authzdbm.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_authz_dbm.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + authz_dbm_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/aaa/NWGNUauthzgrp b/modules/aaa/NWGNUauthzgrp new file mode 100644 index 0000000..4a8df2c --- /dev/null +++ b/modules/aaa/NWGNUauthzgrp @@ -0,0 +1,247 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = authzgrp + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) Group File Authorization Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = AuthzGrp Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/authzgrp.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_authz_groupfile.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + authz_groupfile_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + diff --git a/modules/aaa/NWGNUauthzusr b/modules/aaa/NWGNUauthzusr new file mode 100644 index 0000000..aa79053 --- /dev/null +++ b/modules/aaa/NWGNUauthzusr @@ -0,0 +1,247 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(AP_WORK)/build/NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(AP_WORK)/include \ + $(NWOS) \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = authzusr + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) User Authorization Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = AuthzUser Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/authzusr.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_authz_user.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(PRELUDE) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + authz_user_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + diff --git a/modules/aaa/NWGNUmakefile b/modules/aaa/NWGNUmakefile new file mode 100644 index 0000000..fdb23f6 --- /dev/null +++ b/modules/aaa/NWGNUmakefile @@ -0,0 +1,270 @@ +# +# Declare the sub-directories to be built here +# + +SUBDIRS = \ + $(EOLIST) + +# +# Get the 'head' of the build environment. This includes default targets and +# paths to tools +# + +include $(AP_WORK)/build/NWGNUhead.inc + +# +# build this level's files + +# +# Make sure all needed macro's are defined +# +ifeq "$(wildcard $(APRUTIL)/include/apr_ldap.h)" "$(APRUTIL)/include/apr_ldap.h" +WITH_LDAP = $(shell $(AWK) '/^\#define APR_HAS_LDAP /{print $$3}' $(APRUTIL)/include/apr_ldap.h) +else +WITH_LDAP = 0 +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)/build/NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/authbasc.nlm \ + $(OBJDIR)/authdigt.nlm \ + $(OBJDIR)/authform.nlm \ + $(OBJDIR)/authnano.nlm \ + $(OBJDIR)/authndbd.nlm \ + $(OBJDIR)/authndbm.nlm \ + $(OBJDIR)/authnfil.nlm \ + $(OBJDIR)/authnsocache.nlm \ + $(OBJDIR)/authzdbd.nlm \ + $(OBJDIR)/authzdbm.nlm \ + $(OBJDIR)/authzgrp.nlm \ + $(OBJDIR)/authzusr.nlm \ + $(OBJDIR)/allowmethods.nlm \ + $(OBJDIR)/accesscompat.nlm \ + $(EOLIST) + +# If WITH_LDAP and LDAPSDK have been defined then build the authnz_ldap module +ifeq "$(WITH_LDAP)" "1" +ifneq "$(LDAPSDK)" "" +TARGET_nlm += $(OBJDIR)/authnzldap.nlm +endif +endif + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) +# +install :: nlms FORCE + $(call COPY,$(OBJDIR)/*.nlm, $(INSTALLBASE)/modules/) + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/aaa/config.m4 b/modules/aaa/config.m4 new file mode 100644 index 0000000..b443761 --- /dev/null +++ b/modules/aaa/config.m4 @@ -0,0 +1,84 @@ +dnl modules enabled in this directory by default + +dnl Authentication (authn), Access, and Authorization (authz) + +dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]]) + +APACHE_MODPATH_INIT(aaa) + +dnl Authentication modules; modules checking a username and password against a +dnl file, database, or other similar magic. +dnl +APACHE_MODULE(authn_file, file-based authentication control, , , yes) +APACHE_MODULE(authn_dbm, DBM-based authentication control, , , most) +APACHE_MODULE(authn_anon, anonymous user authentication control, , , most) +APACHE_MODULE(authn_dbd, SQL-based authentication control, , , most) +APACHE_MODULE(authn_socache, Cached authentication control, , , most) + +dnl General Authentication modules; module which implements the +dnl non-authn module specific directives. +dnl +APACHE_MODULE(authn_core, core authentication module, , , yes) + +dnl Authorization modules: modules which verify a certain property such as +dnl membership of a group, value of the IP address against a list of pre +dnl configured directives (e.g. require, allow) or against an external file +dnl or database. +dnl +APACHE_MODULE(authz_host, host-based authorization control, , , yes) +APACHE_MODULE(authz_groupfile, 'require group' authorization control, , , yes) +APACHE_MODULE(authz_user, 'require user' authorization control, , , yes) +APACHE_MODULE(authz_dbm, DBM-based authorization control, , , most) +APACHE_MODULE(authz_owner, 'require file-owner' authorization control, , , most) +APACHE_MODULE(authz_dbd, SQL based authorization and Login/Session support, , , most) + +dnl General Authorization modules; provider module which implements the +dnl non-authz module specific directives. +dnl +APACHE_MODULE(authz_core, core authorization provider vector module, , , yes) + +dnl LDAP authentication module. This module has both the authn and authz +dnl modules in one, so as to share the LDAP server config directives. +APACHE_MODULE(authnz_ldap, LDAP based authentication, , , most, [ + APACHE_CHECK_APR_HAS_LDAP + if test "$ac_cv_APR_HAS_LDAP" = "yes" ; then + if test -z "$apu_config" ; then + LDAP_LIBS="`$apr_config --ldap-libs`" + else + LDAP_LIBS="`$apu_config --ldap-libs`" + fi + APR_ADDTO(MOD_AUTHNZ_LDAP_LDADD, [$LDAP_LIBS]) + AC_SUBST(MOD_AUTHNZ_LDAP_LDADD) + else + AC_MSG_WARN([apr/apr-util is compiled without ldap support]) + enable_authnz_ldap=no + fi +]) + +dnl FastCGI authorizer interface, supporting authn and authz. +APACHE_MODULE(authnz_fcgi, + FastCGI authorizer-based authentication and authorization, , , no) + +dnl - host access control compatibility modules. Implements Order, Allow, +dnl Deny, Satisfy for backward compatibility. These directives have been +dnl deprecated in 2.4. +APACHE_MODULE(access_compat, mod_access compatibility, , , yes) + +dnl these are the front-end authentication modules + +APACHE_MODULE(auth_basic, basic authentication, , , yes) +APACHE_MODULE(auth_form, form authentication, , , most) +APACHE_MODULE(auth_digest, RFC2617 Digest authentication, , , most, [ + APR_CHECK_APR_DEFINE(APR_HAS_RANDOM) + if test $ac_cv_define_APR_HAS_RANDOM = "no"; then + echo "You need APR random support to use mod_auth_digest." + echo "Look at APR configure options --with-egd and --with-devrandom." + enable_auth_digest="no" + fi +]) + +APACHE_MODULE(allowmethods, restrict allowed HTTP methods, , , most) + +APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current]) + +APACHE_MODPATH_FINISH diff --git a/modules/aaa/mod_access_compat.c b/modules/aaa/mod_access_compat.c new file mode 100644 index 0000000..e9f1abe --- /dev/null +++ b/modules/aaa/mod_access_compat.c @@ -0,0 +1,377 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Security options etc. + * + * Module derived from code originally written by Rob McCool + * + */ + +#include "apr_strings.h" +#include "apr_network_io.h" +#include "apr_md5.h" + +#define APR_WANT_STRFUNC +#define APR_WANT_BYTEFUNC +#include "apr_want.h" + +#include "ap_config.h" +#include "httpd.h" +#include "http_core.h" +#include "http_config.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" + +#include "mod_auth.h" + +#if APR_HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +enum allowdeny_type { + T_ENV, + T_NENV, + T_ALL, + T_IP, + T_HOST, + T_FAIL +}; + +typedef struct { + apr_int64_t limited; + union { + char *from; + apr_ipsubnet_t *ip; + } x; + enum allowdeny_type type; +} allowdeny; + +/* things in the 'order' array */ +#define DENY_THEN_ALLOW 0 +#define ALLOW_THEN_DENY 1 +#define MUTUAL_FAILURE 2 + +typedef struct { + int order[METHODS]; + apr_array_header_t *allows; + apr_array_header_t *denys; + int *satisfy; /* for every method one */ +} access_compat_dir_conf; + +module AP_MODULE_DECLARE_DATA access_compat_module; + +static void *create_access_compat_dir_config(apr_pool_t *p, char *dummy) +{ + int i; + access_compat_dir_conf *conf = + (access_compat_dir_conf *)apr_pcalloc(p, sizeof(access_compat_dir_conf)); + + for (i = 0; i < METHODS; ++i) { + conf->order[i] = DENY_THEN_ALLOW; + } + conf->allows = apr_array_make(p, 1, sizeof(allowdeny)); + conf->denys = apr_array_make(p, 1, sizeof(allowdeny)); + conf->satisfy = apr_palloc(p, sizeof(*conf->satisfy) * METHODS); + for (i = 0; i < METHODS; ++i) { + conf->satisfy[i] = SATISFY_NOSPEC; + } + + return (void *)conf; +} + +static const char *order(cmd_parms *cmd, void *dv, const char *arg) +{ + access_compat_dir_conf *d = (access_compat_dir_conf *) dv; + int i, o; + + if (!strcasecmp(arg, "allow,deny")) + o = ALLOW_THEN_DENY; + else if (!strcasecmp(arg, "deny,allow")) + o = DENY_THEN_ALLOW; + else if (!strcasecmp(arg, "mutual-failure")) + o = MUTUAL_FAILURE; + else + return "unknown order"; + + for (i = 0; i < METHODS; ++i) + if (cmd->limited & (AP_METHOD_BIT << i)) + d->order[i] = o; + + return NULL; +} + +static const char *satisfy(cmd_parms *cmd, void *dv, const char *arg) +{ + access_compat_dir_conf *d = (access_compat_dir_conf *) dv; + int satisfy = SATISFY_NOSPEC; + int i; + + if (!strcasecmp(arg, "all")) { + satisfy = SATISFY_ALL; + } + else if (!strcasecmp(arg, "any")) { + satisfy = SATISFY_ANY; + } + else { + return "Satisfy either 'any' or 'all'."; + } + + for (i = 0; i < METHODS; ++i) { + if (cmd->limited & (AP_METHOD_BIT << i)) { + d->satisfy[i] = satisfy; + } + } + + return NULL; +} + +static const char *allow_cmd(cmd_parms *cmd, void *dv, const char *from, + const char *where_c) +{ + access_compat_dir_conf *d = (access_compat_dir_conf *) dv; + allowdeny *a; + char *where = apr_pstrdup(cmd->pool, where_c); + char *s; + apr_status_t rv; + + if (strcasecmp(from, "from")) + return "allow and deny must be followed by 'from'"; + + a = (allowdeny *) apr_array_push(cmd->info ? d->allows : d->denys); + a->x.from = where; + a->limited = cmd->limited; + + if (!strncasecmp(where, "env=!", 5)) { + a->type = T_NENV; + a->x.from += 5; + + } + else if (!strncasecmp(where, "env=", 4)) { + a->type = T_ENV; + a->x.from += 4; + + } + else if (!strcasecmp(where, "all")) { + a->type = T_ALL; + } + else if ((s = ap_strchr(where, '/'))) { + *s++ = '\0'; + rv = apr_ipsubnet_create(&a->x.ip, where, s, cmd->pool); + if(APR_STATUS_IS_EINVAL(rv)) { + /* looked nothing like an IP address */ + return "An IP address was expected"; + } + else if (rv != APR_SUCCESS) { + return apr_psprintf(cmd->pool, "%pm", &rv); + } + a->type = T_IP; + } + else if (!APR_STATUS_IS_EINVAL(rv = apr_ipsubnet_create(&a->x.ip, where, + NULL, cmd->pool))) { + if (rv != APR_SUCCESS) + return apr_psprintf(cmd->pool, "%pm", &rv); + a->type = T_IP; + } + else if (ap_strchr(where, '#')) { + return "No comments are allowed here"; + } + else { /* no slash, didn't look like an IP address => must be a host */ + a->type = T_HOST; + } + + return NULL; +} + +static char its_an_allow; + +static const command_rec access_compat_cmds[] = +{ + AP_INIT_TAKE1("order", order, NULL, OR_LIMIT, + "'allow,deny', 'deny,allow', or 'mutual-failure'"), + AP_INIT_ITERATE2("allow", allow_cmd, &its_an_allow, OR_LIMIT, + "'from' followed by hostnames or IP-address wildcards"), + AP_INIT_ITERATE2("deny", allow_cmd, NULL, OR_LIMIT, + "'from' followed by hostnames or IP-address wildcards"), + AP_INIT_TAKE1("Satisfy", satisfy, NULL, OR_AUTHCFG, + "access policy if both allow and require used ('all' or 'any')"), + {NULL} +}; + +static int in_domain(const char *domain, const char *what) +{ + int dl = strlen(domain); + int wl = strlen(what); + + if ((wl - dl) >= 0) { + if (strcasecmp(domain, &what[wl - dl]) != 0) { + return 0; + } + + /* Make sure we matched an *entire* subdomain --- if the user + * said 'allow from good.com', we don't want people from nogood.com + * to be able to get in. + */ + + if (wl == dl) { + return 1; /* matched whole thing */ + } + else { + return (domain[0] == '.' || what[wl - dl - 1] == '.'); + } + } + else { + return 0; + } +} + +static int find_allowdeny(request_rec *r, apr_array_header_t *a, int method) +{ + + allowdeny *ap = (allowdeny *) a->elts; + apr_int64_t mmask = (AP_METHOD_BIT << method); + int i; + int gothost = 0; + const char *remotehost = NULL; + + for (i = 0; i < a->nelts; ++i) { + if (!(mmask & ap[i].limited)) { + continue; + } + + switch (ap[i].type) { + case T_ENV: + if (apr_table_get(r->subprocess_env, ap[i].x.from)) { + return 1; + } + break; + + case T_NENV: + if (!apr_table_get(r->subprocess_env, ap[i].x.from)) { + return 1; + } + break; + + case T_ALL: + return 1; + + case T_IP: + if (apr_ipsubnet_test(ap[i].x.ip, r->useragent_addr)) { + return 1; + } + break; + + case T_HOST: + if (!gothost) { + int remotehost_is_ip; + + remotehost = ap_get_useragent_host(r, REMOTE_DOUBLE_REV, + &remotehost_is_ip); + + if ((remotehost == NULL) || remotehost_is_ip) { + gothost = 1; + } + else { + gothost = 2; + } + } + + if ((gothost == 2) && in_domain(ap[i].x.from, remotehost)) { + return 1; + } + break; + + case T_FAIL: + /* do nothing? */ + break; + } + } + + return 0; +} + +static int access_compat_ap_satisfies(request_rec *r) +{ + access_compat_dir_conf *conf = (access_compat_dir_conf *) + ap_get_module_config(r->per_dir_config, &access_compat_module); + + return conf->satisfy[r->method_number]; +} + +static int check_dir_access(request_rec *r) +{ + int method = r->method_number; + int ret = OK; + access_compat_dir_conf *a = (access_compat_dir_conf *) + ap_get_module_config(r->per_dir_config, &access_compat_module); + + if (a->order[method] == ALLOW_THEN_DENY) { + ret = HTTP_FORBIDDEN; + if (find_allowdeny(r, a->allows, method)) { + ret = OK; + } + if (find_allowdeny(r, a->denys, method)) { + ret = HTTP_FORBIDDEN; + } + } + else if (a->order[method] == DENY_THEN_ALLOW) { + if (find_allowdeny(r, a->denys, method)) { + ret = HTTP_FORBIDDEN; + } + if (find_allowdeny(r, a->allows, method)) { + ret = OK; + } + } + else { + if (find_allowdeny(r, a->allows, method) + && !find_allowdeny(r, a->denys, method)) { + ret = OK; + } + else { + ret = HTTP_FORBIDDEN; + } + } + + if (ret == HTTP_FORBIDDEN) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01797) + "client denied by server configuration: %s%s", + r->filename ? "" : "uri ", + r->filename ? r->filename : r->uri); + } + + return ret; +} + +static void register_hooks(apr_pool_t *p) +{ + APR_REGISTER_OPTIONAL_FN(access_compat_ap_satisfies); + + /* This can be access checker since we don't require r->user to be set. */ + ap_hook_check_access(check_dir_access, NULL, NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); +} + +AP_DECLARE_MODULE(access_compat) = +{ + STANDARD20_MODULE_STUFF, + create_access_compat_dir_config, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + access_compat_cmds, + register_hooks /* register hooks */ +}; diff --git a/modules/aaa/mod_access_compat.dep b/modules/aaa/mod_access_compat.dep new file mode 100644 index 0000000..e3f5e97 --- /dev/null +++ b/modules/aaa/mod_access_compat.dep @@ -0,0 +1,59 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_access_compat.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_access_compat.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_md5.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apr_xlate.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_access_compat.dsp b/modules/aaa/mod_access_compat.dsp new file mode 100644 index 0000000..c0cef15 --- /dev/null +++ b/modules/aaa/mod_access_compat.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_access_compat" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_access_compat - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_access_compat.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_access_compat.mak" CFG="mod_access_compat - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_access_compat - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_access_compat - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_access_compat - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AAA_DECLARE_EXPORT" /Fd"Release\mod_access_compat_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_access_compat.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_access_compat.so" /d LONG_NAME="access_compat_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_access_compat.so" /base:@..\..\os\win32\BaseAddr.ref,mod_access_compat.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_access_compat.so" /base:@..\..\os\win32\BaseAddr.ref,mod_access_compat.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_access_compat.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_access_compat - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "AAA_DECLARE_EXPORT" /Fd"Debug\mod_access_compat_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_access_compat.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_access_compat.so" /d LONG_NAME="access_compat_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_access_compat.so" /base:@..\..\os\win32\BaseAddr.ref,mod_access_compat.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_access_compat.so" /base:@..\..\os\win32\BaseAddr.ref,mod_access_compat.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_access_compat.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_access_compat - Win32 Release" +# Name "mod_access_compat - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_access_compat.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_access_compat.mak b/modules/aaa/mod_access_compat.mak new file mode 100644 index 0000000..4d80704 --- /dev/null +++ b/modules/aaa/mod_access_compat.mak @@ -0,0 +1,353 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_access_compat.dsp +!IF "$(CFG)" == "" +CFG=mod_access_compat - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_access_compat - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_access_compat - Win32 Release" && "$(CFG)" != "mod_access_compat - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_access_compat.mak" CFG="mod_access_compat - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_access_compat - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_access_compat - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_access_compat - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_access_compat.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_access_compat.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_access_compat.obj" + -@erase "$(INTDIR)\mod_access_compat.res" + -@erase "$(INTDIR)\mod_access_compat_src.idb" + -@erase "$(INTDIR)\mod_access_compat_src.pdb" + -@erase "$(OUTDIR)\mod_access_compat.exp" + -@erase "$(OUTDIR)\mod_access_compat.lib" + -@erase "$(OUTDIR)\mod_access_compat.pdb" + -@erase "$(OUTDIR)\mod_access_compat.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AAA_DECLARE_EXPORT" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_access_compat_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_access_compat.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_access_compat.so" /d LONG_NAME="access_compat_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_access_compat.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_access_compat.pdb" /debug /out:"$(OUTDIR)\mod_access_compat.so" /implib:"$(OUTDIR)\mod_access_compat.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_access_compat.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_access_compat.obj" \ + "$(INTDIR)\mod_access_compat.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" + +"$(OUTDIR)\mod_access_compat.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_access_compat.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_access_compat.so" + if exist .\Release\mod_access_compat.so.manifest mt.exe -manifest .\Release\mod_access_compat.so.manifest -outputresource:.\Release\mod_access_compat.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_access_compat - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_access_compat.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_access_compat.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_access_compat.obj" + -@erase "$(INTDIR)\mod_access_compat.res" + -@erase "$(INTDIR)\mod_access_compat_src.idb" + -@erase "$(INTDIR)\mod_access_compat_src.pdb" + -@erase "$(OUTDIR)\mod_access_compat.exp" + -@erase "$(OUTDIR)\mod_access_compat.lib" + -@erase "$(OUTDIR)\mod_access_compat.pdb" + -@erase "$(OUTDIR)\mod_access_compat.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "AAA_DECLARE_EXPORT" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_access_compat_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_access_compat.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_access_compat.so" /d LONG_NAME="access_compat_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_access_compat.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_access_compat.pdb" /debug /out:"$(OUTDIR)\mod_access_compat.so" /implib:"$(OUTDIR)\mod_access_compat.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_access_compat.so +LINK32_OBJS= \ + "$(INTDIR)\mod_access_compat.obj" \ + "$(INTDIR)\mod_access_compat.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" + +"$(OUTDIR)\mod_access_compat.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_access_compat.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_access_compat.so" + if exist .\Debug\mod_access_compat.so.manifest mt.exe -manifest .\Debug\mod_access_compat.so.manifest -outputresource:.\Debug\mod_access_compat.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_access_compat.dep") +!INCLUDE "mod_access_compat.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_access_compat.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_access_compat - Win32 Release" || "$(CFG)" == "mod_access_compat - Win32 Debug" + +!IF "$(CFG)" == "mod_access_compat - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_access_compat - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_access_compat - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_access_compat - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_access_compat - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_access_compat - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_access_compat - Win32 Release" + + +"$(INTDIR)\mod_access_compat.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_access_compat.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_access_compat.so" /d LONG_NAME="access_compat_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_access_compat - Win32 Debug" + + +"$(INTDIR)\mod_access_compat.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_access_compat.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_access_compat.so" /d LONG_NAME="access_compat_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_access_compat.c + +"$(INTDIR)\mod_access_compat.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_allowmethods.c b/modules/aaa/mod_allowmethods.c new file mode 100644 index 0000000..dd41196 --- /dev/null +++ b/modules/aaa/mod_allowmethods.c @@ -0,0 +1,158 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "httpd.h" +#include "http_core.h" +#include "http_config.h" +#include "http_protocol.h" +#include "http_request.h" +#include "http_log.h" +#include "apr_strings.h" + +/** + * This module makes it easy to restrict what HTTP methods can be ran against + * a server. + * + * It provides one command: + * AllowMethods + * This command takes a list of HTTP methods to allow. + * + * The most common configuration should be like this: + * <Directory /> + * AllowMethods GET HEAD OPTIONS + * </Directory> + * <Directory /special/cgi-bin> + * AllowMethods GET HEAD OPTIONS POST + * </Directory> + * Non-matching methods will be returned a status 405 (method not allowed) + * + * To allow all methods, and effectively turn off mod_allowmethods, use: + * AllowMethods reset + */ + +typedef struct am_conf_t { + int allowed_set; + apr_int64_t allowed; +} am_conf_t; + +module AP_MODULE_DECLARE_DATA allowmethods_module; + +static int am_check_access(request_rec *r) +{ + int method = r->method_number; + am_conf_t *conf; + + conf = (am_conf_t *) ap_get_module_config(r->per_dir_config, + &allowmethods_module); + if (!conf || conf->allowed == 0) { + return DECLINED; + } + + r->allowed = conf->allowed; + + if (conf->allowed & (AP_METHOD_BIT << method)) { + return DECLINED; + } + + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01623) + "client method denied by server configuration: '%s' to %s%s", + r->method, + r->filename ? "" : "uri ", + r->filename ? r->filename : r->uri); + + return HTTP_METHOD_NOT_ALLOWED; +} + +static void *am_create_conf(apr_pool_t *p, char *dummy) +{ + am_conf_t *conf = apr_pcalloc(p, sizeof(am_conf_t)); + + conf->allowed = 0; + conf->allowed_set = 0; + return conf; +} + +static void *am_merge_conf(apr_pool_t *pool, void *a, void *b) +{ + am_conf_t *base = (am_conf_t *)a; + am_conf_t *add = (am_conf_t *)b; + am_conf_t *conf = apr_palloc(pool, sizeof(am_conf_t)); + + if (add->allowed_set) { + conf->allowed = add->allowed; + conf->allowed_set = add->allowed_set; + } + else { + conf->allowed = base->allowed; + conf->allowed_set = base->allowed_set; + } + + return conf; +} + +static const char *am_allowmethods(cmd_parms *cmd, void *d, int argc, + char *const argv[]) +{ + int i; + am_conf_t *conf = (am_conf_t *)d; + + if (argc == 0) { + return "AllowMethods: No method or 'reset' keyword given"; + } + if (argc == 1) { + if (strcasecmp("reset", argv[0]) == 0) { + conf->allowed = 0; + conf->allowed_set = 1; + return NULL; + } + } + + for (i = 0; i < argc; i++) { + int m; + + m = ap_method_number_of(argv[i]); + if (m == M_INVALID) { + return apr_pstrcat(cmd->pool, "AllowMethods: Invalid Method '", + argv[i], "'", NULL); + } + + conf->allowed |= (AP_METHOD_BIT << m); + } + conf->allowed_set = 1; + return NULL; +} + +static void am_register_hooks(apr_pool_t * p) +{ + ap_hook_access_checker(am_check_access, NULL, NULL, APR_HOOK_REALLY_FIRST); +} + +static const command_rec am_cmds[] = { + AP_INIT_TAKE_ARGV("AllowMethods", am_allowmethods, NULL, + ACCESS_CONF, + "only allow specific methods"), + {NULL} +}; + +AP_DECLARE_MODULE(allowmethods) = { + STANDARD20_MODULE_STUFF, + am_create_conf, + am_merge_conf, + NULL, + NULL, + am_cmds, + am_register_hooks, +}; diff --git a/modules/aaa/mod_allowmethods.dep b/modules/aaa/mod_allowmethods.dep new file mode 100644 index 0000000..04db445 --- /dev/null +++ b/modules/aaa/mod_allowmethods.dep @@ -0,0 +1,56 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_allowmethods.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_allowmethods.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_allowmethods.dsp b/modules/aaa/mod_allowmethods.dsp new file mode 100644 index 0000000..446f8dc --- /dev/null +++ b/modules/aaa/mod_allowmethods.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_allowmethods" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_allowmethods - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_allowmethods.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_allowmethods.mak" CFG="mod_allowmethods - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_allowmethods - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_allowmethods - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_allowmethods - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_allowmethods_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_allowmethods.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_allowmethods.so" /d LONG_NAME="allowmethods_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_allowmethods.so" /base:@..\..\os\win32\BaseAddr.ref,mod_allowmethods.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_allowmethods.so" /base:@..\..\os\win32\BaseAddr.ref,mod_allowmethods.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_allowmethods.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_allowmethods - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_allowmethods_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_allowmethods.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_allowmethods.so" /d LONG_NAME="allowmethods_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_allowmethods.so" /base:@..\..\os\win32\BaseAddr.ref,mod_allowmethods.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_allowmethods.so" /base:@..\..\os\win32\BaseAddr.ref,mod_allowmethods.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_allowmethods.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_allowmethods - Win32 Release" +# Name "mod_allowmethods - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_allowmethods.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_allowmethods.mak b/modules/aaa/mod_allowmethods.mak new file mode 100644 index 0000000..1049515 --- /dev/null +++ b/modules/aaa/mod_allowmethods.mak @@ -0,0 +1,353 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_allowmethods.dsp +!IF "$(CFG)" == "" +CFG=mod_allowmethods - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_allowmethods - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_allowmethods - Win32 Release" && "$(CFG)" != "mod_allowmethods - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_allowmethods.mak" CFG="mod_allowmethods - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_allowmethods - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_allowmethods - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_allowmethods - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_allowmethods.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_allowmethods.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_allowmethods.obj" + -@erase "$(INTDIR)\mod_allowmethods.res" + -@erase "$(INTDIR)\mod_allowmethods_src.idb" + -@erase "$(INTDIR)\mod_allowmethods_src.pdb" + -@erase "$(OUTDIR)\mod_allowmethods.exp" + -@erase "$(OUTDIR)\mod_allowmethods.lib" + -@erase "$(OUTDIR)\mod_allowmethods.pdb" + -@erase "$(OUTDIR)\mod_allowmethods.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_allowmethods_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_allowmethods.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_allowmethods.so" /d LONG_NAME="allowmethods_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_allowmethods.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_allowmethods.pdb" /debug /out:"$(OUTDIR)\mod_allowmethods.so" /implib:"$(OUTDIR)\mod_allowmethods.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_allowmethods.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_allowmethods.obj" \ + "$(INTDIR)\mod_allowmethods.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" + +"$(OUTDIR)\mod_allowmethods.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_allowmethods.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_allowmethods.so" + if exist .\Release\mod_allowmethods.so.manifest mt.exe -manifest .\Release\mod_allowmethods.so.manifest -outputresource:.\Release\mod_allowmethods.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_allowmethods - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_allowmethods.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_allowmethods.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_allowmethods.obj" + -@erase "$(INTDIR)\mod_allowmethods.res" + -@erase "$(INTDIR)\mod_allowmethods_src.idb" + -@erase "$(INTDIR)\mod_allowmethods_src.pdb" + -@erase "$(OUTDIR)\mod_allowmethods.exp" + -@erase "$(OUTDIR)\mod_allowmethods.lib" + -@erase "$(OUTDIR)\mod_allowmethods.pdb" + -@erase "$(OUTDIR)\mod_allowmethods.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_allowmethods_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_allowmethods.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_allowmethods.so" /d LONG_NAME="allowmethods_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_allowmethods.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_allowmethods.pdb" /debug /out:"$(OUTDIR)\mod_allowmethods.so" /implib:"$(OUTDIR)\mod_allowmethods.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_allowmethods.so +LINK32_OBJS= \ + "$(INTDIR)\mod_allowmethods.obj" \ + "$(INTDIR)\mod_allowmethods.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" + +"$(OUTDIR)\mod_allowmethods.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_allowmethods.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_allowmethods.so" + if exist .\Debug\mod_allowmethods.so.manifest mt.exe -manifest .\Debug\mod_allowmethods.so.manifest -outputresource:.\Debug\mod_allowmethods.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_allowmethods.dep") +!INCLUDE "mod_allowmethods.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_allowmethods.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_allowmethods - Win32 Release" || "$(CFG)" == "mod_allowmethods - Win32 Debug" + +!IF "$(CFG)" == "mod_allowmethods - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_allowmethods - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_allowmethods - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_allowmethods - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_allowmethods - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_allowmethods - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_allowmethods - Win32 Release" + + +"$(INTDIR)\mod_allowmethods.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_allowmethods.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_allowmethods.so" /d LONG_NAME="allowmethods_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_allowmethods - Win32 Debug" + + +"$(INTDIR)\mod_allowmethods.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_allowmethods.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_allowmethods.so" /d LONG_NAME="allowmethods_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_allowmethods.c + +"$(INTDIR)\mod_allowmethods.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_auth_basic.c b/modules/aaa/mod_auth_basic.c new file mode 100644 index 0000000..4e1d47f --- /dev/null +++ b/modules/aaa/mod_auth_basic.c @@ -0,0 +1,508 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_strings.h" +#include "apr_lib.h" /* for apr_isspace */ +#include "apr_base64.h" /* for apr_base64_decode et al */ +#define APR_WANT_STRFUNC /* for strcasecmp */ +#include "apr_want.h" + +#include "ap_config.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" +#include "util_md5.h" +#include "ap_provider.h" +#include "ap_expr.h" + +#include "mod_auth.h" + +typedef struct { + authn_provider_list *providers; + char *dir; /* unused variable */ + int authoritative; + ap_expr_info_t *fakeuser; + ap_expr_info_t *fakepass; + const char *use_digest_algorithm; + int fake_set:1; + int use_digest_algorithm_set:1; + int authoritative_set:1; +} auth_basic_config_rec; + +static void *create_auth_basic_dir_config(apr_pool_t *p, char *d) +{ + auth_basic_config_rec *conf = apr_pcalloc(p, sizeof(*conf)); + + /* Any failures are fatal. */ + conf->authoritative = 1; + + return conf; +} + +static void *merge_auth_basic_dir_config(apr_pool_t *p, void *basev, void *overridesv) +{ + auth_basic_config_rec *newconf = apr_pcalloc(p, sizeof(*newconf)); + auth_basic_config_rec *base = basev; + auth_basic_config_rec *overrides = overridesv; + + newconf->authoritative = + overrides->authoritative_set ? overrides->authoritative : + base->authoritative; + newconf->authoritative_set = overrides->authoritative_set + || base->authoritative_set; + + newconf->fakeuser = + overrides->fake_set ? overrides->fakeuser : base->fakeuser; + newconf->fakepass = + overrides->fake_set ? overrides->fakepass : base->fakepass; + newconf->fake_set = overrides->fake_set || base->fake_set; + + newconf->use_digest_algorithm = + overrides->use_digest_algorithm_set ? overrides->use_digest_algorithm + : base->use_digest_algorithm; + newconf->use_digest_algorithm_set = + overrides->use_digest_algorithm_set || base->use_digest_algorithm_set; + + newconf->providers = overrides->providers ? overrides->providers : base->providers; + + return newconf; +} + +static const char *add_authn_provider(cmd_parms *cmd, void *config, + const char *arg) +{ + auth_basic_config_rec *conf = (auth_basic_config_rec*)config; + authn_provider_list *newp; + + newp = apr_pcalloc(cmd->pool, sizeof(authn_provider_list)); + newp->provider_name = arg; + + /* lookup and cache the actual provider now */ + newp->provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP, + newp->provider_name, + AUTHN_PROVIDER_VERSION); + + if (newp->provider == NULL) { + /* by the time they use it, the provider should be loaded and + registered with us. */ + return apr_psprintf(cmd->pool, + "Unknown Authn provider: %s", + newp->provider_name); + } + + if (!newp->provider->check_password) { + /* if it doesn't provide the appropriate function, reject it */ + return apr_psprintf(cmd->pool, + "The '%s' Authn provider doesn't support " + "Basic Authentication", newp->provider_name); + } + + /* Add it to the list now. */ + if (!conf->providers) { + conf->providers = newp; + } + else { + authn_provider_list *last = conf->providers; + + while (last->next) { + last = last->next; + } + last->next = newp; + } + + return NULL; +} + +static const char *set_authoritative(cmd_parms * cmd, void *config, int flag) +{ + auth_basic_config_rec *conf = (auth_basic_config_rec *) config; + + conf->authoritative = flag; + conf->authoritative_set = 1; + + return NULL; +} + +static const char *add_basic_fake(cmd_parms * cmd, void *config, + const char *user, const char *pass) +{ + auth_basic_config_rec *conf = (auth_basic_config_rec *) config; + const char *err; + + if (!strcasecmp(user, "off")) { + conf->fakeuser = NULL; + conf->fakepass = NULL; + conf->fake_set = 1; + } + else { + /* if password is unspecified, set it to the fixed string "password" to + * be compatible with the behaviour of mod_ssl. + */ + if (!pass) { + pass = "password"; + } + + conf->fakeuser = + ap_expr_parse_cmd(cmd, user, AP_EXPR_FLAG_STRING_RESULT, + &err, NULL); + if (err) { + return apr_psprintf(cmd->pool, + "Could not parse fake username expression '%s': %s", user, + err); + } + conf->fakepass = + ap_expr_parse_cmd(cmd, pass, AP_EXPR_FLAG_STRING_RESULT, + &err, NULL); + if (err) { + return apr_psprintf(cmd->pool, + "Could not parse fake password expression associated to user '%s': %s", + user, err); + } + conf->fake_set = 1; + } + + return NULL; +} + +static const char *set_use_digest_algorithm(cmd_parms *cmd, void *config, + const char *alg) +{ + auth_basic_config_rec *conf = (auth_basic_config_rec *)config; + + if (strcasecmp(alg, "Off") && strcasecmp(alg, "MD5")) { + return apr_pstrcat(cmd->pool, + "Invalid algorithm in " + "AuthBasicUseDigestAlgorithm: ", alg, NULL); + } + + conf->use_digest_algorithm = alg; + conf->use_digest_algorithm_set = 1; + + return NULL; +} + +static const command_rec auth_basic_cmds[] = +{ + AP_INIT_ITERATE("AuthBasicProvider", add_authn_provider, NULL, OR_AUTHCFG, + "specify the auth providers for a directory or location"), + AP_INIT_FLAG("AuthBasicAuthoritative", set_authoritative, NULL, OR_AUTHCFG, + "Set to 'Off' to allow access control to be passed along to " + "lower modules if the UserID is not known to this module"), + AP_INIT_TAKE12("AuthBasicFake", add_basic_fake, NULL, OR_AUTHCFG, + "Fake basic authentication using the given expressions for " + "username and password, 'off' to disable. Password defaults " + "to 'password' if missing."), + AP_INIT_TAKE1("AuthBasicUseDigestAlgorithm", set_use_digest_algorithm, + NULL, OR_AUTHCFG, + "Set to 'MD5' to use the auth provider's authentication " + "check for digest auth, using a hash of 'user:realm:pass'"), + {NULL} +}; + +module AP_MODULE_DECLARE_DATA auth_basic_module; + +/* These functions return 0 if client is OK, and proper error status + * if not... either HTTP_UNAUTHORIZED, if we made a check, and it failed, or + * HTTP_INTERNAL_SERVER_ERROR, if things are so totally confused that we + * couldn't figure out how to tell if the client is authorized or not. + * + * If they return DECLINED, and all other modules also decline, that's + * treated by the server core as a configuration error, logged and + * reported as such. + */ + +static void note_basic_auth_failure(request_rec *r) +{ + apr_table_setn(r->err_headers_out, + (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate" + : "WWW-Authenticate", + apr_pstrcat(r->pool, "Basic realm=\"", ap_auth_name(r), + "\"", NULL)); +} + +static int hook_note_basic_auth_failure(request_rec *r, const char *auth_type) +{ + if (ap_cstr_casecmp(auth_type, "Basic")) + return DECLINED; + + note_basic_auth_failure(r); + return OK; +} + +static int get_basic_auth(request_rec *r, const char **user, + const char **pw) +{ + const char *auth_line; + char *decoded_line; + + /* Get the appropriate header */ + auth_line = apr_table_get(r->headers_in, (PROXYREQ_PROXY == r->proxyreq) + ? "Proxy-Authorization" + : "Authorization"); + + if (!auth_line) { + note_basic_auth_failure(r); + return HTTP_UNAUTHORIZED; + } + + if (ap_cstr_casecmp(ap_getword(r->pool, &auth_line, ' '), "Basic")) { + /* Client tried to authenticate using wrong auth scheme */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01614) + "client used wrong authentication scheme: %s", r->uri); + note_basic_auth_failure(r); + return HTTP_UNAUTHORIZED; + } + + /* Skip leading spaces. */ + while (*auth_line == ' ' || *auth_line == '\t') { + auth_line++; + } + + decoded_line = ap_pbase64decode(r->pool, auth_line); + + *user = ap_getword_nulls(r->pool, (const char**)&decoded_line, ':'); + *pw = decoded_line; + + /* set the user, even though the user is unauthenticated at this point */ + r->user = (char *) *user; + + return OK; +} + +/* Determine user ID, and check if it really is that user, for HTTP + * basic authentication... + */ +static int authenticate_basic_user(request_rec *r) +{ + auth_basic_config_rec *conf = ap_get_module_config(r->per_dir_config, + &auth_basic_module); + const char *sent_user, *sent_pw, *current_auth; + const char *realm = NULL; + const char *digest = NULL; + int res; + authn_status auth_result; + authn_provider_list *current_provider; + + /* Are we configured to be Basic auth? */ + current_auth = ap_auth_type(r); + if (!current_auth || ap_cstr_casecmp(current_auth, "Basic")) { + return DECLINED; + } + + /* We need an authentication realm. */ + if (!ap_auth_name(r)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01615) + "need AuthName: %s", r->uri); + return HTTP_INTERNAL_SERVER_ERROR; + } + + r->ap_auth_type = (char*)current_auth; + + res = get_basic_auth(r, &sent_user, &sent_pw); + if (res) { + return res; + } + + if (conf->use_digest_algorithm + && !ap_cstr_casecmp(conf->use_digest_algorithm, "MD5")) { + realm = ap_auth_name(r); + digest = ap_md5(r->pool, + (unsigned char *)apr_pstrcat(r->pool, sent_user, ":", + realm, ":", + sent_pw, NULL)); + } + + current_provider = conf->providers; + do { + const authn_provider *provider; + + /* For now, if a provider isn't set, we'll be nice and use the file + * provider. + */ + if (!current_provider) { + provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP, + AUTHN_DEFAULT_PROVIDER, + AUTHN_PROVIDER_VERSION); + + if (!provider || !provider->check_password) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01616) + "No Authn provider configured"); + auth_result = AUTH_GENERAL_ERROR; + break; + } + apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, AUTHN_DEFAULT_PROVIDER); + } + else { + provider = current_provider->provider; + apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, current_provider->provider_name); + } + + if (digest) { + char *password; + + if (!provider->get_realm_hash) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02493) + "Authn provider does not support " + "AuthBasicUseDigestAlgorithm"); + auth_result = AUTH_GENERAL_ERROR; + break; + } + /* We expect the password to be hash of user:realm:password */ + auth_result = provider->get_realm_hash(r, sent_user, realm, + &password); + if (auth_result == AUTH_USER_FOUND) { + auth_result = strcmp(digest, password) ? AUTH_DENIED + : AUTH_GRANTED; + } + } + else { + auth_result = provider->check_password(r, sent_user, sent_pw); + } + + apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE); + + /* Something occurred. Stop checking. */ + if (auth_result != AUTH_USER_NOT_FOUND) { + break; + } + + /* If we're not really configured for providers, stop now. */ + if (!conf->providers) { + break; + } + + current_provider = current_provider->next; + } while (current_provider); + + if (auth_result != AUTH_GRANTED) { + int return_code; + + /* If we're not authoritative, then any error is ignored. */ + if (!(conf->authoritative) && auth_result != AUTH_DENIED) { + return DECLINED; + } + + switch (auth_result) { + case AUTH_DENIED: + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01617) + "user %s: authentication failure for \"%s\": " + "Password Mismatch", + sent_user, r->uri); + return_code = HTTP_UNAUTHORIZED; + break; + case AUTH_USER_NOT_FOUND: + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01618) + "user %s not found: %s", sent_user, r->uri); + return_code = HTTP_UNAUTHORIZED; + break; + case AUTH_GENERAL_ERROR: + default: + /* We'll assume that the module has already said what its error + * was in the logs. + */ + return_code = HTTP_INTERNAL_SERVER_ERROR; + break; + } + + /* If we're returning 401, tell them to try again. */ + if (return_code == HTTP_UNAUTHORIZED) { + note_basic_auth_failure(r); + } + return return_code; + } + + return OK; +} + +/* If requested, create a fake basic authentication header for the benefit + * of a proxy or application running behind this server. + */ +static int authenticate_basic_fake(request_rec *r) +{ + const char *auth_line, *user, *pass, *err; + auth_basic_config_rec *conf = ap_get_module_config(r->per_dir_config, + &auth_basic_module); + + if (!conf->fakeuser) { + return DECLINED; + } + + user = ap_expr_str_exec(r, conf->fakeuser, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02455) + "AuthBasicFake: could not evaluate user expression for URI '%s': %s", r->uri, err); + return HTTP_INTERNAL_SERVER_ERROR; + } + if (!user || !*user) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02458) + "AuthBasicFake: empty username expression for URI '%s', ignoring", r->uri); + + apr_table_unset(r->headers_in, "Authorization"); + + return DECLINED; + } + + pass = ap_expr_str_exec(r, conf->fakepass, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02456) + "AuthBasicFake: could not evaluate password expression for URI '%s': %s", r->uri, err); + return HTTP_INTERNAL_SERVER_ERROR; + } + if (!pass || !*pass) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02459) + "AuthBasicFake: empty password expression for URI '%s', ignoring", r->uri); + + apr_table_unset(r->headers_in, "Authorization"); + + return DECLINED; + } + + auth_line = apr_pstrcat(r->pool, "Basic ", + ap_pbase64encode(r->pool, + apr_pstrcat(r->pool, user, + ":", pass, NULL)), + NULL); + apr_table_setn(r->headers_in, "Authorization", auth_line); + + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02457) + "AuthBasicFake: \"Authorization: %s\"", + auth_line); + + return OK; +} + +static void register_hooks(apr_pool_t *p) +{ + ap_hook_check_authn(authenticate_basic_user, NULL, NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); + ap_hook_fixups(authenticate_basic_fake, NULL, NULL, APR_HOOK_LAST); + ap_hook_note_auth_failure(hook_note_basic_auth_failure, NULL, NULL, + APR_HOOK_MIDDLE); +} + +AP_DECLARE_MODULE(auth_basic) = +{ + STANDARD20_MODULE_STUFF, + create_auth_basic_dir_config, /* dir config creater */ + merge_auth_basic_dir_config, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + auth_basic_cmds, /* command apr_table_t */ + register_hooks /* register hooks */ +}; diff --git a/modules/aaa/mod_auth_basic.dep b/modules/aaa/mod_auth_basic.dep new file mode 100644 index 0000000..6c1291c --- /dev/null +++ b/modules/aaa/mod_auth_basic.dep @@ -0,0 +1,63 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_auth_basic.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_auth_basic.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\include\util_md5.h"\ + "..\..\srclib\apr-util\include\apr_base64.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_md5.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apr_xlate.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_lib.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_auth_basic.dsp b/modules/aaa/mod_auth_basic.dsp new file mode 100644 index 0000000..b45264e --- /dev/null +++ b/modules/aaa/mod_auth_basic.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_auth_basic" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_auth_basic - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_auth_basic.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_auth_basic - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_auth_basic - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_auth_basic - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AAA_DECLARE_EXPORT" /Fd"Release\mod_auth_basic_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_auth_basic.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_auth_basic.so" /d LONG_NAME="auth_basic_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_auth_basic.so" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_basic.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_auth_basic.so" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_basic.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_auth_basic.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_auth_basic - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "AAA_DECLARE_EXPORT" /Fd"Debug\mod_auth_basic_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_auth_basic.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_auth_basic.so" /d LONG_NAME="auth_basic_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_auth_basic.so" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_basic.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_auth_basic.so" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_basic.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_auth_basic.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_auth_basic - Win32 Release" +# Name "mod_auth_basic - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_auth_basic.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_auth_basic.mak b/modules/aaa/mod_auth_basic.mak new file mode 100644 index 0000000..ddd5198 --- /dev/null +++ b/modules/aaa/mod_auth_basic.mak @@ -0,0 +1,353 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_auth_basic.dsp +!IF "$(CFG)" == "" +CFG=mod_auth_basic - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_auth_basic - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_auth_basic - Win32 Release" && "$(CFG)" != "mod_auth_basic - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_auth_basic - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_auth_basic - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_auth_basic - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_auth_basic.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_auth_basic.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_auth_basic.obj" + -@erase "$(INTDIR)\mod_auth_basic.res" + -@erase "$(INTDIR)\mod_auth_basic_src.idb" + -@erase "$(INTDIR)\mod_auth_basic_src.pdb" + -@erase "$(OUTDIR)\mod_auth_basic.exp" + -@erase "$(OUTDIR)\mod_auth_basic.lib" + -@erase "$(OUTDIR)\mod_auth_basic.pdb" + -@erase "$(OUTDIR)\mod_auth_basic.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AAA_DECLARE_EXPORT" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_basic_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_auth_basic.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_auth_basic.so" /d LONG_NAME="auth_basic_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_basic.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_auth_basic.pdb" /debug /out:"$(OUTDIR)\mod_auth_basic.so" /implib:"$(OUTDIR)\mod_auth_basic.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_basic.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_auth_basic.obj" \ + "$(INTDIR)\mod_auth_basic.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" + +"$(OUTDIR)\mod_auth_basic.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_auth_basic.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_auth_basic.so" + if exist .\Release\mod_auth_basic.so.manifest mt.exe -manifest .\Release\mod_auth_basic.so.manifest -outputresource:.\Release\mod_auth_basic.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_auth_basic - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_auth_basic.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_auth_basic.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_auth_basic.obj" + -@erase "$(INTDIR)\mod_auth_basic.res" + -@erase "$(INTDIR)\mod_auth_basic_src.idb" + -@erase "$(INTDIR)\mod_auth_basic_src.pdb" + -@erase "$(OUTDIR)\mod_auth_basic.exp" + -@erase "$(OUTDIR)\mod_auth_basic.lib" + -@erase "$(OUTDIR)\mod_auth_basic.pdb" + -@erase "$(OUTDIR)\mod_auth_basic.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "AAA_DECLARE_EXPORT" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_basic_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_auth_basic.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_auth_basic.so" /d LONG_NAME="auth_basic_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_basic.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_auth_basic.pdb" /debug /out:"$(OUTDIR)\mod_auth_basic.so" /implib:"$(OUTDIR)\mod_auth_basic.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_basic.so +LINK32_OBJS= \ + "$(INTDIR)\mod_auth_basic.obj" \ + "$(INTDIR)\mod_auth_basic.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" + +"$(OUTDIR)\mod_auth_basic.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_auth_basic.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_auth_basic.so" + if exist .\Debug\mod_auth_basic.so.manifest mt.exe -manifest .\Debug\mod_auth_basic.so.manifest -outputresource:.\Debug\mod_auth_basic.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_auth_basic.dep") +!INCLUDE "mod_auth_basic.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_auth_basic.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_auth_basic - Win32 Release" || "$(CFG)" == "mod_auth_basic - Win32 Debug" + +!IF "$(CFG)" == "mod_auth_basic - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_auth_basic - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_auth_basic - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_auth_basic - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_auth_basic - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_auth_basic - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_auth_basic - Win32 Release" + + +"$(INTDIR)\mod_auth_basic.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_auth_basic.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_auth_basic.so" /d LONG_NAME="auth_basic_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_auth_basic - Win32 Debug" + + +"$(INTDIR)\mod_auth_basic.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_auth_basic.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_auth_basic.so" /d LONG_NAME="auth_basic_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_auth_basic.c + +"$(INTDIR)\mod_auth_basic.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c new file mode 100644 index 0000000..791cec2 --- /dev/null +++ b/modules/aaa/mod_auth_digest.c @@ -0,0 +1,1983 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * mod_auth_digest: MD5 digest authentication + * + * Originally by Alexei Kosut <akosut@nueva.pvt.k12.ca.us> + * Updated to RFC-2617 by Ronald Tschal�r <ronald@innovation.ch> + * based on mod_auth, by Rob McCool and Robert S. Thau + * + * This module an updated version of modules/standard/mod_digest.c + * It is still fairly new and problems may turn up - submit problem + * reports to the Apache bug-database, or send them directly to me + * at ronald@innovation.ch. + * + * Open Issues: + * - qop=auth-int (when streams and trailer support available) + * - nonce-format configurability + * - Proxy-Authorization-Info header is set by this module, but is + * currently ignored by mod_proxy (needs patch to mod_proxy) + * - The source of the secret should be run-time directive (with server + * scope: RSRC_CONF) + * - shared-mem not completely tested yet. Seems to work ok for me, + * but... (definitely won't work on Windoze) + * - Sharing a realm among multiple servers has following problems: + * o Server name and port can't be included in nonce-hash + * (we need two nonce formats, which must be configured explicitly) + * o Nonce-count check can't be for equal, or then nonce-count checking + * must be disabled. What we could do is the following: + * (expected < received) ? set expected = received : issue error + * The only problem is that it allows replay attacks when somebody + * captures a packet sent to one server and sends it to another + * one. Should we add "AuthDigestNcCheck Strict"? + * - expired nonces give amaya fits. + * - MD5-sess and auth-int are not yet implemented. An incomplete + * implementation has been removed and can be retrieved from svn history. + */ + +#include "apr_sha1.h" +#include "apr_base64.h" +#include "apr_lib.h" +#include "apr_time.h" +#include "apr_errno.h" +#include "apr_global_mutex.h" +#include "apr_strings.h" + +#define APR_WANT_STRFUNC +#include "apr_want.h" + +#include "ap_config.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_request.h" +#include "http_log.h" +#include "http_protocol.h" +#include "apr_uri.h" +#include "util_md5.h" +#include "util_mutex.h" +#include "apr_shm.h" +#include "apr_rmm.h" +#include "ap_provider.h" + +#include "mod_auth.h" + +#if APR_HAVE_UNISTD_H +#include <unistd.h> +#endif + +/* struct to hold the configuration info */ + +typedef struct digest_config_struct { + const char *dir_name; + authn_provider_list *providers; + const char *realm; + apr_array_header_t *qop_list; + apr_sha1_ctx_t nonce_ctx; + apr_time_t nonce_lifetime; + int check_nc; + const char *algorithm; + char *uri_list; +} digest_config_rec; + + +#define DFLT_ALGORITHM "MD5" + +#define DFLT_NONCE_LIFE apr_time_from_sec(300) +#define NEXTNONCE_DELTA apr_time_from_sec(30) + + +#define NONCE_TIME_LEN (((sizeof(apr_time_t)+2)/3)*4) +#define NONCE_HASH_LEN (2*APR_SHA1_DIGESTSIZE) +#define NONCE_LEN (int )(NONCE_TIME_LEN + NONCE_HASH_LEN) + +#define SECRET_LEN 20 +#define RETAINED_DATA_ID "mod_auth_digest" + + +/* client list definitions */ + +typedef struct hash_entry { + unsigned long key; /* the key for this entry */ + struct hash_entry *next; /* next entry in the bucket */ + unsigned long nonce_count; /* for nonce-count checking */ + char last_nonce[NONCE_LEN+1]; /* for one-time nonce's */ +} client_entry; + +static struct hash_table { + client_entry **table; + unsigned long tbl_len; + unsigned long num_entries; + unsigned long num_created; + unsigned long num_removed; + unsigned long num_renewed; +} *client_list; + + +/* struct to hold a parsed Authorization header */ + +enum hdr_sts { NO_HEADER, NOT_DIGEST, INVALID, VALID }; + +typedef struct digest_header_struct { + const char *scheme; + const char *realm; + const char *username; + char *nonce; + const char *uri; + const char *method; + const char *digest; + const char *algorithm; + const char *cnonce; + const char *opaque; + unsigned long opaque_num; + const char *message_qop; + const char *nonce_count; + /* the following fields are not (directly) from the header */ + const char *raw_request_uri; + apr_uri_t *psd_request_uri; + apr_time_t nonce_time; + enum hdr_sts auth_hdr_sts; + int needed_auth; + const char *ha1; + client_entry *client; +} digest_header_rec; + + +/* (mostly) nonce stuff */ + +typedef union time_union { + apr_time_t time; + unsigned char arr[sizeof(apr_time_t)]; +} time_rec; + +static unsigned char *secret; + +/* client-list, opaque, and one-time-nonce stuff */ + +static apr_shm_t *client_shm = NULL; +static apr_rmm_t *client_rmm = NULL; +static unsigned long *opaque_cntr; +static apr_time_t *otn_counter; /* one-time-nonce counter */ +static apr_global_mutex_t *client_lock = NULL; +static apr_global_mutex_t *opaque_lock = NULL; +static const char *client_mutex_type = "authdigest-client"; +static const char *opaque_mutex_type = "authdigest-opaque"; +static const char *client_shm_filename; + +#define DEF_SHMEM_SIZE 1000L /* ~ 12 entries */ +#define DEF_NUM_BUCKETS 15L +#define HASH_DEPTH 5 + +static apr_size_t shmem_size = DEF_SHMEM_SIZE; +static unsigned long num_buckets = DEF_NUM_BUCKETS; + + +module AP_MODULE_DECLARE_DATA auth_digest_module; + +/* + * initialization code + */ + +static apr_status_t cleanup_tables(void *not_used) +{ + ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, APLOGNO(01756) + "cleaning up shared memory"); + + if (client_rmm) { + apr_rmm_destroy(client_rmm); + client_rmm = NULL; + } + + if (client_shm) { + apr_shm_destroy(client_shm); + client_shm = NULL; + } + + if (client_lock) { + apr_global_mutex_destroy(client_lock); + client_lock = NULL; + } + + if (opaque_lock) { + apr_global_mutex_destroy(opaque_lock); + opaque_lock = NULL; + } + + client_list = NULL; + + return APR_SUCCESS; +} + +static void log_error_and_cleanup(char *msg, apr_status_t sts, server_rec *s) +{ + ap_log_error(APLOG_MARK, APLOG_ERR, sts, s, APLOGNO(01760) + "%s - all nonce-count checking and one-time nonces " + "disabled", msg); + + cleanup_tables(NULL); +} + +/* RMM helper functions that behave like single-step malloc/free. */ + +static void *rmm_malloc(apr_rmm_t *rmm, apr_size_t size) +{ + apr_rmm_off_t offset = apr_rmm_malloc(rmm, size); + + if (!offset) { + return NULL; + } + + return apr_rmm_addr_get(rmm, offset); +} + +static apr_status_t rmm_free(apr_rmm_t *rmm, void *alloc) +{ + apr_rmm_off_t offset = apr_rmm_offset_get(rmm, alloc); + + return apr_rmm_free(rmm, offset); +} + +#if APR_HAS_SHARED_MEMORY + +static int initialize_tables(server_rec *s, apr_pool_t *ctx) +{ + unsigned long idx; + apr_status_t sts; + + /* set up client list */ + + /* Create the shared memory segment */ + + client_shm = NULL; + client_rmm = NULL; + client_lock = NULL; + opaque_lock = NULL; + client_list = NULL; + + /* + * Create a unique filename using our pid. This information is + * stashed in the global variable so the children inherit it. + */ + client_shm_filename = ap_runtime_dir_relative(ctx, "authdigest_shm"); + client_shm_filename = ap_append_pid(ctx, client_shm_filename, "."); + + /* Use anonymous shm by default, fall back on name-based. */ + sts = apr_shm_create(&client_shm, shmem_size, NULL, ctx); + if (APR_STATUS_IS_ENOTIMPL(sts)) { + /* For a name-based segment, remove it first in case of a + * previous unclean shutdown. */ + apr_shm_remove(client_shm_filename, ctx); + + /* Now create that segment */ + sts = apr_shm_create(&client_shm, shmem_size, + client_shm_filename, ctx); + } + + if (APR_SUCCESS != sts) { + ap_log_error(APLOG_MARK, APLOG_ERR, sts, s, APLOGNO(01762) + "Failed to create shared memory segment on file %s", + client_shm_filename); + log_error_and_cleanup("failed to initialize shm", sts, s); + return HTTP_INTERNAL_SERVER_ERROR; + } + + sts = apr_rmm_init(&client_rmm, + NULL, /* no lock, we'll do the locking ourselves */ + apr_shm_baseaddr_get(client_shm), + shmem_size, ctx); + if (sts != APR_SUCCESS) { + log_error_and_cleanup("failed to initialize rmm", sts, s); + return !OK; + } + + client_list = rmm_malloc(client_rmm, sizeof(*client_list) + + sizeof(client_entry *) * num_buckets); + if (!client_list) { + log_error_and_cleanup("failed to allocate shared memory", -1, s); + return !OK; + } + client_list->table = (client_entry**) (client_list + 1); + for (idx = 0; idx < num_buckets; idx++) { + client_list->table[idx] = NULL; + } + client_list->tbl_len = num_buckets; + client_list->num_entries = 0; + + sts = ap_global_mutex_create(&client_lock, NULL, client_mutex_type, NULL, + s, ctx, 0); + if (sts != APR_SUCCESS) { + log_error_and_cleanup("failed to create lock (client_lock)", sts, s); + return !OK; + } + + + /* setup opaque */ + + opaque_cntr = rmm_malloc(client_rmm, sizeof(*opaque_cntr)); + if (opaque_cntr == NULL) { + log_error_and_cleanup("failed to allocate shared memory", -1, s); + return !OK; + } + *opaque_cntr = 1UL; + + sts = ap_global_mutex_create(&opaque_lock, NULL, opaque_mutex_type, NULL, + s, ctx, 0); + if (sts != APR_SUCCESS) { + log_error_and_cleanup("failed to create lock (opaque_lock)", sts, s); + return !OK; + } + + + /* setup one-time-nonce counter */ + + otn_counter = rmm_malloc(client_rmm, sizeof(*otn_counter)); + if (otn_counter == NULL) { + log_error_and_cleanup("failed to allocate shared memory", -1, s); + return !OK; + } + *otn_counter = 0; + /* no lock here */ + + + /* success */ + return OK; +} + +#endif /* APR_HAS_SHARED_MEMORY */ + +static int pre_init(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp) +{ + apr_status_t rv; + void *retained; + + rv = ap_mutex_register(pconf, client_mutex_type, NULL, APR_LOCK_DEFAULT, 0); + if (rv != APR_SUCCESS) + return !OK; + rv = ap_mutex_register(pconf, opaque_mutex_type, NULL, APR_LOCK_DEFAULT, 0); + if (rv != APR_SUCCESS) + return !OK; + + retained = ap_retained_data_get(RETAINED_DATA_ID); + if (retained == NULL) { + retained = ap_retained_data_create(RETAINED_DATA_ID, SECRET_LEN); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, APLOGNO(01757) + "generating secret for digest authentication"); +#if APR_HAS_RANDOM + rv = apr_generate_random_bytes(retained, SECRET_LEN); +#else +#error APR random number support is missing +#endif + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(01758) + "error generating secret"); + return !OK; + } + } + secret = retained; + return OK; +} + +static int initialize_module(apr_pool_t *p, apr_pool_t *plog, + apr_pool_t *ptemp, server_rec *s) +{ + /* initialize_module() will be called twice, and if it's a DSO + * then all static data from the first call will be lost. Only + * set up our static data on the second call. */ + if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG) + return OK; + +#if APR_HAS_SHARED_MEMORY + /* Note: this stuff is currently fixed for the lifetime of the server, + * i.e. even across restarts. This means that A) any shmem-size + * configuration changes are ignored, and B) certain optimizations, + * such as only allocating the smallest necessary entry for each + * client, can't be done. However, the alternative is a nightmare: + * we can't call apr_shm_destroy on a graceful restart because there + * will be children using the tables, and we also don't know when the + * last child dies. Therefore we can never clean up the old stuff, + * creating a creeping memory leak. + */ + if (initialize_tables(s, p) != OK) { + return !OK; + } +#endif /* APR_HAS_SHARED_MEMORY */ + return OK; +} + +static void initialize_child(apr_pool_t *p, server_rec *s) +{ + apr_status_t sts; + + if (!client_shm) { + return; + } + + /* Get access to rmm in child */ + sts = apr_rmm_attach(&client_rmm, + NULL, + apr_shm_baseaddr_get(client_shm), + p); + if (sts != APR_SUCCESS) { + log_error_and_cleanup("failed to attach to rmm", sts, s); + return; + } + + sts = apr_global_mutex_child_init(&client_lock, + apr_global_mutex_lockfile(client_lock), + p); + if (sts != APR_SUCCESS) { + log_error_and_cleanup("failed to create lock (client_lock)", sts, s); + return; + } + sts = apr_global_mutex_child_init(&opaque_lock, + apr_global_mutex_lockfile(opaque_lock), + p); + if (sts != APR_SUCCESS) { + log_error_and_cleanup("failed to create lock (opaque_lock)", sts, s); + return; + } +} + +/* + * configuration code + */ + +static void *create_digest_dir_config(apr_pool_t *p, char *dir) +{ + digest_config_rec *conf; + + if (dir == NULL) { + return NULL; + } + + conf = (digest_config_rec *) apr_pcalloc(p, sizeof(digest_config_rec)); + if (conf) { + conf->qop_list = apr_array_make(p, 2, sizeof(char *)); + conf->nonce_lifetime = DFLT_NONCE_LIFE; + conf->dir_name = apr_pstrdup(p, dir); + conf->algorithm = DFLT_ALGORITHM; + } + + return conf; +} + +static const char *set_realm(cmd_parms *cmd, void *config, const char *realm) +{ + digest_config_rec *conf = (digest_config_rec *) config; +#ifdef AP_DEBUG + int i; + + /* check that we got random numbers */ + for (i = 0; i < SECRET_LEN; i++) { + if (secret[i] != 0) + break; + } + ap_assert(i < SECRET_LEN); +#endif + + /* The core already handles the realm, but it's just too convenient to + * grab it ourselves too and cache some setups. However, we need to + * let the core get at it too, which is why we decline at the end - + * this relies on the fact that http_core is last in the list. + */ + conf->realm = realm; + + /* we precompute the part of the nonce hash that is constant (well, + * the host:port would be too, but that varies for .htaccess files + * and directives outside a virtual host section) + */ + apr_sha1_init(&conf->nonce_ctx); + apr_sha1_update_binary(&conf->nonce_ctx, secret, SECRET_LEN); + apr_sha1_update_binary(&conf->nonce_ctx, (const unsigned char *) realm, + strlen(realm)); + + return DECLINE_CMD; +} + +static const char *add_authn_provider(cmd_parms *cmd, void *config, + const char *arg) +{ + digest_config_rec *conf = (digest_config_rec*)config; + authn_provider_list *newp; + + newp = apr_pcalloc(cmd->pool, sizeof(authn_provider_list)); + newp->provider_name = arg; + + /* lookup and cache the actual provider now */ + newp->provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP, + newp->provider_name, + AUTHN_PROVIDER_VERSION); + + if (newp->provider == NULL) { + /* by the time they use it, the provider should be loaded and + registered with us. */ + return apr_psprintf(cmd->pool, + "Unknown Authn provider: %s", + newp->provider_name); + } + + if (!newp->provider->get_realm_hash) { + /* if it doesn't provide the appropriate function, reject it */ + return apr_psprintf(cmd->pool, + "The '%s' Authn provider doesn't support " + "Digest Authentication", newp->provider_name); + } + + /* Add it to the list now. */ + if (!conf->providers) { + conf->providers = newp; + } + else { + authn_provider_list *last = conf->providers; + + while (last->next) { + last = last->next; + } + last->next = newp; + } + + return NULL; +} + +static const char *set_qop(cmd_parms *cmd, void *config, const char *op) +{ + digest_config_rec *conf = (digest_config_rec *) config; + + if (!ap_cstr_casecmp(op, "none")) { + apr_array_clear(conf->qop_list); + *(const char **)apr_array_push(conf->qop_list) = "none"; + return NULL; + } + + if (!ap_cstr_casecmp(op, "auth-int")) { + return "AuthDigestQop auth-int is not implemented"; + } + else if (ap_cstr_casecmp(op, "auth")) { + return apr_pstrcat(cmd->pool, "Unrecognized qop: ", op, NULL); + } + + *(const char **)apr_array_push(conf->qop_list) = op; + + return NULL; +} + +static const char *set_nonce_lifetime(cmd_parms *cmd, void *config, + const char *t) +{ + char *endptr; + long lifetime; + + lifetime = strtol(t, &endptr, 10); + if (endptr < (t+strlen(t)) && !apr_isspace(*endptr)) { + return apr_pstrcat(cmd->pool, + "Invalid time in AuthDigestNonceLifetime: ", + t, NULL); + } + + ((digest_config_rec *) config)->nonce_lifetime = apr_time_from_sec(lifetime); + return NULL; +} + +static const char *set_nonce_format(cmd_parms *cmd, void *config, + const char *fmt) +{ + return "AuthDigestNonceFormat is not implemented"; +} + +static const char *set_nc_check(cmd_parms *cmd, void *config, int flag) +{ +#if !APR_HAS_SHARED_MEMORY + if (flag) { + return "AuthDigestNcCheck: ERROR: nonce-count checking " + "is not supported on platforms without shared-memory " + "support"; + } +#endif + + ((digest_config_rec *) config)->check_nc = flag; + return NULL; +} + +static const char *set_algorithm(cmd_parms *cmd, void *config, const char *alg) +{ + if (!ap_cstr_casecmp(alg, "MD5-sess")) { + return "AuthDigestAlgorithm: ERROR: algorithm `MD5-sess' " + "is not implemented"; + } + else if (ap_cstr_casecmp(alg, "MD5")) { + return apr_pstrcat(cmd->pool, "Invalid algorithm in AuthDigestAlgorithm: ", alg, NULL); + } + + ((digest_config_rec *) config)->algorithm = alg; + return NULL; +} + +static const char *set_uri_list(cmd_parms *cmd, void *config, const char *uri) +{ + digest_config_rec *c = (digest_config_rec *) config; + if (c->uri_list) { + c->uri_list[strlen(c->uri_list)-1] = '\0'; + c->uri_list = apr_pstrcat(cmd->pool, c->uri_list, " ", uri, "\"", NULL); + } + else { + c->uri_list = apr_pstrcat(cmd->pool, ", domain=\"", uri, "\"", NULL); + } + return NULL; +} + +static const char *set_shmem_size(cmd_parms *cmd, void *config, + const char *size_str) +{ + char *endptr; + long size, min; + + size = strtol(size_str, &endptr, 10); + while (apr_isspace(*endptr)) endptr++; + if (*endptr == '\0' || *endptr == 'b' || *endptr == 'B') { + ; + } + else if (*endptr == 'k' || *endptr == 'K') { + size *= 1024; + } + else if (*endptr == 'm' || *endptr == 'M') { + size *= 1048576; + } + else { + return apr_pstrcat(cmd->pool, "Invalid size in AuthDigestShmemSize: ", + size_str, NULL); + } + + min = sizeof(*client_list) + sizeof(client_entry*) + sizeof(client_entry); + if (size < min) { + return apr_psprintf(cmd->pool, "size in AuthDigestShmemSize too small: " + "%ld < %ld", size, min); + } + + shmem_size = size; + num_buckets = (size - sizeof(*client_list)) / + (sizeof(client_entry*) + HASH_DEPTH * sizeof(client_entry)); + if (num_buckets == 0) { + num_buckets = 1; + } + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, APLOGNO(01763) + "Set shmem-size: %" APR_SIZE_T_FMT ", num-buckets: %ld", + shmem_size, num_buckets); + + return NULL; +} + +static const command_rec digest_cmds[] = +{ + AP_INIT_TAKE1("AuthName", set_realm, NULL, OR_AUTHCFG, + "The authentication realm (e.g. \"Members Only\")"), + AP_INIT_ITERATE("AuthDigestProvider", add_authn_provider, NULL, OR_AUTHCFG, + "specify the auth providers for a directory or location"), + AP_INIT_ITERATE("AuthDigestQop", set_qop, NULL, OR_AUTHCFG, + "A list of quality-of-protection options"), + AP_INIT_TAKE1("AuthDigestNonceLifetime", set_nonce_lifetime, NULL, OR_AUTHCFG, + "Maximum lifetime of the server nonce (seconds)"), + AP_INIT_TAKE1("AuthDigestNonceFormat", set_nonce_format, NULL, OR_AUTHCFG, + "The format to use when generating the server nonce"), + AP_INIT_FLAG("AuthDigestNcCheck", set_nc_check, NULL, OR_AUTHCFG, + "Whether or not to check the nonce-count sent by the client"), + AP_INIT_TAKE1("AuthDigestAlgorithm", set_algorithm, NULL, OR_AUTHCFG, + "The algorithm used for the hash calculation"), + AP_INIT_ITERATE("AuthDigestDomain", set_uri_list, NULL, OR_AUTHCFG, + "A list of URI's which belong to the same protection space as the current URI"), + AP_INIT_TAKE1("AuthDigestShmemSize", set_shmem_size, NULL, RSRC_CONF, + "The amount of shared memory to allocate for keeping track of clients"), + {NULL} +}; + + +/* + * client list code + * + * Each client is assigned a number, which is transferred in the opaque + * field of the WWW-Authenticate and Authorization headers. The number + * is just a simple counter which is incremented for each new client. + * Clients can't forge this number because it is hashed up into the + * server nonce, and that is checked. + * + * The clients are kept in a simple hash table, which consists of an + * array of client_entry's, each with a linked list of entries hanging + * off it. The client's number modulo the size of the array gives the + * bucket number. + * + * The clients are garbage collected whenever a new client is allocated + * but there is not enough space left in the shared memory segment. A + * simple semi-LRU is used for this: whenever a client entry is accessed + * it is moved to the beginning of the linked list in its bucket (this + * also makes for faster lookups for current clients). The garbage + * collecter then just removes the oldest entry (i.e. the one at the + * end of the list) in each bucket. + * + * The main advantages of the above scheme are that it's easy to implement + * and it keeps the hash table evenly balanced (i.e. same number of entries + * in each bucket). The major disadvantage is that you may be throwing + * entries out which are in active use. This is not tragic, as these + * clients will just be sent a new client id (opaque field) and nonce + * with a stale=true (i.e. it will just look like the nonce expired, + * thereby forcing an extra round trip). If the shared memory segment + * has enough headroom over the current client set size then this should + * not occur too often. + * + * To help tune the size of the shared memory segment (and see if the + * above algorithm is really sufficient) a set of counters is kept + * indicating the number of clients held, the number of garbage collected + * clients, and the number of erroneously purged clients. These are printed + * out at each garbage collection run. Note that access to the counters is + * not synchronized because they are just indicaters, and whether they are + * off by a few doesn't matter; and for the same reason no attempt is made + * to guarantee the num_renewed is correct in the face of clients spoofing + * the opaque field. + */ + +/* + * Get the client given its client number (the key). Returns the entry, + * or NULL if it's not found. + * + * Access to the list itself is synchronized via locks. However, access + * to the entry returned by get_client() is NOT synchronized. This means + * that there are potentially problems if a client uses multiple, + * simultaneous connections to access url's within the same protection + * space. However, these problems are not new: when using multiple + * connections you have no guarantee of the order the requests are + * processed anyway, so you have problems with the nonce-count and + * one-time nonces anyway. + */ +static client_entry *get_client(unsigned long key, const request_rec *r) +{ + int bucket; + client_entry *entry, *prev = NULL; + + + if (!key || !client_shm) return NULL; + + bucket = key % client_list->tbl_len; + entry = client_list->table[bucket]; + + apr_global_mutex_lock(client_lock); + + while (entry && key != entry->key) { + prev = entry; + entry = entry->next; + } + + if (entry && prev) { /* move entry to front of list */ + prev->next = entry->next; + entry->next = client_list->table[bucket]; + client_list->table[bucket] = entry; + } + + apr_global_mutex_unlock(client_lock); + + if (entry) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01764) + "get_client(): client %lu found", key); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01765) + "get_client(): client %lu not found", key); + } + + return entry; +} + + +/* A simple garbage-collecter to remove unused clients. It removes the + * last entry in each bucket and updates the counters. Returns the + * number of removed entries. + */ +static long gc(server_rec *s) +{ + client_entry *entry, *prev; + unsigned long num_removed = 0, idx; + + /* garbage collect all last entries */ + + for (idx = 0; idx < client_list->tbl_len; idx++) { + entry = client_list->table[idx]; + prev = NULL; + + if (!entry) { + /* This bucket is empty. */ + continue; + } + + while (entry->next) { /* find last entry */ + prev = entry; + entry = entry->next; + } + if (prev) { + prev->next = NULL; /* cut list */ + } + else { + client_list->table[idx] = NULL; + } + if (entry) { /* remove entry */ + apr_status_t err; + + err = rmm_free(client_rmm, entry); + num_removed++; + + if (err) { + /* Nothing we can really do but log... */ + ap_log_error(APLOG_MARK, APLOG_ERR, err, s, APLOGNO(10007) + "Failed to free auth_digest client allocation"); + } + } + } + + /* update counters and log */ + + client_list->num_entries -= num_removed; + client_list->num_removed += num_removed; + + return num_removed; +} + + +/* + * Add a new client to the list. Returns the entry if successful, NULL + * otherwise. This triggers the garbage collection if memory is low. + */ +static client_entry *add_client(unsigned long key, client_entry *info, + server_rec *s) +{ + int bucket; + client_entry *entry; + + + if (!key || !client_shm) { + return NULL; + } + + bucket = key % client_list->tbl_len; + + apr_global_mutex_lock(client_lock); + + /* try to allocate a new entry */ + + entry = rmm_malloc(client_rmm, sizeof(client_entry)); + if (!entry) { + long num_removed = gc(s); + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01766) + "gc'd %ld client entries. Total new clients: " + "%ld; Total removed clients: %ld; Total renewed clients: " + "%ld", num_removed, + client_list->num_created - client_list->num_renewed, + client_list->num_removed, client_list->num_renewed); + entry = rmm_malloc(client_rmm, sizeof(client_entry)); + if (!entry) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01767) + "unable to allocate new auth_digest client"); + apr_global_mutex_unlock(client_lock); + return NULL; /* give up */ + } + } + + /* now add the entry */ + + memcpy(entry, info, sizeof(client_entry)); + entry->key = key; + entry->next = client_list->table[bucket]; + client_list->table[bucket] = entry; + client_list->num_created++; + client_list->num_entries++; + + apr_global_mutex_unlock(client_lock); + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01768) + "allocated new client %lu", key); + + return entry; +} + + +/* + * Authorization header parser code + */ + +/* Parse the Authorization header, if it exists */ +static int get_digest_rec(request_rec *r, digest_header_rec *resp) +{ + const char *auth_line; + apr_size_t l; + int vk = 0, vv = 0; + char *key, *value; + + auth_line = apr_table_get(r->headers_in, + (PROXYREQ_PROXY == r->proxyreq) + ? "Proxy-Authorization" + : "Authorization"); + if (!auth_line) { + resp->auth_hdr_sts = NO_HEADER; + return !OK; + } + + resp->scheme = ap_getword_white(r->pool, &auth_line); + if (ap_cstr_casecmp(resp->scheme, "Digest")) { + resp->auth_hdr_sts = NOT_DIGEST; + return !OK; + } + + l = strlen(auth_line); + + key = apr_palloc(r->pool, l+1); + value = apr_palloc(r->pool, l+1); + + while (auth_line[0] != '\0') { + + /* find key */ + + while (apr_isspace(auth_line[0])) { + auth_line++; + } + vk = 0; + while (auth_line[0] != '=' && auth_line[0] != ',' + && auth_line[0] != '\0' && !apr_isspace(auth_line[0])) { + key[vk++] = *auth_line++; + } + key[vk] = '\0'; + while (apr_isspace(auth_line[0])) { + auth_line++; + } + + /* find value */ + + vv = 0; + if (auth_line[0] == '=') { + auth_line++; + while (apr_isspace(auth_line[0])) { + auth_line++; + } + + if (auth_line[0] == '\"') { /* quoted string */ + auth_line++; + while (auth_line[0] != '\"' && auth_line[0] != '\0') { + if (auth_line[0] == '\\' && auth_line[1] != '\0') { + auth_line++; /* escaped char */ + } + value[vv++] = *auth_line++; + } + if (auth_line[0] != '\0') { + auth_line++; + } + } + else { /* token */ + while (auth_line[0] != ',' && auth_line[0] != '\0' + && !apr_isspace(auth_line[0])) { + value[vv++] = *auth_line++; + } + } + } + value[vv] = '\0'; + + while (auth_line[0] != ',' && auth_line[0] != '\0') { + auth_line++; + } + if (auth_line[0] != '\0') { + auth_line++; + } + + if (!ap_cstr_casecmp(key, "username")) + resp->username = apr_pstrdup(r->pool, value); + else if (!ap_cstr_casecmp(key, "realm")) + resp->realm = apr_pstrdup(r->pool, value); + else if (!ap_cstr_casecmp(key, "nonce")) + resp->nonce = apr_pstrdup(r->pool, value); + else if (!ap_cstr_casecmp(key, "uri")) + resp->uri = apr_pstrdup(r->pool, value); + else if (!ap_cstr_casecmp(key, "response")) + resp->digest = apr_pstrdup(r->pool, value); + else if (!ap_cstr_casecmp(key, "algorithm")) + resp->algorithm = apr_pstrdup(r->pool, value); + else if (!ap_cstr_casecmp(key, "cnonce")) + resp->cnonce = apr_pstrdup(r->pool, value); + else if (!ap_cstr_casecmp(key, "opaque")) + resp->opaque = apr_pstrdup(r->pool, value); + else if (!ap_cstr_casecmp(key, "qop")) + resp->message_qop = apr_pstrdup(r->pool, value); + else if (!ap_cstr_casecmp(key, "nc")) + resp->nonce_count = apr_pstrdup(r->pool, value); + } + + if (!resp->username || !resp->realm || !resp->nonce || !resp->uri + || !resp->digest + || (resp->message_qop && (!resp->cnonce || !resp->nonce_count))) { + resp->auth_hdr_sts = INVALID; + return !OK; + } + + if (resp->opaque) { + resp->opaque_num = (unsigned long) strtol(resp->opaque, NULL, 16); + } + + resp->auth_hdr_sts = VALID; + return OK; +} + + +/* Because the browser may preemptively send auth info, incrementing the + * nonce-count when it does, and because the client does not get notified + * if the URI didn't need authentication after all, we need to be sure to + * update the nonce-count each time we receive an Authorization header no + * matter what the final outcome of the request. Furthermore this is a + * convenient place to get the request-uri (before any subrequests etc + * are initiated) and to initialize the request_config. + * + * Note that this must be called after mod_proxy had its go so that + * r->proxyreq is set correctly. + */ +static int parse_hdr_and_update_nc(request_rec *r) +{ + digest_header_rec *resp; + int res; + + if (!ap_is_initial_req(r)) { + return DECLINED; + } + + resp = apr_pcalloc(r->pool, sizeof(digest_header_rec)); + resp->raw_request_uri = r->unparsed_uri; + resp->psd_request_uri = &r->parsed_uri; + resp->needed_auth = 0; + resp->method = r->method; + ap_set_module_config(r->request_config, &auth_digest_module, resp); + + res = get_digest_rec(r, resp); + resp->client = get_client(resp->opaque_num, r); + if (res == OK && resp->client) { + resp->client->nonce_count++; + } + + return DECLINED; +} + + +/* + * Nonce generation code + */ + +/* The hash part of the nonce is a SHA-1 hash of the time, realm, server host + * and port, opaque, and our secret. + */ +static void gen_nonce_hash(char *hash, const char *timestr, const char *opaque, + const server_rec *server, + const digest_config_rec *conf) +{ + unsigned char sha1[APR_SHA1_DIGESTSIZE]; + apr_sha1_ctx_t ctx; + + memcpy(&ctx, &conf->nonce_ctx, sizeof(ctx)); + /* + apr_sha1_update_binary(&ctx, (const unsigned char *) server->server_hostname, + strlen(server->server_hostname)); + apr_sha1_update_binary(&ctx, (const unsigned char *) &server->port, + sizeof(server->port)); + */ + apr_sha1_update_binary(&ctx, (const unsigned char *) timestr, strlen(timestr)); + if (opaque) { + apr_sha1_update_binary(&ctx, (const unsigned char *) opaque, + strlen(opaque)); + } + apr_sha1_final(sha1, &ctx); + + ap_bin2hex(sha1, APR_SHA1_DIGESTSIZE, hash); +} + + +/* The nonce has the format b64(time)+hash . + */ +static const char *gen_nonce(apr_pool_t *p, apr_time_t now, const char *opaque, + const server_rec *server, + const digest_config_rec *conf) +{ + char *nonce = apr_palloc(p, NONCE_LEN+1); + time_rec t; + + if (conf->nonce_lifetime != 0) { + t.time = now; + } + else if (otn_counter) { + /* this counter is not synch'd, because it doesn't really matter + * if it counts exactly. + */ + t.time = (*otn_counter)++; + } + else { + /* XXX: WHAT IS THIS CONSTANT? */ + t.time = 42; + } + apr_base64_encode_binary(nonce, t.arr, sizeof(t.arr)); + gen_nonce_hash(nonce+NONCE_TIME_LEN, nonce, opaque, server, conf); + + return nonce; +} + + +/* + * Opaque and hash-table management + */ + +/* + * Generate a new client entry, add it to the list, and return the + * entry. Returns NULL if failed. + */ +static client_entry *gen_client(const request_rec *r) +{ + unsigned long op; + client_entry new_entry = { 0, NULL, 0, "" }, *entry; + + if (!opaque_cntr) { + return NULL; + } + + apr_global_mutex_lock(opaque_lock); + op = (*opaque_cntr)++; + apr_global_mutex_unlock(opaque_lock); + + if (!(entry = add_client(op, &new_entry, r->server))) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01769) + "failed to allocate client entry - ignoring client"); + return NULL; + } + + return entry; +} + + +/* + * Authorization challenge generation code (for WWW-Authenticate) + */ + +static const char *ltox(apr_pool_t *p, unsigned long num) +{ + if (num != 0) { + return apr_psprintf(p, "%lx", num); + } + else { + return ""; + } +} + +static void note_digest_auth_failure(request_rec *r, + const digest_config_rec *conf, + digest_header_rec *resp, int stale) +{ + const char *qop, *opaque, *opaque_param, *domain, *nonce; + + /* Setup qop */ + if (apr_is_empty_array(conf->qop_list)) { + qop = ", qop=\"auth\""; + } + else if (!ap_cstr_casecmp(*(const char **)(conf->qop_list->elts), "none")) { + qop = ""; + } + else { + qop = apr_pstrcat(r->pool, ", qop=\"", + apr_array_pstrcat(r->pool, conf->qop_list, ','), + "\"", + NULL); + } + + /* Setup opaque */ + + if (resp->opaque == NULL) { + /* new client */ + if ((conf->check_nc || conf->nonce_lifetime == 0) + && (resp->client = gen_client(r)) != NULL) { + opaque = ltox(r->pool, resp->client->key); + } + else { + opaque = ""; /* opaque not needed */ + } + } + else if (resp->client == NULL) { + /* client info was gc'd */ + resp->client = gen_client(r); + if (resp->client != NULL) { + opaque = ltox(r->pool, resp->client->key); + stale = 1; + client_list->num_renewed++; + } + else { + opaque = ""; /* ??? */ + } + } + else { + opaque = resp->opaque; + /* we're generating a new nonce, so reset the nonce-count */ + resp->client->nonce_count = 0; + } + + if (opaque[0]) { + opaque_param = apr_pstrcat(r->pool, ", opaque=\"", opaque, "\"", NULL); + } + else { + opaque_param = NULL; + } + + /* Setup nonce */ + + nonce = gen_nonce(r->pool, r->request_time, opaque, r->server, conf); + if (resp->client && conf->nonce_lifetime == 0) { + memcpy(resp->client->last_nonce, nonce, NONCE_LEN+1); + } + + /* setup domain attribute. We want to send this attribute wherever + * possible so that the client won't send the Authorization header + * unnecessarily (it's usually > 200 bytes!). + */ + + + /* don't send domain + * - for proxy requests + * - if it's not specified + */ + if (r->proxyreq || !conf->uri_list) { + domain = NULL; + } + else { + domain = conf->uri_list; + } + + apr_table_mergen(r->err_headers_out, + (PROXYREQ_PROXY == r->proxyreq) + ? "Proxy-Authenticate" : "WWW-Authenticate", + apr_psprintf(r->pool, "Digest realm=\"%s\", " + "nonce=\"%s\", algorithm=%s%s%s%s%s", + ap_auth_name(r), nonce, conf->algorithm, + opaque_param ? opaque_param : "", + domain ? domain : "", + stale ? ", stale=true" : "", qop)); + +} + +static int hook_note_digest_auth_failure(request_rec *r, const char *auth_type) +{ + request_rec *mainreq; + digest_header_rec *resp; + digest_config_rec *conf; + + if (ap_cstr_casecmp(auth_type, "Digest")) + return DECLINED; + + /* get the client response and mark */ + + mainreq = r; + while (mainreq->main != NULL) { + mainreq = mainreq->main; + } + while (mainreq->prev != NULL) { + mainreq = mainreq->prev; + } + resp = (digest_header_rec *) ap_get_module_config(mainreq->request_config, + &auth_digest_module); + resp->needed_auth = 1; + + + /* get our conf */ + + conf = (digest_config_rec *) ap_get_module_config(r->per_dir_config, + &auth_digest_module); + + note_digest_auth_failure(r, conf, resp, 0); + + return OK; +} + + +/* + * Authorization header verification code + */ + +static authn_status get_hash(request_rec *r, const char *user, + digest_config_rec *conf, const char **rethash) +{ + authn_status auth_result; + char *password; + authn_provider_list *current_provider; + + current_provider = conf->providers; + do { + const authn_provider *provider; + + /* For now, if a provider isn't set, we'll be nice and use the file + * provider. + */ + if (!current_provider) { + provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP, + AUTHN_DEFAULT_PROVIDER, + AUTHN_PROVIDER_VERSION); + + if (!provider || !provider->get_realm_hash) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01770) + "No Authn provider configured"); + auth_result = AUTH_GENERAL_ERROR; + break; + } + apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, AUTHN_DEFAULT_PROVIDER); + } + else { + provider = current_provider->provider; + apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, current_provider->provider_name); + } + + + /* We expect the password to be md5 hash of user:realm:password */ + auth_result = provider->get_realm_hash(r, user, conf->realm, + &password); + + apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE); + + /* Something occurred. Stop checking. */ + if (auth_result != AUTH_USER_NOT_FOUND) { + break; + } + + /* If we're not really configured for providers, stop now. */ + if (!conf->providers) { + break; + } + + current_provider = current_provider->next; + } while (current_provider); + + if (auth_result == AUTH_USER_FOUND) { + *rethash = password; + } + + return auth_result; +} + +static int check_nc(const request_rec *r, const digest_header_rec *resp, + const digest_config_rec *conf) +{ + unsigned long nc; + const char *snc = resp->nonce_count; + char *endptr; + + if (conf->check_nc && !client_shm) { + /* Shouldn't happen, but just in case... */ + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01771) + "cannot check nonce count without shared memory"); + return OK; + } + + if (!conf->check_nc || !client_shm) { + return OK; + } + + if (!apr_is_empty_array(conf->qop_list) && + !ap_cstr_casecmp(*(const char **)(conf->qop_list->elts), "none")) { + /* qop is none, client must not send a nonce count */ + if (snc != NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01772) + "invalid nc %s received - no nonce count allowed when qop=none", + snc); + return !OK; + } + /* qop is none, cannot check nonce count */ + return OK; + } + + nc = strtol(snc, &endptr, 16); + if (endptr < (snc+strlen(snc)) && !apr_isspace(*endptr)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01773) + "invalid nc %s received - not a number", snc); + return !OK; + } + + if (!resp->client) { + return !OK; + } + + if (nc != resp->client->nonce_count) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01774) + "Warning, possible replay attack: nonce-count " + "check failed: %lu != %lu", nc, + resp->client->nonce_count); + return !OK; + } + + return OK; +} + +static int check_nonce(request_rec *r, digest_header_rec *resp, + const digest_config_rec *conf) +{ + apr_time_t dt; + time_rec nonce_time; + char tmp, hash[NONCE_HASH_LEN+1]; + + /* Since the time part of the nonce is a base64 encoding of an + * apr_time_t (8 bytes), it should end with a '=', fail early otherwise. + */ + if (strlen(resp->nonce) != NONCE_LEN + || resp->nonce[NONCE_TIME_LEN - 1] != '=') { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01775) + "invalid nonce '%s' received - length is not %d " + "or time encoding is incorrect", + resp->nonce, NONCE_LEN); + note_digest_auth_failure(r, conf, resp, 1); + return HTTP_UNAUTHORIZED; + } + + tmp = resp->nonce[NONCE_TIME_LEN]; + resp->nonce[NONCE_TIME_LEN] = '\0'; + apr_base64_decode_binary(nonce_time.arr, resp->nonce); + gen_nonce_hash(hash, resp->nonce, resp->opaque, r->server, conf); + resp->nonce[NONCE_TIME_LEN] = tmp; + resp->nonce_time = nonce_time.time; + + if (strcmp(hash, resp->nonce+NONCE_TIME_LEN)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01776) + "invalid nonce %s received - hash is not %s", + resp->nonce, hash); + note_digest_auth_failure(r, conf, resp, 1); + return HTTP_UNAUTHORIZED; + } + + dt = r->request_time - nonce_time.time; + if (conf->nonce_lifetime > 0 && dt < 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01777) + "invalid nonce %s received - user attempted " + "time travel", resp->nonce); + note_digest_auth_failure(r, conf, resp, 1); + return HTTP_UNAUTHORIZED; + } + + if (conf->nonce_lifetime > 0) { + if (dt > conf->nonce_lifetime) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0,r, APLOGNO(01778) + "user %s: nonce expired (%.2f seconds old " + "- max lifetime %.2f) - sending new nonce", + r->user, (double)apr_time_sec(dt), + (double)apr_time_sec(conf->nonce_lifetime)); + note_digest_auth_failure(r, conf, resp, 1); + return HTTP_UNAUTHORIZED; + } + } + else if (conf->nonce_lifetime == 0 && resp->client) { + if (memcmp(resp->client->last_nonce, resp->nonce, NONCE_LEN)) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01779) + "user %s: one-time-nonce mismatch - sending " + "new nonce", r->user); + note_digest_auth_failure(r, conf, resp, 1); + return HTTP_UNAUTHORIZED; + } + } + /* else (lifetime < 0) => never expires */ + + return OK; +} + +/* The actual MD5 code... whee */ + +/* RFC-2069 */ +static const char *old_digest(const request_rec *r, + const digest_header_rec *resp) +{ + const char *ha2; + + ha2 = ap_md5(r->pool, (unsigned char *)apr_pstrcat(r->pool, resp->method, ":", + resp->uri, NULL)); + return ap_md5(r->pool, + (unsigned char *)apr_pstrcat(r->pool, resp->ha1, ":", + resp->nonce, ":", ha2, NULL)); +} + +/* RFC-2617 */ +static const char *new_digest(const request_rec *r, + digest_header_rec *resp) +{ + const char *ha1, *ha2, *a2; + + ha1 = resp->ha1; + + a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, NULL); + ha2 = ap_md5(r->pool, (const unsigned char *)a2); + + return ap_md5(r->pool, + (unsigned char *)apr_pstrcat(r->pool, ha1, ":", resp->nonce, + ":", resp->nonce_count, ":", + resp->cnonce, ":", + resp->message_qop, ":", ha2, + NULL)); +} + +static void copy_uri_components(apr_uri_t *dst, + apr_uri_t *src, request_rec *r) { + if (src->scheme && src->scheme[0] != '\0') { + dst->scheme = src->scheme; + } + else { + dst->scheme = (char *) "http"; + } + + if (src->hostname && src->hostname[0] != '\0') { + dst->hostname = apr_pstrdup(r->pool, src->hostname); + ap_unescape_url(dst->hostname); + } + else { + dst->hostname = (char *) ap_get_server_name(r); + } + + if (src->port_str && src->port_str[0] != '\0') { + dst->port = src->port; + } + else { + dst->port = ap_get_server_port(r); + } + + if (src->path && src->path[0] != '\0') { + dst->path = apr_pstrdup(r->pool, src->path); + ap_unescape_url(dst->path); + } + else { + dst->path = src->path; + } + + if (src->query && src->query[0] != '\0') { + dst->query = apr_pstrdup(r->pool, src->query); + ap_unescape_url(dst->query); + } + else { + dst->query = src->query; + } + + dst->hostinfo = src->hostinfo; +} + +/* These functions return 0 if client is OK, and proper error status + * if not... either HTTP_UNAUTHORIZED, if we made a check, and it failed, or + * HTTP_INTERNAL_SERVER_ERROR, if things are so totally confused that we + * couldn't figure out how to tell if the client is authorized or not. + * + * If they return DECLINED, and all other modules also decline, that's + * treated by the server core as a configuration error, logged and + * reported as such. + */ + +/* Determine user ID, and check if the attributes are correct, if it + * really is that user, if the nonce is correct, etc. + */ + +static int authenticate_digest_user(request_rec *r) +{ + digest_config_rec *conf; + digest_header_rec *resp; + request_rec *mainreq; + const char *t; + int res; + authn_status return_code; + + /* do we require Digest auth for this URI? */ + + if (!(t = ap_auth_type(r)) || ap_cstr_casecmp(t, "Digest")) { + return DECLINED; + } + + if (!ap_auth_name(r)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01780) + "need AuthName: %s", r->uri); + return HTTP_INTERNAL_SERVER_ERROR; + } + + + /* get the client response and mark */ + + mainreq = r; + while (mainreq->main != NULL) { + mainreq = mainreq->main; + } + while (mainreq->prev != NULL) { + mainreq = mainreq->prev; + } + resp = (digest_header_rec *) ap_get_module_config(mainreq->request_config, + &auth_digest_module); + resp->needed_auth = 1; + + + /* get our conf */ + + conf = (digest_config_rec *) ap_get_module_config(r->per_dir_config, + &auth_digest_module); + + + /* check for existence and syntax of Auth header */ + + if (resp->auth_hdr_sts != VALID) { + if (resp->auth_hdr_sts == NOT_DIGEST) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01781) + "client used wrong authentication scheme `%s': %s", + resp->scheme, r->uri); + } + else if (resp->auth_hdr_sts == INVALID) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01782) + "missing user, realm, nonce, uri, digest, " + "cnonce, or nonce_count in authorization header: %s", + r->uri); + } + /* else (resp->auth_hdr_sts == NO_HEADER) */ + note_digest_auth_failure(r, conf, resp, 0); + return HTTP_UNAUTHORIZED; + } + + r->user = (char *) resp->username; + r->ap_auth_type = (char *) "Digest"; + + /* check the auth attributes */ + + if (strcmp(resp->uri, resp->raw_request_uri)) { + /* Hmm, the simple match didn't work (probably a proxy modified the + * request-uri), so lets do a more sophisticated match + */ + apr_uri_t r_uri, d_uri; + + copy_uri_components(&r_uri, resp->psd_request_uri, r); + if (apr_uri_parse(r->pool, resp->uri, &d_uri) != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01783) + "invalid uri <%s> in Authorization header", + resp->uri); + return HTTP_BAD_REQUEST; + } + + if (d_uri.hostname) { + ap_unescape_url(d_uri.hostname); + } + if (d_uri.path) { + ap_unescape_url(d_uri.path); + } + + if (d_uri.query) { + ap_unescape_url(d_uri.query); + } + else if (r_uri.query) { + /* MSIE compatibility hack. MSIE has some RFC issues - doesn't + * include the query string in the uri Authorization component + * or when computing the response component. the second part + * works out ok, since we can hash the header and get the same + * result. however, the uri from the request line won't match + * the uri Authorization component since the header lacks the + * query string, leaving us incompatible with a (broken) MSIE. + * + * the workaround is to fake a query string match if in the proper + * environment - BrowserMatch MSIE, for example. the cool thing + * is that if MSIE ever fixes itself the simple match ought to + * work and this code won't be reached anyway, even if the + * environment is set. + */ + + if (apr_table_get(r->subprocess_env, + "AuthDigestEnableQueryStringHack")) { + + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01784) + "applying AuthDigestEnableQueryStringHack " + "to uri <%s>", resp->raw_request_uri); + + d_uri.query = r_uri.query; + } + } + + if (r->method_number == M_CONNECT) { + if (!r_uri.hostinfo || strcmp(resp->uri, r_uri.hostinfo)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01785) + "uri mismatch - <%s> does not match " + "request-uri <%s>", resp->uri, r_uri.hostinfo); + return HTTP_BAD_REQUEST; + } + } + else if ( + /* check hostname matches, if present */ + (d_uri.hostname && d_uri.hostname[0] != '\0' + && strcasecmp(d_uri.hostname, r_uri.hostname)) + /* check port matches, if present */ + || (d_uri.port_str && d_uri.port != r_uri.port) + /* check that server-port is default port if no port present */ + || (d_uri.hostname && d_uri.hostname[0] != '\0' + && !d_uri.port_str && r_uri.port != ap_default_port(r)) + /* check that path matches */ + || (d_uri.path != r_uri.path + /* either exact match */ + && (!d_uri.path || !r_uri.path + || strcmp(d_uri.path, r_uri.path)) + /* or '*' matches empty path in scheme://host */ + && !(d_uri.path && !r_uri.path && resp->psd_request_uri->hostname + && d_uri.path[0] == '*' && d_uri.path[1] == '\0')) + /* check that query matches */ + || (d_uri.query != r_uri.query + && (!d_uri.query || !r_uri.query + || strcmp(d_uri.query, r_uri.query))) + ) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01786) + "uri mismatch - <%s> does not match " + "request-uri <%s>", resp->uri, resp->raw_request_uri); + return HTTP_BAD_REQUEST; + } + } + + if (resp->opaque && resp->opaque_num == 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01787) + "received invalid opaque - got `%s'", + resp->opaque); + note_digest_auth_failure(r, conf, resp, 0); + return HTTP_UNAUTHORIZED; + } + + if (!conf->realm) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02533) + "realm mismatch - got `%s' but no realm specified", + resp->realm); + note_digest_auth_failure(r, conf, resp, 0); + return HTTP_UNAUTHORIZED; + } + + if (!resp->realm || strcmp(resp->realm, conf->realm)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01788) + "realm mismatch - got `%s' but expected `%s'", + resp->realm, conf->realm); + note_digest_auth_failure(r, conf, resp, 0); + return HTTP_UNAUTHORIZED; + } + + if (resp->algorithm != NULL + && ap_cstr_casecmp(resp->algorithm, "MD5")) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01789) + "unknown algorithm `%s' received: %s", + resp->algorithm, r->uri); + note_digest_auth_failure(r, conf, resp, 0); + return HTTP_UNAUTHORIZED; + } + + return_code = get_hash(r, r->user, conf, &resp->ha1); + + if (return_code == AUTH_USER_NOT_FOUND) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01790) + "user `%s' in realm `%s' not found: %s", + r->user, conf->realm, r->uri); + note_digest_auth_failure(r, conf, resp, 0); + return HTTP_UNAUTHORIZED; + } + else if (return_code == AUTH_USER_FOUND) { + /* we have a password, so continue */ + } + else if (return_code == AUTH_DENIED) { + /* authentication denied in the provider before attempting a match */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01791) + "user `%s' in realm `%s' denied by provider: %s", + r->user, conf->realm, r->uri); + note_digest_auth_failure(r, conf, resp, 0); + return HTTP_UNAUTHORIZED; + } + else { + /* AUTH_GENERAL_ERROR (or worse) + * We'll assume that the module has already said what its error + * was in the logs. + */ + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (resp->message_qop == NULL) { + /* old (rfc-2069) style digest */ + if (strcmp(resp->digest, old_digest(r, resp))) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01792) + "user %s: password mismatch: %s", r->user, + r->uri); + note_digest_auth_failure(r, conf, resp, 0); + return HTTP_UNAUTHORIZED; + } + } + else { + const char *exp_digest; + int match = 0, idx; + const char **tmp = (const char **)(conf->qop_list->elts); + for (idx = 0; idx < conf->qop_list->nelts; idx++) { + if (!ap_cstr_casecmp(*tmp, resp->message_qop)) { + match = 1; + break; + } + ++tmp; + } + + if (!match + && !(apr_is_empty_array(conf->qop_list) + && !ap_cstr_casecmp(resp->message_qop, "auth"))) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01793) + "invalid qop `%s' received: %s", + resp->message_qop, r->uri); + note_digest_auth_failure(r, conf, resp, 0); + return HTTP_UNAUTHORIZED; + } + + exp_digest = new_digest(r, resp); + if (!exp_digest) { + /* we failed to allocate a client struct */ + return HTTP_INTERNAL_SERVER_ERROR; + } + if (strcmp(resp->digest, exp_digest)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01794) + "user %s: password mismatch: %s", r->user, + r->uri); + note_digest_auth_failure(r, conf, resp, 0); + return HTTP_UNAUTHORIZED; + } + } + + if (check_nc(r, resp, conf) != OK) { + note_digest_auth_failure(r, conf, resp, 0); + return HTTP_UNAUTHORIZED; + } + + /* Note: this check is done last so that a "stale=true" can be + generated if the nonce is old */ + if ((res = check_nonce(r, resp, conf))) { + return res; + } + + return OK; +} + +/* + * Authorization-Info header code + */ + +static int add_auth_info(request_rec *r) +{ + const digest_config_rec *conf = + (digest_config_rec *) ap_get_module_config(r->per_dir_config, + &auth_digest_module); + digest_header_rec *resp = + (digest_header_rec *) ap_get_module_config(r->request_config, + &auth_digest_module); + const char *ai = NULL, *nextnonce = ""; + + if (resp == NULL || !resp->needed_auth || conf == NULL) { + return OK; + } + + /* 2069-style entity-digest is not supported (it's too hard, and + * there are no clients which support 2069 but not 2617). */ + + /* setup nextnonce + */ + if (conf->nonce_lifetime > 0) { + /* send nextnonce if current nonce will expire in less than 30 secs */ + if ((r->request_time - resp->nonce_time) > (conf->nonce_lifetime-NEXTNONCE_DELTA)) { + nextnonce = apr_pstrcat(r->pool, ", nextnonce=\"", + gen_nonce(r->pool, r->request_time, + resp->opaque, r->server, conf), + "\"", NULL); + if (resp->client) + resp->client->nonce_count = 0; + } + } + else if (conf->nonce_lifetime == 0 && resp->client) { + const char *nonce = gen_nonce(r->pool, 0, resp->opaque, r->server, + conf); + nextnonce = apr_pstrcat(r->pool, ", nextnonce=\"", nonce, "\"", NULL); + memcpy(resp->client->last_nonce, nonce, NONCE_LEN+1); + } + /* else nonce never expires, hence no nextnonce */ + + + /* do rfc-2069 digest + */ + if (!apr_is_empty_array(conf->qop_list) && + !ap_cstr_casecmp(*(const char **)(conf->qop_list->elts), "none") + && resp->message_qop == NULL) { + /* use only RFC-2069 format */ + ai = nextnonce; + } + else { + const char *resp_dig, *ha1, *a2, *ha2; + + /* calculate rspauth attribute + */ + ha1 = resp->ha1; + + a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL); + ha2 = ap_md5(r->pool, (const unsigned char *)a2); + + resp_dig = ap_md5(r->pool, + (unsigned char *)apr_pstrcat(r->pool, ha1, ":", + resp->nonce, ":", + resp->nonce_count, ":", + resp->cnonce, ":", + resp->message_qop ? + resp->message_qop : "", + ":", ha2, NULL)); + + /* assemble Authentication-Info header + */ + ai = apr_pstrcat(r->pool, + "rspauth=\"", resp_dig, "\"", + nextnonce, + resp->cnonce ? ", cnonce=\"" : "", + resp->cnonce + ? ap_escape_quotes(r->pool, resp->cnonce) + : "", + resp->cnonce ? "\"" : "", + resp->nonce_count ? ", nc=" : "", + resp->nonce_count ? resp->nonce_count : "", + resp->message_qop ? ", qop=" : "", + resp->message_qop ? resp->message_qop : "", + NULL); + } + + if (ai && ai[0]) { + apr_table_mergen(r->headers_out, + (PROXYREQ_PROXY == r->proxyreq) + ? "Proxy-Authentication-Info" + : "Authentication-Info", + ai); + } + + return OK; +} + +static void register_hooks(apr_pool_t *p) +{ + static const char * const cfgPost[]={ "http_core.c", NULL }; + static const char * const parsePre[]={ "mod_proxy.c", NULL }; + + ap_hook_pre_config(pre_init, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_post_config(initialize_module, NULL, cfgPost, APR_HOOK_MIDDLE); + ap_hook_child_init(initialize_child, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_post_read_request(parse_hdr_and_update_nc, parsePre, NULL, APR_HOOK_MIDDLE); + ap_hook_check_authn(authenticate_digest_user, NULL, NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); + + ap_hook_fixups(add_auth_info, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_note_auth_failure(hook_note_digest_auth_failure, NULL, NULL, + APR_HOOK_MIDDLE); + +} + +AP_DECLARE_MODULE(auth_digest) = +{ + STANDARD20_MODULE_STUFF, + create_digest_dir_config, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + digest_cmds, /* command table */ + register_hooks /* register hooks */ +}; + diff --git a/modules/aaa/mod_auth_digest.dep b/modules/aaa/mod_auth_digest.dep new file mode 100644 index 0000000..81451de --- /dev/null +++ b/modules/aaa/mod_auth_digest.dep @@ -0,0 +1,68 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_auth_digest.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_auth_digest.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\include\util_md5.h"\ + "..\..\include\util_mutex.h"\ + "..\..\srclib\apr-util\include\apr_anylock.h"\ + "..\..\srclib\apr-util\include\apr_base64.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_md5.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_rmm.h"\ + "..\..\srclib\apr-util\include\apr_sha1.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apr_xlate.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_lib.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_thread_rwlock.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_auth_digest.dsp b/modules/aaa/mod_auth_digest.dsp new file mode 100644 index 0000000..9d1bee1 --- /dev/null +++ b/modules/aaa/mod_auth_digest.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_auth_digest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_auth_digest - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_auth_digest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_auth_digest.mak" CFG="mod_auth_digest - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_auth_digest - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_auth_digest - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_auth_digest - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_auth_digest_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_auth_digest.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_auth_digest.so" /d LONG_NAME="auth_digest_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_auth_digest.so" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_digest.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_auth_digest.so" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_digest.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_auth_digest.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_auth_digest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_auth_digest_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_auth_digest.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_auth_digest.so" /d LONG_NAME="auth_digest_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_auth_digest.so" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_digest.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_auth_digest.so" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_digest.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_auth_digest.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_auth_digest - Win32 Release" +# Name "mod_auth_digest - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_auth_digest.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_auth_digest.mak b/modules/aaa/mod_auth_digest.mak new file mode 100644 index 0000000..4b54375 --- /dev/null +++ b/modules/aaa/mod_auth_digest.mak @@ -0,0 +1,353 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_auth_digest.dsp +!IF "$(CFG)" == "" +CFG=mod_auth_digest - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_auth_digest - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_auth_digest - Win32 Release" && "$(CFG)" != "mod_auth_digest - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_auth_digest.mak" CFG="mod_auth_digest - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_auth_digest - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_auth_digest - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_auth_digest - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_auth_digest.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_auth_digest.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_auth_digest.obj" + -@erase "$(INTDIR)\mod_auth_digest.res" + -@erase "$(INTDIR)\mod_auth_digest_src.idb" + -@erase "$(INTDIR)\mod_auth_digest_src.pdb" + -@erase "$(OUTDIR)\mod_auth_digest.exp" + -@erase "$(OUTDIR)\mod_auth_digest.lib" + -@erase "$(OUTDIR)\mod_auth_digest.pdb" + -@erase "$(OUTDIR)\mod_auth_digest.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_digest_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_auth_digest.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_auth_digest.so" /d LONG_NAME="auth_digest_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_digest.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_auth_digest.pdb" /debug /out:"$(OUTDIR)\mod_auth_digest.so" /implib:"$(OUTDIR)\mod_auth_digest.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_digest.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_auth_digest.obj" \ + "$(INTDIR)\mod_auth_digest.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" + +"$(OUTDIR)\mod_auth_digest.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_auth_digest.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_auth_digest.so" + if exist .\Release\mod_auth_digest.so.manifest mt.exe -manifest .\Release\mod_auth_digest.so.manifest -outputresource:.\Release\mod_auth_digest.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_auth_digest - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_auth_digest.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_auth_digest.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_auth_digest.obj" + -@erase "$(INTDIR)\mod_auth_digest.res" + -@erase "$(INTDIR)\mod_auth_digest_src.idb" + -@erase "$(INTDIR)\mod_auth_digest_src.pdb" + -@erase "$(OUTDIR)\mod_auth_digest.exp" + -@erase "$(OUTDIR)\mod_auth_digest.lib" + -@erase "$(OUTDIR)\mod_auth_digest.pdb" + -@erase "$(OUTDIR)\mod_auth_digest.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_digest_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_auth_digest.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_auth_digest.so" /d LONG_NAME="auth_digest_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_digest.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_auth_digest.pdb" /debug /out:"$(OUTDIR)\mod_auth_digest.so" /implib:"$(OUTDIR)\mod_auth_digest.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_digest.so +LINK32_OBJS= \ + "$(INTDIR)\mod_auth_digest.obj" \ + "$(INTDIR)\mod_auth_digest.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" + +"$(OUTDIR)\mod_auth_digest.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_auth_digest.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_auth_digest.so" + if exist .\Debug\mod_auth_digest.so.manifest mt.exe -manifest .\Debug\mod_auth_digest.so.manifest -outputresource:.\Debug\mod_auth_digest.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_auth_digest.dep") +!INCLUDE "mod_auth_digest.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_auth_digest.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_auth_digest - Win32 Release" || "$(CFG)" == "mod_auth_digest - Win32 Debug" + +!IF "$(CFG)" == "mod_auth_digest - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_auth_digest - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_auth_digest - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_auth_digest - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_auth_digest - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_auth_digest - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_auth_digest - Win32 Release" + + +"$(INTDIR)\mod_auth_digest.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_auth_digest.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_auth_digest.so" /d LONG_NAME="auth_digest_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_auth_digest - Win32 Debug" + + +"$(INTDIR)\mod_auth_digest.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_auth_digest.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_auth_digest.so" /d LONG_NAME="auth_digest_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_auth_digest.c + +"$(INTDIR)\mod_auth_digest.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_auth_form.c b/modules/aaa/mod_auth_form.c new file mode 100644 index 0000000..d443092 --- /dev/null +++ b/modules/aaa/mod_auth_form.c @@ -0,0 +1,1332 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_strings.h" +#include "apr_lib.h" /* for apr_isspace */ +#include "apr_base64.h" /* for apr_base64_decode et al */ +#define APR_WANT_STRFUNC /* for strcasecmp */ +#include "apr_want.h" + +#include "ap_config.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" +#include "ap_provider.h" +#include "util_md5.h" +#include "ap_expr.h" + +#include "mod_auth.h" +#include "mod_session.h" +#include "mod_request.h" + +#define FORM_LOGIN_HANDLER "form-login-handler" +#define FORM_LOGOUT_HANDLER "form-logout-handler" +#define FORM_REDIRECT_HANDLER "form-redirect-handler" +#define MOD_AUTH_FORM_HASH "site" + +static APR_OPTIONAL_FN_TYPE(ap_session_load) *ap_session_load_fn = NULL; +static APR_OPTIONAL_FN_TYPE(ap_session_get) *ap_session_get_fn = NULL; +static APR_OPTIONAL_FN_TYPE(ap_session_set) *ap_session_set_fn = NULL; + +static void (*ap_request_insert_filter_fn) (request_rec * r) = NULL; +static void (*ap_request_remove_filter_fn) (request_rec * r) = NULL; + +typedef struct { + authn_provider_list *providers; + char *dir; + int authoritative; + int authoritative_set; + const char *site; + int site_set; + const char *username; + int username_set; + const char *password; + int password_set; + apr_size_t form_size; + int form_size_set; + int fakebasicauth; + int fakebasicauth_set; + const char *location; + int location_set; + const char *method; + int method_set; + const char *mimetype; + int mimetype_set; + const char *body; + int body_set; + int disable_no_store; + int disable_no_store_set; + ap_expr_info_t *loginsuccess; + int loginsuccess_set; + ap_expr_info_t *loginrequired; + int loginrequired_set; + ap_expr_info_t *logout; + int logout_set; +} auth_form_config_rec; + +static void *create_auth_form_dir_config(apr_pool_t * p, char *d) +{ + auth_form_config_rec *conf = apr_pcalloc(p, sizeof(*conf)); + + conf->dir = d; + /* Any failures are fatal. */ + conf->authoritative = 1; + + /* form size defaults to 8k */ + conf->form_size = HUGE_STRING_LEN; + + /* default form field names */ + conf->username = "httpd_username"; + conf->password = "httpd_password"; + conf->location = "httpd_location"; + conf->method = "httpd_method"; + conf->mimetype = "httpd_mimetype"; + conf->body = "httpd_body"; + + return conf; +} + +static void *merge_auth_form_dir_config(apr_pool_t * p, void *basev, void *addv) +{ + auth_form_config_rec *new = (auth_form_config_rec *) apr_pcalloc(p, sizeof(auth_form_config_rec)); + auth_form_config_rec *add = (auth_form_config_rec *) addv; + auth_form_config_rec *base = (auth_form_config_rec *) basev; + + new->providers = !add->providers ? base->providers : add->providers; + new->authoritative = (add->authoritative_set == 0) ? base->authoritative : add->authoritative; + new->authoritative_set = add->authoritative_set || base->authoritative_set; + new->site = (add->site_set == 0) ? base->site : add->site; + new->site_set = add->site_set || base->site_set; + new->username = (add->username_set == 0) ? base->username : add->username; + new->username_set = add->username_set || base->username_set; + new->password = (add->password_set == 0) ? base->password : add->password; + new->password_set = add->password_set || base->password_set; + new->location = (add->location_set == 0) ? base->location : add->location; + new->location_set = add->location_set || base->location_set; + new->form_size = (add->form_size_set == 0) ? base->form_size : add->form_size; + new->form_size_set = add->form_size_set || base->form_size_set; + new->fakebasicauth = (add->fakebasicauth_set == 0) ? base->fakebasicauth : add->fakebasicauth; + new->fakebasicauth_set = add->fakebasicauth_set || base->fakebasicauth_set; + new->method = (add->method_set == 0) ? base->method : add->method; + new->method_set = add->method_set || base->method_set; + new->mimetype = (add->mimetype_set == 0) ? base->mimetype : add->mimetype; + new->mimetype_set = add->mimetype_set || base->mimetype_set; + new->body = (add->body_set == 0) ? base->body : add->body; + new->body_set = add->body_set || base->body_set; + new->disable_no_store = (add->disable_no_store_set == 0) ? base->disable_no_store : add->disable_no_store; + new->disable_no_store_set = add->disable_no_store_set || base->disable_no_store_set; + new->loginsuccess = (add->loginsuccess_set == 0) ? base->loginsuccess : add->loginsuccess; + new->loginsuccess_set = add->loginsuccess_set || base->loginsuccess_set; + new->loginrequired = (add->loginrequired_set == 0) ? base->loginrequired : add->loginrequired; + new->loginrequired_set = add->loginrequired_set || base->loginrequired_set; + new->logout = (add->logout_set == 0) ? base->logout : add->logout; + new->logout_set = add->logout_set || base->logout_set; + + return new; +} + +static const char *add_authn_provider(cmd_parms * cmd, void *config, + const char *arg) +{ + auth_form_config_rec *conf = (auth_form_config_rec *) config; + authn_provider_list *newp; + + newp = apr_pcalloc(cmd->pool, sizeof(authn_provider_list)); + newp->provider_name = arg; + + /* lookup and cache the actual provider now */ + newp->provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP, + newp->provider_name, + AUTHN_PROVIDER_VERSION); + + if (newp->provider == NULL) { + /* + * by the time they use it, the provider should be loaded and + * registered with us. + */ + return apr_psprintf(cmd->pool, + "Unknown Authn provider: %s", + newp->provider_name); + } + + if (!newp->provider->check_password) { + /* if it doesn't provide the appropriate function, reject it */ + return apr_psprintf(cmd->pool, + "The '%s' Authn provider doesn't support " + "Form Authentication", newp->provider_name); + } + + /* Add it to the list now. */ + if (!conf->providers) { + conf->providers = newp; + } + else { + authn_provider_list *last = conf->providers; + + while (last->next) { + last = last->next; + } + last->next = newp; + } + + return NULL; +} + +/** + * Sanity check a given string that it exists, is not empty, + * and does not contain special characters. + */ +static const char *check_string(cmd_parms * cmd, const char *string) +{ + if (!string || !*string || ap_strchr_c(string, '=') || ap_strchr_c(string, '&')) { + return apr_pstrcat(cmd->pool, cmd->directive->directive, + " cannot be empty, or contain '=' or '&'.", + NULL); + } + return NULL; +} + +static const char *set_cookie_form_location(cmd_parms * cmd, void *config, const char *location) +{ + auth_form_config_rec *conf = (auth_form_config_rec *) config; + conf->location = location; + conf->location_set = 1; + return check_string(cmd, location); +} + +static const char *set_cookie_form_username(cmd_parms * cmd, void *config, const char *username) +{ + auth_form_config_rec *conf = (auth_form_config_rec *) config; + conf->username = username; + conf->username_set = 1; + return check_string(cmd, username); +} + +static const char *set_cookie_form_password(cmd_parms * cmd, void *config, const char *password) +{ + auth_form_config_rec *conf = (auth_form_config_rec *) config; + conf->password = password; + conf->password_set = 1; + return check_string(cmd, password); +} + +static const char *set_cookie_form_method(cmd_parms * cmd, void *config, const char *method) +{ + auth_form_config_rec *conf = (auth_form_config_rec *) config; + conf->method = method; + conf->method_set = 1; + return check_string(cmd, method); +} + +static const char *set_cookie_form_mimetype(cmd_parms * cmd, void *config, const char *mimetype) +{ + auth_form_config_rec *conf = (auth_form_config_rec *) config; + conf->mimetype = mimetype; + conf->mimetype_set = 1; + return check_string(cmd, mimetype); +} + +static const char *set_cookie_form_body(cmd_parms * cmd, void *config, const char *body) +{ + auth_form_config_rec *conf = (auth_form_config_rec *) config; + conf->body = body; + conf->body_set = 1; + return check_string(cmd, body); +} + +static const char *set_cookie_form_size(cmd_parms * cmd, void *config, + const char *arg) +{ + auth_form_config_rec *conf = config; + apr_off_t size; + + if (APR_SUCCESS != apr_strtoff(&size, arg, NULL, 10) + || size < 0 || size > APR_SIZE_MAX) { + return "AuthCookieFormSize must be a size in bytes, or zero."; + } + conf->form_size = (apr_size_t)size; + conf->form_size_set = 1; + + return NULL; +} + +static const char *set_login_required_location(cmd_parms * cmd, void *config, const char *loginrequired) +{ + auth_form_config_rec *conf = (auth_form_config_rec *) config; + const char *err; + + conf->loginrequired = ap_expr_parse_cmd(cmd, loginrequired, AP_EXPR_FLAG_STRING_RESULT, + &err, NULL); + if (err) { + return apr_psprintf(cmd->pool, + "Could not parse login required expression '%s': %s", + loginrequired, err); + } + conf->loginrequired_set = 1; + + return NULL; +} + +static const char *set_login_success_location(cmd_parms * cmd, void *config, const char *loginsuccess) +{ + auth_form_config_rec *conf = (auth_form_config_rec *) config; + const char *err; + + conf->loginsuccess = ap_expr_parse_cmd(cmd, loginsuccess, AP_EXPR_FLAG_STRING_RESULT, + &err, NULL); + if (err) { + return apr_psprintf(cmd->pool, + "Could not parse login success expression '%s': %s", + loginsuccess, err); + } + conf->loginsuccess_set = 1; + + return NULL; +} + +static const char *set_logout_location(cmd_parms * cmd, void *config, const char *logout) +{ + auth_form_config_rec *conf = (auth_form_config_rec *) config; + const char *err; + + conf->logout = ap_expr_parse_cmd(cmd, logout, AP_EXPR_FLAG_STRING_RESULT, + &err, NULL); + if (err) { + return apr_psprintf(cmd->pool, + "Could not parse logout required expression '%s': %s", + logout, err); + } + conf->logout_set = 1; + + return NULL; +} + +static const char *set_site_passphrase(cmd_parms * cmd, void *config, const char *site) +{ + auth_form_config_rec *conf = (auth_form_config_rec *) config; + conf->site = site; + conf->site_set = 1; + return NULL; +} + +static const char *set_authoritative(cmd_parms * cmd, void *config, int flag) +{ + auth_form_config_rec *conf = (auth_form_config_rec *) config; + conf->authoritative = flag; + conf->authoritative_set = 1; + return NULL; +} + +static const char *set_fake_basic_auth(cmd_parms * cmd, void *config, int flag) +{ + auth_form_config_rec *conf = (auth_form_config_rec *) config; + conf->fakebasicauth = flag; + conf->fakebasicauth_set = 1; + return NULL; +} + +static const char *set_disable_no_store(cmd_parms * cmd, void *config, int flag) +{ + auth_form_config_rec *conf = (auth_form_config_rec *) config; + conf->disable_no_store = flag; + conf->disable_no_store_set = 1; + return NULL; +} + +static const command_rec auth_form_cmds[] = +{ + AP_INIT_ITERATE("AuthFormProvider", add_authn_provider, NULL, OR_AUTHCFG, + "specify the auth providers for a directory or location"), + AP_INIT_TAKE1("AuthFormUsername", set_cookie_form_username, NULL, OR_AUTHCFG, + "The field of the login form carrying the username"), + AP_INIT_TAKE1("AuthFormPassword", set_cookie_form_password, NULL, OR_AUTHCFG, + "The field of the login form carrying the password"), + AP_INIT_TAKE1("AuthFormLocation", set_cookie_form_location, NULL, OR_AUTHCFG, + "The field of the login form carrying the URL to redirect on " + "successful login."), + AP_INIT_TAKE1("AuthFormMethod", set_cookie_form_method, NULL, OR_AUTHCFG, + "The field of the login form carrying the original request method."), + AP_INIT_TAKE1("AuthFormMimetype", set_cookie_form_mimetype, NULL, OR_AUTHCFG, + "The field of the login form carrying the original request mimetype."), + AP_INIT_TAKE1("AuthFormBody", set_cookie_form_body, NULL, OR_AUTHCFG, + "The field of the login form carrying the urlencoded original request " + "body."), + AP_INIT_TAKE1("AuthFormSize", set_cookie_form_size, NULL, ACCESS_CONF, + "Maximum size of body parsed by the form parser"), + AP_INIT_TAKE1("AuthFormLoginRequiredLocation", set_login_required_location, + NULL, OR_AUTHCFG, + "If set, redirect the browser to this URL rather than " + "return 401 Not Authorized."), + AP_INIT_TAKE1("AuthFormLoginSuccessLocation", set_login_success_location, + NULL, OR_AUTHCFG, + "If set, redirect the browser to this URL when a login " + "processed by the login handler is successful."), + AP_INIT_TAKE1("AuthFormLogoutLocation", set_logout_location, + NULL, OR_AUTHCFG, + "The URL of the logout successful page. An attempt to access an " + "URL handled by the handler " FORM_LOGOUT_HANDLER " will result " + "in an redirect to this page after logout."), + AP_INIT_TAKE1("AuthFormSitePassphrase", set_site_passphrase, + NULL, OR_AUTHCFG, + "If set, use this passphrase to determine whether the user should " + "be authenticated. Bypasses the user authentication check on " + "every website hit, and is useful for high traffic sites."), + AP_INIT_FLAG("AuthFormAuthoritative", set_authoritative, + NULL, OR_AUTHCFG, + "Set to 'Off' to allow access control to be passed along to " + "lower modules if the UserID is not known to this module"), + AP_INIT_FLAG("AuthFormFakeBasicAuth", set_fake_basic_auth, + NULL, OR_AUTHCFG, + "Set to 'On' to pass through authentication to the rest of the " + "server as a basic authentication header."), + AP_INIT_FLAG("AuthFormDisableNoStore", set_disable_no_store, + NULL, OR_AUTHCFG, + "Set to 'on' to stop the sending of a Cache-Control no-store header with " + "the login screen. This allows the browser to cache the credentials, but " + "at the risk of it being possible for the login form to be resubmitted " + "and revealed to the backend server through XSS. Use at own risk."), + {NULL} +}; + +module AP_MODULE_DECLARE_DATA auth_form_module; + +static void note_cookie_auth_failure(request_rec * r) +{ + auth_form_config_rec *conf = ap_get_module_config(r->per_dir_config, + &auth_form_module); + + if (conf->location && ap_strchr_c(conf->location, ':')) { + apr_table_setn(r->err_headers_out, "Location", conf->location); + } +} + +static int hook_note_cookie_auth_failure(request_rec * r, + const char *auth_type) +{ + if (ap_cstr_casecmp(auth_type, "form")) + return DECLINED; + + note_cookie_auth_failure(r); + return OK; +} + +/** + * Set the auth username and password into the main request + * notes table. + */ +static void set_notes_auth(request_rec * r, + const char *user, const char *pw, + const char *method, const char *mimetype) +{ + apr_table_t *notes = NULL; + const char *authname; + + /* find the main request */ + while (r->main) { + r = r->main; + } + /* find the first redirect */ + while (r->prev) { + r = r->prev; + } + notes = r->notes; + + /* have we isolated the user and pw before? */ + authname = ap_auth_name(r); + if (user) { + apr_table_setn(notes, apr_pstrcat(r->pool, authname, "-user", NULL), user); + } + if (pw) { + apr_table_setn(notes, apr_pstrcat(r->pool, authname, "-pw", NULL), pw); + } + if (method) { + apr_table_setn(notes, apr_pstrcat(r->pool, authname, "-method", NULL), method); + } + if (mimetype) { + apr_table_setn(notes, apr_pstrcat(r->pool, authname, "-mimetype", NULL), mimetype); + } + +} + +/** + * Get the auth username and password from the main request + * notes table, if present. + */ +static void get_notes_auth(request_rec *r, + const char **user, const char **pw, + const char **method, const char **mimetype) +{ + const char *authname; + request_rec *m = r; + + /* find the main request */ + while (m->main) { + m = m->main; + } + /* find the first redirect */ + while (m->prev) { + m = m->prev; + } + + /* have we isolated the user and pw before? */ + authname = ap_auth_name(m); + if (user) { + *user = (char *) apr_table_get(m->notes, apr_pstrcat(m->pool, authname, "-user", NULL)); + } + if (pw) { + *pw = (char *) apr_table_get(m->notes, apr_pstrcat(m->pool, authname, "-pw", NULL)); + } + if (method) { + *method = (char *) apr_table_get(m->notes, apr_pstrcat(m->pool, authname, "-method", NULL)); + } + if (mimetype) { + *mimetype = (char *) apr_table_get(m->notes, apr_pstrcat(m->pool, authname, "-mimetype", NULL)); + } + + /* set the user, even though the user is unauthenticated at this point */ + if (user && *user) { + r->user = (char *) *user; + } + + ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, + "from notes: user: %s, pw: %s, method: %s, mimetype: %s", + user ? *user : "<null>", pw ? *pw : "<null>", + method ? *method : "<null>", mimetype ? *mimetype : "<null>"); + +} + +/** + * Set the auth username and password into the session. + * + * If either the username, or the password are NULL, the username + * and/or password will be removed from the session. + */ +static apr_status_t set_session_auth(request_rec * r, + const char *user, const char *pw, const char *site) +{ + const char *hash = NULL; + const char *authname = ap_auth_name(r); + session_rec *z = NULL; + + if (site) { + hash = ap_md5(r->pool, + (unsigned char *) apr_pstrcat(r->pool, user, ":", site, NULL)); + } + + ap_session_load_fn(r, &z); + ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-" MOD_SESSION_USER, NULL), user); + ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-" MOD_SESSION_PW, NULL), pw); + ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-" MOD_AUTH_FORM_HASH, NULL), hash); + + return APR_SUCCESS; + +} + +/** + * Get the auth username and password from the main request + * notes table, if present. + */ +static apr_status_t get_session_auth(request_rec * r, + const char **user, const char **pw, const char **hash) +{ + const char *authname = ap_auth_name(r); + session_rec *z = NULL; + + ap_session_load_fn(r, &z); + + if (user) { + ap_session_get_fn(r, z, apr_pstrcat(r->pool, authname, "-" MOD_SESSION_USER, NULL), user); + } + if (pw) { + ap_session_get_fn(r, z, apr_pstrcat(r->pool, authname, "-" MOD_SESSION_PW, NULL), pw); + } + if (hash) { + ap_session_get_fn(r, z, apr_pstrcat(r->pool, authname, "-" MOD_AUTH_FORM_HASH, NULL), hash); + } + + /* set the user, even though the user is unauthenticated at this point */ + if (user && *user) { + r->user = (char *) *user; + } + + ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, + "from session: " MOD_SESSION_USER ": %s, " MOD_SESSION_PW + ": %s, " MOD_AUTH_FORM_HASH ": %s", + user ? *user : "<null>", pw ? *pw : "<null>", + hash ? *hash : "<null>"); + + return APR_SUCCESS; + +} + +/** + * Isolate the username and password in a POSTed form with the + * username in the "username" field, and the password in the + * "password" field. + * + * If either the username or the password is missing, this + * function will return HTTP_UNAUTHORIZED. + * + * The location field is considered optional, and will be returned + * if present. + */ +static int get_form_auth(request_rec * r, + const char *username, + const char *password, + const char *location, + const char *method, + const char *mimetype, + const char *body, + const char **sent_user, + const char **sent_pw, + const char **sent_loc, + const char **sent_method, + const char **sent_mimetype, + apr_bucket_brigade **sent_body, + auth_form_config_rec * conf) +{ + /* sanity check - are we a POST request? */ + + /* find the username and password in the form */ + apr_array_header_t *pairs = NULL; + apr_off_t len; + apr_size_t size; + int res; + char *buffer; + + /* have we isolated the user and pw before? */ + get_notes_auth(r, sent_user, sent_pw, sent_method, sent_mimetype); + if (sent_user && *sent_user && sent_pw && *sent_pw) { + return OK; + } + + res = ap_parse_form_data(r, NULL, &pairs, -1, conf->form_size); + if (res != OK) { + return res; + } + while (pairs && !apr_is_empty_array(pairs)) { + ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs); + if (username && !strcmp(pair->name, username) && sent_user) { + apr_brigade_length(pair->value, 1, &len); + size = (apr_size_t) len; + buffer = apr_palloc(r->pool, size + 1); + apr_brigade_flatten(pair->value, buffer, &size); + buffer[len] = 0; + *sent_user = buffer; + } + else if (password && !strcmp(pair->name, password) && sent_pw) { + apr_brigade_length(pair->value, 1, &len); + size = (apr_size_t) len; + buffer = apr_palloc(r->pool, size + 1); + apr_brigade_flatten(pair->value, buffer, &size); + buffer[len] = 0; + *sent_pw = buffer; + } + else if (location && !strcmp(pair->name, location) && sent_loc) { + apr_brigade_length(pair->value, 1, &len); + size = (apr_size_t) len; + buffer = apr_palloc(r->pool, size + 1); + apr_brigade_flatten(pair->value, buffer, &size); + buffer[len] = 0; + *sent_loc = buffer; + } + else if (method && !strcmp(pair->name, method) && sent_method) { + apr_brigade_length(pair->value, 1, &len); + size = (apr_size_t) len; + buffer = apr_palloc(r->pool, size + 1); + apr_brigade_flatten(pair->value, buffer, &size); + buffer[len] = 0; + *sent_method = buffer; + } + else if (mimetype && !strcmp(pair->name, mimetype) && sent_mimetype) { + apr_brigade_length(pair->value, 1, &len); + size = (apr_size_t) len; + buffer = apr_palloc(r->pool, size + 1); + apr_brigade_flatten(pair->value, buffer, &size); + buffer[len] = 0; + *sent_mimetype = buffer; + } + else if (body && !strcmp(pair->name, body) && sent_body) { + *sent_body = pair->value; + } + } + + ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, + "from form: user: %s, pw: %s, method: %s, mimetype: %s, location: %s", + sent_user ? *sent_user : "<null>", sent_pw ? *sent_pw : "<null>", + sent_method ? *sent_method : "<null>", + sent_mimetype ? *sent_mimetype : "<null>", + sent_loc ? *sent_loc : "<null>"); + + /* set the user, even though the user is unauthenticated at this point */ + if (sent_user && *sent_user) { + r->user = (char *) *sent_user; + } + + /* a missing username or missing password means auth denied */ + if (!sent_user || !*sent_user) { + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02982) + "form parsed, but username field '%s' was missing or empty, unauthorized", + username); + + return HTTP_UNAUTHORIZED; + } + if (!sent_pw || !*sent_pw) { + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02983) + "form parsed, but password field '%s' was missing or empty, unauthorized", + password); + + return HTTP_UNAUTHORIZED; + } + + /* + * save away the username, password, mimetype and method, so that they + * are available should the auth need to be run again. + */ + set_notes_auth(r, *sent_user, *sent_pw, sent_method ? *sent_method : NULL, + sent_mimetype ? *sent_mimetype : NULL); + + return OK; +} + +/* These functions return 0 if client is OK, and proper error status + * if not... either HTTP_UNAUTHORIZED, if we made a check, and it failed, or + * HTTP_INTERNAL_SERVER_ERROR, if things are so totally confused that we + * couldn't figure out how to tell if the client is authorized or not. + * + * If they return DECLINED, and all other modules also decline, that's + * treated by the server core as a configuration error, logged and + * reported as such. + */ + + +/** + * Given a username and site passphrase hash from the session, determine + * whether the site passphrase is valid for this session. + * + * If the site passphrase is NULL, or if the sent_hash is NULL, this + * function returns DECLINED. + * + * If the site passphrase hash does not match the sent hash, this function + * returns AUTH_USER_NOT_FOUND. + * + * On success, returns OK. + */ +static int check_site(request_rec * r, const char *site, const char *sent_user, const char *sent_hash) +{ + + if (site && sent_user && sent_hash) { + const char *hash = ap_md5(r->pool, + (unsigned char *) apr_pstrcat(r->pool, sent_user, ":", site, NULL)); + + if (!strcmp(sent_hash, hash)) { + return OK; + } + else { + return AUTH_USER_NOT_FOUND; + } + } + + return DECLINED; + +} + +/** + * Given a username and password (extracted externally from a cookie), run + * the authnz hooks to determine whether this request is authorized. + * + * Return an HTTP code. + */ +static int check_authn(request_rec * r, const char *sent_user, const char *sent_pw) +{ + authn_status auth_result; + authn_provider_list *current_provider; + auth_form_config_rec *conf = ap_get_module_config(r->per_dir_config, + &auth_form_module); + + current_provider = conf->providers; + do { + const authn_provider *provider; + + /* + * For now, if a provider isn't set, we'll be nice and use the file + * provider. + */ + if (!current_provider) { + provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP, + AUTHN_DEFAULT_PROVIDER, + AUTHN_PROVIDER_VERSION); + + if (!provider || !provider->check_password) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01806) + "no authn provider configured"); + auth_result = AUTH_GENERAL_ERROR; + break; + } + apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, AUTHN_DEFAULT_PROVIDER); + } + else { + provider = current_provider->provider; + apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, current_provider->provider_name); + } + + if (!sent_user || !sent_pw) { + auth_result = AUTH_USER_NOT_FOUND; + break; + } + + auth_result = provider->check_password(r, sent_user, sent_pw); + + apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE); + + /* Something occurred. Stop checking. */ + if (auth_result != AUTH_USER_NOT_FOUND) { + break; + } + + /* If we're not really configured for providers, stop now. */ + if (!conf->providers) { + break; + } + + current_provider = current_provider->next; + } while (current_provider); + + if (auth_result != AUTH_GRANTED) { + int return_code; + + /* If we're not authoritative, then any error is ignored. */ + if (!(conf->authoritative) && auth_result != AUTH_DENIED) { + return DECLINED; + } + + switch (auth_result) { + case AUTH_DENIED: + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01807) + "user '%s': authentication failure for \"%s\": " + "password Mismatch", + sent_user, r->uri); + return_code = HTTP_UNAUTHORIZED; + break; + case AUTH_USER_NOT_FOUND: + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01808) + "user '%s' not found: %s", sent_user, r->uri); + return_code = HTTP_UNAUTHORIZED; + break; + case AUTH_GENERAL_ERROR: + default: + /* + * We'll assume that the module has already said what its error + * was in the logs. + */ + return_code = HTTP_INTERNAL_SERVER_ERROR; + break; + } + + /* If we're returning 401, tell them to try again. */ + if (return_code == HTTP_UNAUTHORIZED) { + note_cookie_auth_failure(r); + } + +/* TODO: Flag the user somehow as to the reason for the failure */ + + return return_code; + } + + return OK; + +} + +/* fake the basic authentication header if configured to do so */ +static void fake_basic_authentication(request_rec *r, auth_form_config_rec *conf, + const char *user, const char *pw) +{ + if (conf->fakebasicauth) { + char *basic = apr_pstrcat(r->pool, user, ":", pw, NULL); + apr_size_t size = (apr_size_t) strlen(basic); + char *base64 = apr_palloc(r->pool, + apr_base64_encode_len(size + 1) * sizeof(char)); + apr_base64_encode(base64, basic, size); + apr_table_setn(r->headers_in, "Authorization", + apr_pstrcat(r->pool, "Basic ", base64, NULL)); + } +} + +/** + * Must we use form authentication? If so, extract the cookie and run + * the authnz hooks to determine if the login is valid. + * + * If the login is not valid, a 401 Not Authorized will be returned. It + * is up to the webmaster to ensure this screen displays a suitable login + * form to give the user the opportunity to log in. + */ +static int authenticate_form_authn(request_rec * r) +{ + auth_form_config_rec *conf = ap_get_module_config(r->per_dir_config, + &auth_form_module); + const char *sent_user = NULL, *sent_pw = NULL, *sent_hash = NULL; + const char *sent_loc = NULL, *sent_method = "GET", *sent_mimetype = NULL; + const char *current_auth = NULL; + const char *err; + apr_status_t res; + int rv = HTTP_UNAUTHORIZED; + + /* Are we configured to be Form auth? */ + current_auth = ap_auth_type(r); + if (!current_auth || ap_cstr_casecmp(current_auth, "form")) { + return DECLINED; + } + + /* + * XSS security warning: using cookies to store private data only works + * when the administrator has full control over the source website. When + * in forward-proxy mode, websites are public by definition, and so can + * never be secure. Abort the auth attempt in this case. + */ + if (PROXYREQ_PROXY == r->proxyreq) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01809) + "form auth cannot be used for proxy " + "requests due to XSS risk, access denied: %s", r->uri); + return HTTP_INTERNAL_SERVER_ERROR; + } + + /* We need an authentication realm. */ + if (!ap_auth_name(r)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01810) + "need AuthName: %s", r->uri); + return HTTP_INTERNAL_SERVER_ERROR; + } + + r->ap_auth_type = (char *) current_auth; + + /* try get the username and password from the notes, if present */ + get_notes_auth(r, &sent_user, &sent_pw, &sent_method, &sent_mimetype); + if (!sent_user || !sent_pw || !*sent_user || !*sent_pw) { + + /* otherwise try get the username and password from a session, if present */ + res = get_session_auth(r, &sent_user, &sent_pw, &sent_hash); + + } + else { + res = APR_SUCCESS; + } + + /* first test whether the site passphrase matches */ + if (APR_SUCCESS == res && sent_user && sent_hash && sent_pw) { + rv = check_site(r, conf->site, sent_user, sent_hash); + if (OK == rv) { + fake_basic_authentication(r, conf, sent_user, sent_pw); + return OK; + } + } + + /* otherwise test for a normal password match */ + if (APR_SUCCESS == res && sent_user && sent_pw) { + rv = check_authn(r, sent_user, sent_pw); + if (OK == rv) { + fake_basic_authentication(r, conf, sent_user, sent_pw); + return OK; + } + } + + /* + * If we reach this point, the request should fail with access denied, + * except for one potential scenario: + * + * If the request is a POST, and the posted form contains user defined fields + * for a username and a password, and the username and password are correct, + * then return the response obtained by a GET to this URL. + * + * If an additional user defined location field is present in the form, + * instead of a GET of the current URL, redirect the browser to the new + * location. + * + * As a further option, if the user defined fields for the type of request, + * the mime type of the body of the request, and the body of the request + * itself are present, replace this request with a new request of the given + * type and with the given body. + * + * Otherwise access is denied. + * + * Reading the body requires some song and dance, because the input filters + * are not yet configured. To work around this problem, we create a + * subrequest and use that to create a sane filter stack we can read the + * form from. + * + * The main request is then capped with a kept_body input filter, which has + * the effect of guaranteeing the input stack can be safely read a second time. + * + */ + if (HTTP_UNAUTHORIZED == rv && r->method_number == M_POST && ap_is_initial_req(r)) { + request_rec *rr; + apr_bucket_brigade *sent_body = NULL; + + /* create a subrequest of our current uri */ + rr = ap_sub_req_lookup_uri(r->uri, r, r->input_filters); + rr->headers_in = r->headers_in; + + /* run the insert_filters hook on the subrequest to ensure a body read can + * be done properly. + */ + ap_run_insert_filter(rr); + + /* parse the form by reading the subrequest */ + rv = get_form_auth(rr, conf->username, conf->password, conf->location, + conf->method, conf->mimetype, conf->body, + &sent_user, &sent_pw, &sent_loc, &sent_method, + &sent_mimetype, &sent_body, conf); + + /* make sure any user detected within the subrequest is saved back to + * the main request. + */ + r->user = apr_pstrdup(r->pool, rr->user); + + /* we cannot clean up rr at this point, as memory allocated to rr is + * referenced from the main request. It will be cleaned up when the + * main request is cleaned up. + */ + + /* insert the kept_body filter on the main request to guarantee the + * input filter stack cannot be read a second time, optionally inject + * a saved body if one was specified in the login form. + */ + if (sent_body && sent_mimetype) { + apr_table_set(r->headers_in, "Content-Type", sent_mimetype); + r->kept_body = sent_body; + } + else { + r->kept_body = apr_brigade_create(r->pool, r->connection->bucket_alloc); + } + ap_request_insert_filter_fn(r); + + /* did the form ask to change the method? if so, switch in the redirect handler + * to relaunch this request as the subrequest with the new method. If the + * form didn't specify a method, the default value GET will force a redirect. + */ + if (sent_method && strcmp(r->method, sent_method)) { + r->handler = FORM_REDIRECT_HANDLER; + } + + /* check the authn in the main request, based on the username found */ + if (OK == rv) { + rv = check_authn(r, sent_user, sent_pw); + if (OK == rv) { + fake_basic_authentication(r, conf, sent_user, sent_pw); + set_session_auth(r, sent_user, sent_pw, conf->site); + if (sent_loc) { + apr_table_set(r->headers_out, "Location", sent_loc); + return HTTP_MOVED_TEMPORARILY; + } + if (conf->loginsuccess) { + const char *loginsuccess = ap_expr_str_exec(r, + conf->loginsuccess, &err); + if (!err) { + apr_table_set(r->headers_out, "Location", loginsuccess); + return HTTP_MOVED_TEMPORARILY; + } + else { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02339) + "Can't evaluate login success expression: %s", err); + return HTTP_INTERNAL_SERVER_ERROR; + } + } + } + } + + } + + /* + * did the admin prefer to be redirected to the login page on failure + * instead? + */ + if (HTTP_UNAUTHORIZED == rv && conf->loginrequired) { + const char *loginrequired = ap_expr_str_exec(r, + conf->loginrequired, &err); + if (!err) { + apr_table_set(r->headers_out, "Location", loginrequired); + return HTTP_MOVED_TEMPORARILY; + } + else { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02340) + "Can't evaluate login required expression: %s", err); + return HTTP_INTERNAL_SERVER_ERROR; + } + } + + /* did the user ask to be redirected on login success? */ + if (sent_loc) { + apr_table_set(r->headers_out, "Location", sent_loc); + rv = HTTP_MOVED_TEMPORARILY; + } + + + /* + * potential security issue: if we return a login to the browser, we must + * send a no-store to make sure a well behaved browser will not try and + * send the login details a second time if the back button is pressed. + * + * if the user has full control over the backend, the + * AuthCookieDisableNoStore can be used to turn this off. + */ + if (HTTP_UNAUTHORIZED == rv && !conf->disable_no_store) { + apr_table_addn(r->headers_out, "Cache-Control", "no-store"); + apr_table_addn(r->err_headers_out, "Cache-Control", "no-store"); + } + + return rv; + +} + +/** + * Handle a login attempt. + * + * If the login session is either missing or form authnz is unsuccessful, a + * 401 Not Authorized will be returned to the browser. The webmaster + * is expected to insert a login form into the 401 Not Authorized + * error screen. + * + * If the webmaster wishes, they can point the form submission at this + * handler, which will redirect the user to the correct page on success. + * On failure, the 401 Not Authorized error screen will be redisplayed, + * where the login attempt can be repeated. + * + */ +static int authenticate_form_login_handler(request_rec * r) +{ + auth_form_config_rec *conf; + const char *err; + + const char *sent_user = NULL, *sent_pw = NULL, *sent_loc = NULL; + int rv; + + if (strcmp(r->handler, FORM_LOGIN_HANDLER)) { + return DECLINED; + } + + if (r->method_number != M_POST) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01811) + "the " FORM_LOGIN_HANDLER " only supports the POST method for %s", + r->uri); + return HTTP_METHOD_NOT_ALLOWED; + } + + conf = ap_get_module_config(r->per_dir_config, &auth_form_module); + + rv = get_form_auth(r, conf->username, conf->password, conf->location, + NULL, NULL, NULL, + &sent_user, &sent_pw, &sent_loc, + NULL, NULL, NULL, conf); + if (OK == rv) { + rv = check_authn(r, sent_user, sent_pw); + if (OK == rv) { + set_session_auth(r, sent_user, sent_pw, conf->site); + if (sent_loc) { + apr_table_set(r->headers_out, "Location", sent_loc); + return HTTP_MOVED_TEMPORARILY; + } + if (conf->loginsuccess) { + const char *loginsuccess = ap_expr_str_exec(r, + conf->loginsuccess, &err); + if (!err) { + apr_table_set(r->headers_out, "Location", loginsuccess); + return HTTP_MOVED_TEMPORARILY; + } + else { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02341) + "Can't evaluate login success expression: %s", err); + return HTTP_INTERNAL_SERVER_ERROR; + } + } + return HTTP_OK; + } + } + + /* did we prefer to be redirected to the login page on failure instead? */ + if (HTTP_UNAUTHORIZED == rv && conf->loginrequired) { + const char *loginrequired = ap_expr_str_exec(r, + conf->loginrequired, &err); + if (!err) { + apr_table_set(r->headers_out, "Location", loginrequired); + return HTTP_MOVED_TEMPORARILY; + } + else { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02342) + "Can't evaluate login required expression: %s", err); + return HTTP_INTERNAL_SERVER_ERROR; + } + } + + return rv; + +} + +/** + * Handle a logout attempt. + * + * If an attempt is made to access this URL, any username and password + * embedded in the session is deleted. + * + * This has the effect of logging the person out. + * + * If a logout URI has been specified, this function will create an + * internal redirect to this page. + */ +static int authenticate_form_logout_handler(request_rec * r) +{ + auth_form_config_rec *conf; + const char *err; + + if (strcmp(r->handler, FORM_LOGOUT_HANDLER)) { + return DECLINED; + } + + conf = ap_get_module_config(r->per_dir_config, &auth_form_module); + + /* remove the username and password, effectively logging the user out */ + set_session_auth(r, NULL, NULL, NULL); + + /* + * make sure the logout page is never cached - otherwise the logout won't + * work! + */ + apr_table_addn(r->headers_out, "Cache-Control", "no-store"); + apr_table_addn(r->err_headers_out, "Cache-Control", "no-store"); + + /* if set, internal redirect to the logout page */ + if (conf->logout) { + const char *logout = ap_expr_str_exec(r, + conf->logout, &err); + if (!err) { + apr_table_addn(r->headers_out, "Location", logout); + return HTTP_TEMPORARY_REDIRECT; + } + else { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02343) + "Can't evaluate logout expression: %s", err); + return HTTP_INTERNAL_SERVER_ERROR; + } + } + + return HTTP_OK; + +} + +/** + * Handle a redirect attempt. + * + * If during a form login, the method, mimetype and request body are + * specified, this handler will ensure that this request is included + * as an internal redirect. + * + */ +static int authenticate_form_redirect_handler(request_rec * r) +{ + + request_rec *rr = NULL; + const char *sent_method = NULL, *sent_mimetype = NULL; + + if (strcmp(r->handler, FORM_REDIRECT_HANDLER)) { + return DECLINED; + } + + /* get the method and mimetype from the notes */ + get_notes_auth(r, NULL, NULL, &sent_method, &sent_mimetype); + + if (r->kept_body && sent_method && sent_mimetype) { + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01812) + "internal redirect to method '%s' and body mimetype '%s' for the " + "uri: %s", sent_method, sent_mimetype, r->uri); + + rr = ap_sub_req_method_uri(sent_method, r->uri, r, r->output_filters); + r->status = ap_run_sub_req(rr); + + } + else { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01813) + "internal redirect requested but one or all of method, mimetype or " + "body are NULL: %s", r->uri); + return HTTP_INTERNAL_SERVER_ERROR; + } + + /* return the underlying error, or OK on success */ + return r->status == HTTP_OK || r->status == OK ? OK : r->status; + +} + +static int authenticate_form_post_config(apr_pool_t *pconf, apr_pool_t *plog, + apr_pool_t *ptemp, server_rec *s) +{ + + if (!ap_session_load_fn || !ap_session_get_fn || !ap_session_set_fn) { + ap_session_load_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_load); + ap_session_get_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_get); + ap_session_set_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_set); + if (!ap_session_load_fn || !ap_session_get_fn || !ap_session_set_fn) { + ap_log_error(APLOG_MARK, APLOG_CRIT, 0, NULL, APLOGNO(02617) + "You must load mod_session to enable the mod_auth_form " + "functions"); + return !OK; + } + } + + if (!ap_request_insert_filter_fn || !ap_request_remove_filter_fn) { + ap_request_insert_filter_fn = APR_RETRIEVE_OPTIONAL_FN(ap_request_insert_filter); + ap_request_remove_filter_fn = APR_RETRIEVE_OPTIONAL_FN(ap_request_remove_filter); + if (!ap_request_insert_filter_fn || !ap_request_remove_filter_fn) { + ap_log_error(APLOG_MARK, APLOG_CRIT, 0, NULL, APLOGNO(02618) + "You must load mod_request to enable the mod_auth_form " + "functions"); + return !OK; + } + } + + return OK; +} + +static void register_hooks(apr_pool_t * p) +{ + ap_hook_post_config(authenticate_form_post_config,NULL,NULL,APR_HOOK_MIDDLE); + +#if AP_MODULE_MAGIC_AT_LEAST(20080403,1) + ap_hook_check_authn(authenticate_form_authn, NULL, NULL, APR_HOOK_MIDDLE, + AP_AUTH_INTERNAL_PER_CONF); +#else + ap_hook_check_user_id(authenticate_form_authn, NULL, NULL, APR_HOOK_MIDDLE); +#endif + ap_hook_handler(authenticate_form_login_handler, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_handler(authenticate_form_logout_handler, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_handler(authenticate_form_redirect_handler, NULL, NULL, APR_HOOK_MIDDLE); + + ap_hook_note_auth_failure(hook_note_cookie_auth_failure, NULL, NULL, + APR_HOOK_MIDDLE); +} + +AP_DECLARE_MODULE(auth_form) = +{ + STANDARD20_MODULE_STUFF, + create_auth_form_dir_config, /* dir config creater */ + merge_auth_form_dir_config, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + auth_form_cmds, /* command apr_table_t */ + register_hooks /* register hooks */ +}; diff --git a/modules/aaa/mod_auth_form.dep b/modules/aaa/mod_auth_form.dep new file mode 100644 index 0000000..190b2db --- /dev/null +++ b/modules/aaa/mod_auth_form.dep @@ -0,0 +1,66 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_auth_form.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_auth_form.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\mod_request.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\include\util_md5.h"\ + "..\..\srclib\apr-util\include\apr_base64.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_md5.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apr_uuid.h"\ + "..\..\srclib\apr-util\include\apr_xlate.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_lib.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + "..\session\mod_session.h"\ + diff --git a/modules/aaa/mod_auth_form.dsp b/modules/aaa/mod_auth_form.dsp new file mode 100644 index 0000000..f47c1a2 --- /dev/null +++ b/modules/aaa/mod_auth_form.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_auth_form" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_auth_form - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_auth_form.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_auth_form.mak" CFG="mod_auth_form - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_auth_form - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_auth_form - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_auth_form - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../session" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AAA_DECLARE_EXPORT" /Fd"Release\mod_auth_form_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_auth_form.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_auth_form.so" /d LONG_NAME="auth_form_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_auth_form.so" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_form.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_auth_form.so" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_form.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_auth_form.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_auth_form - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../session" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "AAA_DECLARE_EXPORT" /Fd"Debug\mod_auth_form_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_auth_form.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_auth_form.so" /d LONG_NAME="auth_form_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_auth_form.so" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_form.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_auth_form.so" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_form.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_auth_form.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_auth_form - Win32 Release" +# Name "mod_auth_form - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_auth_form.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_auth_form.mak b/modules/aaa/mod_auth_form.mak new file mode 100644 index 0000000..3c6c67a --- /dev/null +++ b/modules/aaa/mod_auth_form.mak @@ -0,0 +1,353 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_auth_form.dsp +!IF "$(CFG)" == "" +CFG=mod_auth_form - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_auth_form - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_auth_form - Win32 Release" && "$(CFG)" != "mod_auth_form - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_auth_form.mak" CFG="mod_auth_form - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_auth_form - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_auth_form - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_auth_form - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_auth_form.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_auth_form.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_auth_form.obj" + -@erase "$(INTDIR)\mod_auth_form.res" + -@erase "$(INTDIR)\mod_auth_form_src.idb" + -@erase "$(INTDIR)\mod_auth_form_src.pdb" + -@erase "$(OUTDIR)\mod_auth_form.exp" + -@erase "$(OUTDIR)\mod_auth_form.lib" + -@erase "$(OUTDIR)\mod_auth_form.pdb" + -@erase "$(OUTDIR)\mod_auth_form.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../session" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AAA_DECLARE_EXPORT" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_form_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_auth_form.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_auth_form.so" /d LONG_NAME="auth_form_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_form.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_auth_form.pdb" /debug /out:"$(OUTDIR)\mod_auth_form.so" /implib:"$(OUTDIR)\mod_auth_form.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_form.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_auth_form.obj" \ + "$(INTDIR)\mod_auth_form.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" + +"$(OUTDIR)\mod_auth_form.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_auth_form.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_auth_form.so" + if exist .\Release\mod_auth_form.so.manifest mt.exe -manifest .\Release\mod_auth_form.so.manifest -outputresource:.\Release\mod_auth_form.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_auth_form - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_auth_form.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_auth_form.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_auth_form.obj" + -@erase "$(INTDIR)\mod_auth_form.res" + -@erase "$(INTDIR)\mod_auth_form_src.idb" + -@erase "$(INTDIR)\mod_auth_form_src.pdb" + -@erase "$(OUTDIR)\mod_auth_form.exp" + -@erase "$(OUTDIR)\mod_auth_form.lib" + -@erase "$(OUTDIR)\mod_auth_form.pdb" + -@erase "$(OUTDIR)\mod_auth_form.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../session" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "AAA_DECLARE_EXPORT" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_form_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_auth_form.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_auth_form.so" /d LONG_NAME="auth_form_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_form.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_auth_form.pdb" /debug /out:"$(OUTDIR)\mod_auth_form.so" /implib:"$(OUTDIR)\mod_auth_form.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_auth_form.so +LINK32_OBJS= \ + "$(INTDIR)\mod_auth_form.obj" \ + "$(INTDIR)\mod_auth_form.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" + +"$(OUTDIR)\mod_auth_form.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_auth_form.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_auth_form.so" + if exist .\Debug\mod_auth_form.so.manifest mt.exe -manifest .\Debug\mod_auth_form.so.manifest -outputresource:.\Debug\mod_auth_form.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_auth_form.dep") +!INCLUDE "mod_auth_form.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_auth_form.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_auth_form - Win32 Release" || "$(CFG)" == "mod_auth_form - Win32 Debug" + +!IF "$(CFG)" == "mod_auth_form - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_auth_form - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_auth_form - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_auth_form - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_auth_form - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_auth_form - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_auth_form - Win32 Release" + + +"$(INTDIR)\mod_auth_form.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_auth_form.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_auth_form.so" /d LONG_NAME="auth_form_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_auth_form - Win32 Debug" + + +"$(INTDIR)\mod_auth_form.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_auth_form.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_auth_form.so" /d LONG_NAME="auth_form_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_auth_form.c + +"$(INTDIR)\mod_auth_form.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authn_anon.c b/modules/aaa/mod_authn_anon.c new file mode 100644 index 0000000..82559bc --- /dev/null +++ b/modules/aaa/mod_authn_anon.c @@ -0,0 +1,215 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Adapted to allow anonymous logins, just like with Anon-FTP, when + * one gives the magic user name 'anonymous' and ones email address + * as the password. + * + * Just add the following tokes to your <directory> setup: + * + * Anonymous magic-userid [magic-userid]... + * + * Anonymous_MustGiveEmail [ on | off ] default = on + * Anonymous_LogEmail [ on | off ] default = on + * Anonymous_VerifyEmail [ on | off ] default = off + * Anonymous_NoUserId [ on | off ] default = off + * + * The magic user id is something like 'anonymous', it is NOT case sensitive. + * + * The MustGiveEmail flag can be used to force users to enter something + * in the password field (like an email address). Default is on. + * + * Furthermore the 'NoUserID' flag can be set to allow completely empty + * usernames in as well; this can be is convenient as a single return + * in broken GUIs like W95 is often given by the user. The Default is off. + * + * Dirk.vanGulik@jrc.it; http://ewse.ceo.org; http://me-www.jrc.it/~dirkx + * + */ + +#include "apr_strings.h" + +#define APR_WANT_STRFUNC +#include "apr_want.h" + +#include "ap_provider.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_request.h" +#include "http_protocol.h" + +#include "mod_auth.h" + +typedef struct anon_auth_user { + const char *user; + struct anon_auth_user *next; +} anon_auth_user; + +typedef struct { + anon_auth_user *users; + int nouserid; + int logemail; + int verifyemail; + int mustemail; + int anyuserid; +} authn_anon_config_rec; + +static void *create_authn_anon_dir_config(apr_pool_t *p, char *d) +{ + authn_anon_config_rec *conf = apr_palloc(p, sizeof(*conf)); + + /* just to illustrate the defaults really. */ + conf->users = NULL; + + conf->nouserid = 0; + conf->anyuserid = 0; + conf->logemail = 1; + conf->verifyemail = 0; + conf->mustemail = 1; + return conf; +} + +static const char *anon_set_string_slots(cmd_parms *cmd, + void *my_config, const char *arg) +{ + authn_anon_config_rec *conf = my_config; + anon_auth_user *first; + + if (!*arg) { + return "Anonymous string cannot be empty, use Anonymous_NoUserId"; + } + + /* squeeze in a record */ + if (!conf->anyuserid) { + if (!strcmp(arg, "*")) { + conf->anyuserid = 1; + } + else { + first = conf->users; + conf->users = apr_palloc(cmd->pool, sizeof(*conf->users)); + conf->users->user = arg; + conf->users->next = first; + } + } + + return NULL; +} + +static const command_rec authn_anon_cmds[] = +{ + AP_INIT_ITERATE("Anonymous", anon_set_string_slots, NULL, OR_AUTHCFG, + "a space-separated list of user IDs"), + AP_INIT_FLAG("Anonymous_MustGiveEmail", ap_set_flag_slot, + (void *)APR_OFFSETOF(authn_anon_config_rec, mustemail), + OR_AUTHCFG, "Limited to 'on' or 'off'"), + AP_INIT_FLAG("Anonymous_NoUserId", ap_set_flag_slot, + (void *)APR_OFFSETOF(authn_anon_config_rec, nouserid), + OR_AUTHCFG, "Limited to 'on' or 'off'"), + AP_INIT_FLAG("Anonymous_VerifyEmail", ap_set_flag_slot, + (void *)APR_OFFSETOF(authn_anon_config_rec, verifyemail), + OR_AUTHCFG, "Limited to 'on' or 'off'"), + AP_INIT_FLAG("Anonymous_LogEmail", ap_set_flag_slot, + (void *)APR_OFFSETOF(authn_anon_config_rec, logemail), + OR_AUTHCFG, "Limited to 'on' or 'off'"), + {NULL} +}; + +module AP_MODULE_DECLARE_DATA authn_anon_module; + +static authn_status check_anonymous(request_rec *r, const char *user, + const char *sent_pw) +{ + authn_anon_config_rec *conf = ap_get_module_config(r->per_dir_config, + &authn_anon_module); + authn_status res = AUTH_USER_NOT_FOUND; + + /* Ignore if we are not configured */ + if (!conf->users && !conf->anyuserid) { + return AUTH_USER_NOT_FOUND; + } + + /* Do we allow an empty userID and/or is it the magic one + */ + if (!*user) { + if (conf->nouserid) { + res = AUTH_USER_FOUND; + } + } + else if (conf->anyuserid) { + res = AUTH_USER_FOUND; + } + else { + anon_auth_user *p = conf->users; + + while (p) { + if (!strcasecmp(user, p->user)) { + res = AUTH_USER_FOUND; + break; + } + p = p->next; + } + } + + /* Now if the supplied user-ID was ok, grant access if: + * (a) no passwd was sent and no password and no verification + * were configured. + * (b) password was sent and no verification was configured + * (c) verification was configured and the password (sent or not) + * looks like an email address + */ + if ( (res == AUTH_USER_FOUND) + && (!conf->mustemail || *sent_pw) + && ( !conf->verifyemail + || (ap_strchr_c(sent_pw, '@') && ap_strchr_c(sent_pw, '.')))) + { + if (conf->logemail && ap_is_initial_req(r)) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, APLOGNO(01672) + "Anonymous: Passwd <%s> Accepted", + sent_pw ? sent_pw : "\'none\'"); + } + + return AUTH_GRANTED; + } + + return (res == AUTH_USER_NOT_FOUND ? res : AUTH_DENIED); +} + +static const authn_provider authn_anon_provider = +{ + &check_anonymous, + NULL +}; + +static void register_hooks(apr_pool_t *p) +{ + ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "anon", + AUTHN_PROVIDER_VERSION, + &authn_anon_provider, AP_AUTH_INTERNAL_PER_CONF); +} + +AP_DECLARE_MODULE(authn_anon) = +{ + STANDARD20_MODULE_STUFF, + create_authn_anon_dir_config, /* dir config creater */ + NULL, /* dir merger ensure strictness */ + NULL, /* server config */ + NULL, /* merge server config */ + authn_anon_cmds, /* command apr_table_t */ + register_hooks /* register hooks */ +}; diff --git a/modules/aaa/mod_authn_anon.dep b/modules/aaa/mod_authn_anon.dep new file mode 100644 index 0000000..30bb436 --- /dev/null +++ b/modules/aaa/mod_authn_anon.dep @@ -0,0 +1,58 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authn_anon.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authn_anon.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_authn_anon.dsp b/modules/aaa/mod_authn_anon.dsp new file mode 100644 index 0000000..be88104 --- /dev/null +++ b/modules/aaa/mod_authn_anon.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_authn_anon" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authn_anon - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_anon.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_anon.mak" CFG="mod_authn_anon - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authn_anon - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authn_anon - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authn_anon - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_authn_anon_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authn_anon.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authn_anon.so" /d LONG_NAME="authn_anon_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authn_anon.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_anon.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authn_anon.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_anon.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authn_anon.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authn_anon - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_authn_anon_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authn_anon.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authn_anon.so" /d LONG_NAME="authn_anon_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authn_anon.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_anon.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authn_anon.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_anon.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authn_anon.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authn_anon - Win32 Release" +# Name "mod_authn_anon - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_authn_anon.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authn_anon.mak b/modules/aaa/mod_authn_anon.mak new file mode 100644 index 0000000..6ff9972 --- /dev/null +++ b/modules/aaa/mod_authn_anon.mak @@ -0,0 +1,381 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authn_anon.dsp +!IF "$(CFG)" == "" +CFG=mod_authn_anon - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_authn_anon - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_authn_anon - Win32 Release" && "$(CFG)" != "mod_authn_anon - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_anon.mak" CFG="mod_authn_anon - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authn_anon - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authn_anon - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authn_anon - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authn_anon.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Release" "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authn_anon.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" "mod_auth_basic - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authn_anon.obj" + -@erase "$(INTDIR)\mod_authn_anon.res" + -@erase "$(INTDIR)\mod_authn_anon_src.idb" + -@erase "$(INTDIR)\mod_authn_anon_src.pdb" + -@erase "$(OUTDIR)\mod_authn_anon.exp" + -@erase "$(OUTDIR)\mod_authn_anon.lib" + -@erase "$(OUTDIR)\mod_authn_anon.pdb" + -@erase "$(OUTDIR)\mod_authn_anon.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authn_anon_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authn_anon.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authn_anon.so" /d LONG_NAME="authn_anon_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authn_anon.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authn_anon.pdb" /debug /out:"$(OUTDIR)\mod_authn_anon.so" /implib:"$(OUTDIR)\mod_authn_anon.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_anon.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authn_anon.obj" \ + "$(INTDIR)\mod_authn_anon.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authn_anon.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authn_anon.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authn_anon.so" + if exist .\Release\mod_authn_anon.so.manifest mt.exe -manifest .\Release\mod_authn_anon.so.manifest -outputresource:.\Release\mod_authn_anon.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authn_anon - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authn_anon.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Debug" "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authn_anon.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" "mod_auth_basic - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authn_anon.obj" + -@erase "$(INTDIR)\mod_authn_anon.res" + -@erase "$(INTDIR)\mod_authn_anon_src.idb" + -@erase "$(INTDIR)\mod_authn_anon_src.pdb" + -@erase "$(OUTDIR)\mod_authn_anon.exp" + -@erase "$(OUTDIR)\mod_authn_anon.lib" + -@erase "$(OUTDIR)\mod_authn_anon.pdb" + -@erase "$(OUTDIR)\mod_authn_anon.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authn_anon_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authn_anon.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authn_anon.so" /d LONG_NAME="authn_anon_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authn_anon.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authn_anon.pdb" /debug /out:"$(OUTDIR)\mod_authn_anon.so" /implib:"$(OUTDIR)\mod_authn_anon.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_anon.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authn_anon.obj" \ + "$(INTDIR)\mod_authn_anon.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authn_anon.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authn_anon.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authn_anon.so" + if exist .\Debug\mod_authn_anon.so.manifest mt.exe -manifest .\Debug\mod_authn_anon.so.manifest -outputresource:.\Debug\mod_authn_anon.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authn_anon.dep") +!INCLUDE "mod_authn_anon.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authn_anon.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authn_anon - Win32 Release" || "$(CFG)" == "mod_authn_anon - Win32 Debug" + +!IF "$(CFG)" == "mod_authn_anon - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_anon - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_anon - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_anon - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_anon - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_anon - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_anon - Win32 Release" + +"mod_auth_basic - Win32 Release" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" + cd "." + +"mod_auth_basic - Win32 ReleaseCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" RECURSE=1 CLEAN + cd "." + +!ELSEIF "$(CFG)" == "mod_authn_anon - Win32 Debug" + +"mod_auth_basic - Win32 Debug" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" + cd "." + +"mod_auth_basic - Win32 DebugCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" RECURSE=1 CLEAN + cd "." + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authn_anon - Win32 Release" + + +"$(INTDIR)\mod_authn_anon.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authn_anon.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authn_anon.so" /d LONG_NAME="authn_anon_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authn_anon - Win32 Debug" + + +"$(INTDIR)\mod_authn_anon.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authn_anon.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authn_anon.so" /d LONG_NAME="authn_anon_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authn_anon.c + +"$(INTDIR)\mod_authn_anon.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authn_core.c b/modules/aaa/mod_authn_core.c new file mode 100644 index 0000000..f3a494c --- /dev/null +++ b/modules/aaa/mod_authn_core.c @@ -0,0 +1,427 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Security options etc. + * + * Module derived from code originally written by Rob McCool + * + */ + +#include "apr_strings.h" +#include "apr_network_io.h" +#define APR_WANT_STRFUNC +#define APR_WANT_BYTEFUNC +#include "apr_want.h" + +#include "ap_config.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_request.h" +#include "http_protocol.h" +#include "ap_expr.h" +#include "ap_provider.h" + +#include "mod_auth.h" + +#if APR_HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +/* TODO List + +- Track down all of the references to r->ap_auth_type + and change them to ap_auth_type() +- Remove ap_auth_type and ap_auth_name from the + request_rec + +*/ + +typedef struct { + ap_expr_info_t *ap_auth_type; + int auth_type_set; + ap_expr_info_t *ap_auth_name; +} authn_core_dir_conf; + +typedef struct provider_alias_rec { + char *provider_name; + char *provider_alias; + ap_conf_vector_t *sec_auth; + const authn_provider *provider; +} provider_alias_rec; + +typedef struct authn_alias_srv_conf { + apr_hash_t *alias_rec; +} authn_alias_srv_conf; + + +module AP_MODULE_DECLARE_DATA authn_core_module; + +static void *create_authn_core_dir_config(apr_pool_t *p, char *dummy) +{ + authn_core_dir_conf *conf = + (authn_core_dir_conf *)apr_pcalloc(p, sizeof(authn_core_dir_conf)); + + return (void *)conf; +} + +static void *merge_authn_core_dir_config(apr_pool_t *a, void *basev, void *newv) +{ + authn_core_dir_conf *base = (authn_core_dir_conf *)basev; + authn_core_dir_conf *new = (authn_core_dir_conf *)newv; + authn_core_dir_conf *conf = + (authn_core_dir_conf *)apr_pcalloc(a, sizeof(authn_core_dir_conf)); + + if (new->auth_type_set) { + conf->ap_auth_type = new->ap_auth_type; + conf->auth_type_set = 1; + } + else { + conf->ap_auth_type = base->ap_auth_type; + conf->auth_type_set = base->auth_type_set; + } + + if (new->ap_auth_name) { + conf->ap_auth_name = new->ap_auth_name; + } else { + conf->ap_auth_name = base->ap_auth_name; + } + + return (void*)conf; +} + +static authn_status authn_alias_check_password(request_rec *r, const char *user, + const char *password) +{ + /* Look up the provider alias in the alias list */ + /* Get the dir_config and call ap_Merge_per_dir_configs() */ + /* Call the real provider->check_password() function */ + /* return the result of the above function call */ + + const char *provider_name = apr_table_get(r->notes, AUTHN_PROVIDER_NAME_NOTE); + authn_status ret = AUTH_USER_NOT_FOUND; + authn_alias_srv_conf *authcfg = + (authn_alias_srv_conf *)ap_get_module_config(r->server->module_config, + &authn_core_module); + + if (provider_name) { + provider_alias_rec *prvdraliasrec = apr_hash_get(authcfg->alias_rec, + provider_name, APR_HASH_KEY_STRING); + ap_conf_vector_t *orig_dir_config = r->per_dir_config; + + /* If we found the alias provider in the list, then merge the directory + configurations and call the real provider */ + if (prvdraliasrec) { + r->per_dir_config = ap_merge_per_dir_configs(r->pool, orig_dir_config, + prvdraliasrec->sec_auth); + ret = prvdraliasrec->provider->check_password(r,user,password); + r->per_dir_config = orig_dir_config; + } + } + + return ret; +} + +static authn_status authn_alias_get_realm_hash(request_rec *r, const char *user, + const char *realm, char **rethash) +{ + /* Look up the provider alias in the alias list */ + /* Get the dir_config and call ap_Merge_per_dir_configs() */ + /* Call the real provider->get_realm_hash() function */ + /* return the result of the above function call */ + + const char *provider_name = apr_table_get(r->notes, AUTHN_PROVIDER_NAME_NOTE); + authn_status ret = AUTH_USER_NOT_FOUND; + authn_alias_srv_conf *authcfg = + (authn_alias_srv_conf *)ap_get_module_config(r->server->module_config, + &authn_core_module); + + if (provider_name) { + provider_alias_rec *prvdraliasrec = apr_hash_get(authcfg->alias_rec, + provider_name, APR_HASH_KEY_STRING); + ap_conf_vector_t *orig_dir_config = r->per_dir_config; + + /* If we found the alias provider in the list, then merge the directory + configurations and call the real provider */ + if (prvdraliasrec) { + r->per_dir_config = ap_merge_per_dir_configs(r->pool, orig_dir_config, + prvdraliasrec->sec_auth); + ret = prvdraliasrec->provider->get_realm_hash(r,user,realm,rethash); + r->per_dir_config = orig_dir_config; + } + } + + return ret; +} + +static void *create_authn_alias_svr_config(apr_pool_t *p, server_rec *s) +{ + + authn_alias_srv_conf *authcfg; + + authcfg = (authn_alias_srv_conf *) apr_pcalloc(p, sizeof(authn_alias_srv_conf)); + authcfg->alias_rec = apr_hash_make(p); + + return (void *) authcfg; +} + +/* Only per-server directive we have is GLOBAL_ONLY */ +static void *merge_authn_alias_svr_config(apr_pool_t *p, void *basev, void *overridesv) +{ + return basev; +} + +static const authn_provider authn_alias_provider = +{ + &authn_alias_check_password, + &authn_alias_get_realm_hash, +}; + +static const authn_provider authn_alias_provider_nodigest = +{ + &authn_alias_check_password, + NULL, +}; + +static const char *authaliassection(cmd_parms *cmd, void *mconfig, const char *arg) +{ + const char *endp = ap_strrchr_c(arg, '>'); + const char *args; + char *provider_alias; + char *provider_name; + int old_overrides = cmd->override; + const char *errmsg; + const authn_provider *provider = NULL; + ap_conf_vector_t *new_auth_config = ap_create_per_dir_config(cmd->pool); + authn_alias_srv_conf *authcfg = + (authn_alias_srv_conf *)ap_get_module_config(cmd->server->module_config, + &authn_core_module); + + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if (err != NULL) { + return err; + } + + if (endp == NULL) { + return apr_pstrcat(cmd->pool, cmd->cmd->name, + "> directive missing closing '>'", NULL); + } + + args = apr_pstrndup(cmd->temp_pool, arg, endp - arg); + + if (!args[0]) { + return apr_pstrcat(cmd->pool, cmd->cmd->name, + "> directive requires additional arguments", NULL); + } + + /* Pull the real provider name and the alias name from the block header */ + provider_name = ap_getword_conf(cmd->pool, &args); + provider_alias = ap_getword_conf(cmd->pool, &args); + + if (!provider_name[0] || !provider_alias[0]) { + return apr_pstrcat(cmd->pool, cmd->cmd->name, + "> directive requires additional arguments", NULL); + } + + if (strcasecmp(provider_name, provider_alias) == 0) { + return apr_pstrcat(cmd->pool, + "The alias provider name must be different from the base provider name.", NULL); + } + + /* Look up the alias provider to make sure that it hasn't already been registered. */ + provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP, provider_alias, + AUTHN_PROVIDER_VERSION); + if (provider) { + return apr_pstrcat(cmd->pool, "The alias provider ", provider_alias, + " has already be registered previously as either a base provider or an alias provider.", + NULL); + } + + /* walk the subsection configuration to get the per_dir config that we will + merge just before the real provider is called. */ + cmd->override = OR_AUTHCFG | ACCESS_CONF; + errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_auth_config); + cmd->override = old_overrides; + + if (!errmsg) { + provider_alias_rec *prvdraliasrec = apr_pcalloc(cmd->pool, sizeof(provider_alias_rec)); + provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP, provider_name, + AUTHN_PROVIDER_VERSION); + + if (!provider) { + /* by the time they use it, the provider should be loaded and + registered with us. */ + return apr_psprintf(cmd->pool, + "Unknown Authn provider: %s", + provider_name); + } + + /* Save off the new directory config along with the original provider name + and function pointer data */ + prvdraliasrec->sec_auth = new_auth_config; + prvdraliasrec->provider_name = provider_name; + prvdraliasrec->provider_alias = provider_alias; + prvdraliasrec->provider = provider; + apr_hash_set(authcfg->alias_rec, provider_alias, APR_HASH_KEY_STRING, prvdraliasrec); + + /* Register the fake provider so that we get called first */ + ap_register_auth_provider(cmd->pool, AUTHN_PROVIDER_GROUP, + provider_alias, AUTHN_PROVIDER_VERSION, + provider->get_realm_hash ? + &authn_alias_provider : + &authn_alias_provider_nodigest, + AP_AUTH_INTERNAL_PER_CONF); + } + + return errmsg; +} + +/* + * Load an authorisation realm into our location configuration, applying the + * usual rules that apply to realms. + */ +static const char *set_authname(cmd_parms *cmd, void *mconfig, + const char *word1) +{ + authn_core_dir_conf *aconfig = (authn_core_dir_conf *)mconfig; + const char *expr_err = NULL; + + aconfig->ap_auth_name = ap_expr_parse_cmd(cmd, word1, AP_EXPR_FLAG_STRING_RESULT, + &expr_err, NULL); + if (expr_err) { + return apr_pstrcat(cmd->temp_pool, + "Cannot parse expression '", word1, "' in AuthName: ", + expr_err, NULL); + } + + return NULL; +} + +static const char *set_authtype(cmd_parms *cmd, void *mconfig, + const char *word1) +{ + authn_core_dir_conf *aconfig = (authn_core_dir_conf *)mconfig; + const char *expr_err = NULL; + + aconfig->ap_auth_type = ap_expr_parse_cmd(cmd, word1, AP_EXPR_FLAG_STRING_RESULT, + &expr_err, NULL); + if (expr_err) { + return apr_pstrcat(cmd->temp_pool, + "Cannot parse expression '", word1, "' in AuthType: ", + expr_err, NULL); + } + + aconfig->auth_type_set = 1; + + return NULL; +} + +static const char *authn_ap_auth_type(request_rec *r) +{ + authn_core_dir_conf *conf; + + conf = (authn_core_dir_conf *) ap_get_module_config(r->per_dir_config, + &authn_core_module); + + if (conf->ap_auth_type) { + const char *err = NULL, *type; + type = ap_expr_str_exec(r, conf->ap_auth_type, &err); + if (err) { + ap_log_rerror( + APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, APLOGNO(02834) "AuthType expression could not be evaluated: %s", err); + return NULL; + } + + return strcasecmp(type, "None") ? type : NULL; + } + + return NULL; +} + +static const char *authn_ap_auth_name(request_rec *r) +{ + authn_core_dir_conf *conf; + const char *err = NULL, *name; + + conf = (authn_core_dir_conf *) ap_get_module_config(r->per_dir_config, + &authn_core_module); + + if (conf->ap_auth_name) { + name = ap_expr_str_exec(r, conf->ap_auth_name, &err); + if (err) { + ap_log_rerror( + APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, APLOGNO(02835) "AuthName expression could not be evaluated: %s", err); + return NULL; + } + + return ap_escape_quotes(r->pool, name); + } + + return NULL; +} + +static const command_rec authn_cmds[] = +{ + AP_INIT_TAKE1("AuthType", set_authtype, NULL, OR_AUTHCFG, + "an HTTP authorization type (e.g., \"Basic\")"), + AP_INIT_TAKE1("AuthName", set_authname, NULL, OR_AUTHCFG, + "the authentication realm (e.g. \"Members Only\")"), + AP_INIT_RAW_ARGS("<AuthnProviderAlias", authaliassection, NULL, RSRC_CONF, + "container for grouping an authentication provider's " + "directives under a provider alias"), + {NULL} +}; + +static int authenticate_no_user(request_rec *r) +{ + /* if there isn't an AuthType, then assume that no authentication + is required so return OK */ + if (!ap_auth_type(r)) { + return OK; + } + + /* there's an AuthType configured, but no authentication module + * loaded to support it + */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, APLOGNO(01796) + "AuthType %s configured without corresponding module", + ap_auth_type(r)); + + return HTTP_INTERNAL_SERVER_ERROR; +} + +static void register_hooks(apr_pool_t *p) +{ + APR_REGISTER_OPTIONAL_FN(authn_ap_auth_type); + APR_REGISTER_OPTIONAL_FN(authn_ap_auth_name); + + ap_hook_check_authn(authenticate_no_user, NULL, NULL, APR_HOOK_LAST, + AP_AUTH_INTERNAL_PER_CONF); +} + +AP_DECLARE_MODULE(authn_core) = +{ + STANDARD20_MODULE_STUFF, + create_authn_core_dir_config, /* dir config creater */ + merge_authn_core_dir_config, /* dir merger --- default is to override */ + create_authn_alias_svr_config, /* server config */ + merge_authn_alias_svr_config, /* merge server config */ + authn_cmds, + register_hooks /* register hooks */ +}; + diff --git a/modules/aaa/mod_authn_core.dep b/modules/aaa/mod_authn_core.dep new file mode 100644 index 0000000..18003b3 --- /dev/null +++ b/modules/aaa/mod_authn_core.dep @@ -0,0 +1,58 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authn_core.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authn_core.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_authn_core.dsp b/modules/aaa/mod_authn_core.dsp new file mode 100644 index 0000000..506c96e --- /dev/null +++ b/modules/aaa/mod_authn_core.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_authn_core" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authn_core - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_core.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_core.mak" CFG="mod_authn_core - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authn_core - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authn_core - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authn_core - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_authn_core_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authn_core.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authn_core.so" /d LONG_NAME="authn_core_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authn_core.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_core.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authn_core.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_core.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authn_core.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authn_core - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_authn_core_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authn_core.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authn_core.so" /d LONG_NAME="authn_core_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authn_core.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_core.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authn_core.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_core.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authn_core.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authn_core - Win32 Release" +# Name "mod_authn_core - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_authn_core.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authn_core.mak b/modules/aaa/mod_authn_core.mak new file mode 100644 index 0000000..ec88b2d --- /dev/null +++ b/modules/aaa/mod_authn_core.mak @@ -0,0 +1,381 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authn_core.dsp +!IF "$(CFG)" == "" +CFG=mod_authn_core - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_authn_core - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_authn_core - Win32 Release" && "$(CFG)" != "mod_authn_core - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_core.mak" CFG="mod_authn_core - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authn_core - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authn_core - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authn_core - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authn_core.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Release" "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authn_core.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" "mod_auth_basic - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authn_core.obj" + -@erase "$(INTDIR)\mod_authn_core.res" + -@erase "$(INTDIR)\mod_authn_core_src.idb" + -@erase "$(INTDIR)\mod_authn_core_src.pdb" + -@erase "$(OUTDIR)\mod_authn_core.exp" + -@erase "$(OUTDIR)\mod_authn_core.lib" + -@erase "$(OUTDIR)\mod_authn_core.pdb" + -@erase "$(OUTDIR)\mod_authn_core.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authn_core_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authn_core.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authn_core.so" /d LONG_NAME="authn_core_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authn_core.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authn_core.pdb" /debug /out:"$(OUTDIR)\mod_authn_core.so" /implib:"$(OUTDIR)\mod_authn_core.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_core.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authn_core.obj" \ + "$(INTDIR)\mod_authn_core.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authn_core.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authn_core.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authn_core.so" + if exist .\Release\mod_authn_core.so.manifest mt.exe -manifest .\Release\mod_authn_core.so.manifest -outputresource:.\Release\mod_authn_core.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authn_core - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authn_core.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Debug" "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authn_core.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" "mod_auth_basic - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authn_core.obj" + -@erase "$(INTDIR)\mod_authn_core.res" + -@erase "$(INTDIR)\mod_authn_core_src.idb" + -@erase "$(INTDIR)\mod_authn_core_src.pdb" + -@erase "$(OUTDIR)\mod_authn_core.exp" + -@erase "$(OUTDIR)\mod_authn_core.lib" + -@erase "$(OUTDIR)\mod_authn_core.pdb" + -@erase "$(OUTDIR)\mod_authn_core.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authn_core_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authn_core.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authn_core.so" /d LONG_NAME="authn_core_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authn_core.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authn_core.pdb" /debug /out:"$(OUTDIR)\mod_authn_core.so" /implib:"$(OUTDIR)\mod_authn_core.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_core.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authn_core.obj" \ + "$(INTDIR)\mod_authn_core.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authn_core.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authn_core.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authn_core.so" + if exist .\Debug\mod_authn_core.so.manifest mt.exe -manifest .\Debug\mod_authn_core.so.manifest -outputresource:.\Debug\mod_authn_core.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authn_core.dep") +!INCLUDE "mod_authn_core.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authn_core.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authn_core - Win32 Release" || "$(CFG)" == "mod_authn_core - Win32 Debug" + +!IF "$(CFG)" == "mod_authn_core - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_core - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_core - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_core - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_core - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_core - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_core - Win32 Release" + +"mod_auth_basic - Win32 Release" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" + cd "." + +"mod_auth_basic - Win32 ReleaseCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" RECURSE=1 CLEAN + cd "." + +!ELSEIF "$(CFG)" == "mod_authn_core - Win32 Debug" + +"mod_auth_basic - Win32 Debug" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" + cd "." + +"mod_auth_basic - Win32 DebugCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" RECURSE=1 CLEAN + cd "." + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authn_core - Win32 Release" + + +"$(INTDIR)\mod_authn_core.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authn_core.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authn_core.so" /d LONG_NAME="authn_core_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authn_core - Win32 Debug" + + +"$(INTDIR)\mod_authn_core.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authn_core.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authn_core.so" /d LONG_NAME="authn_core_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authn_core.c + +"$(INTDIR)\mod_authn_core.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authn_dbd.c b/modules/aaa/mod_authn_dbd.c new file mode 100644 index 0000000..08e5993 --- /dev/null +++ b/modules/aaa/mod_authn_dbd.c @@ -0,0 +1,307 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ap_provider.h" +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" +#include "http_request.h" +#include "apr_lib.h" +#include "apr_dbd.h" +#include "mod_dbd.h" +#include "apr_strings.h" +#include "mod_auth.h" +#include "apr_md5.h" +#include "apu_version.h" + +module AP_MODULE_DECLARE_DATA authn_dbd_module; + +typedef struct { + const char *user; + const char *realm; +} authn_dbd_conf; + +/* optional function - look it up once in post_config */ +static ap_dbd_t *(*authn_dbd_acquire_fn)(request_rec*) = NULL; +static void (*authn_dbd_prepare_fn)(server_rec*, const char*, const char*) = NULL; +static APR_OPTIONAL_FN_TYPE(ap_authn_cache_store) *authn_cache_store = NULL; +#define AUTHN_CACHE_STORE(r,user,realm,data) \ + if (authn_cache_store != NULL) \ + authn_cache_store((r), "dbd", (user), (realm), (data)) + +static void *authn_dbd_cr_conf(apr_pool_t *pool, char *dummy) +{ + authn_dbd_conf *ret = apr_pcalloc(pool, sizeof(authn_dbd_conf)); + return ret; +} + +static void *authn_dbd_merge_conf(apr_pool_t *pool, void *BASE, void *ADD) +{ + authn_dbd_conf *add = ADD; + authn_dbd_conf *base = BASE; + authn_dbd_conf *ret = apr_palloc(pool, sizeof(authn_dbd_conf)); + ret->user = (add->user == NULL) ? base->user : add->user; + ret->realm = (add->realm == NULL) ? base->realm : add->realm; + return ret; +} + +static const char *authn_dbd_prepare(cmd_parms *cmd, void *cfg, const char *query) +{ + static unsigned int label_num = 0; + char *label; + const char *err = ap_check_cmd_context(cmd, NOT_IN_HTACCESS); + if (err) + return err; + + if (authn_dbd_prepare_fn == NULL) { + authn_dbd_prepare_fn = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_prepare); + if (authn_dbd_prepare_fn == NULL) { + return "You must load mod_dbd to enable AuthDBD functions"; + } + authn_dbd_acquire_fn = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_acquire); + } + label = apr_psprintf(cmd->pool, "authn_dbd_%d", ++label_num); + + authn_dbd_prepare_fn(cmd->server, query, label); + + /* save the label here for our own use */ + return ap_set_string_slot(cmd, cfg, label); +} + +static const command_rec authn_dbd_cmds[] = +{ + AP_INIT_TAKE1("AuthDBDUserPWQuery", authn_dbd_prepare, + (void *)APR_OFFSETOF(authn_dbd_conf, user), ACCESS_CONF, + "Query used to fetch password for user"), + AP_INIT_TAKE1("AuthDBDUserRealmQuery", authn_dbd_prepare, + (void *)APR_OFFSETOF(authn_dbd_conf, realm), ACCESS_CONF, + "Query used to fetch password for user+realm"), + {NULL} +}; + +static authn_status authn_dbd_password(request_rec *r, const char *user, + const char *password) +{ + apr_status_t rv; + const char *dbd_password = NULL; + apr_dbd_prepared_t *statement; + apr_dbd_results_t *res = NULL; + apr_dbd_row_t *row = NULL; + int ret; + + authn_dbd_conf *conf = ap_get_module_config(r->per_dir_config, + &authn_dbd_module); + ap_dbd_t *dbd = authn_dbd_acquire_fn(r); + if (dbd == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01653) + "Failed to acquire database connection to look up " + "user '%s'", user); + return AUTH_GENERAL_ERROR; + } + + if (conf->user == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01654) + "No AuthDBDUserPWQuery has been specified"); + return AUTH_GENERAL_ERROR; + } + + statement = apr_hash_get(dbd->prepared, conf->user, APR_HASH_KEY_STRING); + if (statement == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01655) + "A prepared statement could not be found for " + "AuthDBDUserPWQuery with the key '%s'", conf->user); + return AUTH_GENERAL_ERROR; + } + if ((ret = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res, + statement, 0, user, NULL)) != 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01656) + "Query execution error looking up '%s' " + "in database [%s]", + user, apr_dbd_error(dbd->driver, dbd->handle, ret)); + return AUTH_GENERAL_ERROR; + } + for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1); + rv != -1; + rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) { + if (rv != 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01657) + "Error retrieving results while looking up '%s' " + "in database", user); + return AUTH_GENERAL_ERROR; + } + if (dbd_password == NULL) { + /* add the rest of the columns to the environment */ + int i = 1; + const char *name; + for (name = apr_dbd_get_name(dbd->driver, res, i); + name != NULL; + name = apr_dbd_get_name(dbd->driver, res, i)) { + + char *str = apr_pstrcat(r->pool, AUTHN_PREFIX, + name, + NULL); + int j = sizeof(AUTHN_PREFIX)-1; /* string length of "AUTHENTICATE_", excluding the trailing NIL */ + while (str[j]) { + if (!apr_isalnum(str[j])) { + str[j] = '_'; + } + else { + str[j] = apr_toupper(str[j]); + } + j++; + } + apr_table_set(r->subprocess_env, str, + apr_dbd_get_entry(dbd->driver, row, i)); + i++; + } + + dbd_password = apr_pstrdup(r->pool, + apr_dbd_get_entry(dbd->driver, row, 0)); + } + /* we can't break out here or row won't get cleaned up */ + } + + if (!dbd_password) { + return AUTH_USER_NOT_FOUND; + } + AUTHN_CACHE_STORE(r, user, NULL, dbd_password); + + rv = apr_password_validate(password, dbd_password); + + if (rv != APR_SUCCESS) { + return AUTH_DENIED; + } + + return AUTH_GRANTED; +} + +static authn_status authn_dbd_realm(request_rec *r, const char *user, + const char *realm, char **rethash) +{ + apr_status_t rv; + const char *dbd_hash = NULL; + apr_dbd_prepared_t *statement; + apr_dbd_results_t *res = NULL; + apr_dbd_row_t *row = NULL; + int ret; + + authn_dbd_conf *conf = ap_get_module_config(r->per_dir_config, + &authn_dbd_module); + ap_dbd_t *dbd = authn_dbd_acquire_fn(r); + if (dbd == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01658) + "Failed to acquire database connection to look up " + "user '%s:%s'", user, realm); + return AUTH_GENERAL_ERROR; + } + if (conf->realm == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01659) + "No AuthDBDUserRealmQuery has been specified"); + return AUTH_GENERAL_ERROR; + } + statement = apr_hash_get(dbd->prepared, conf->realm, APR_HASH_KEY_STRING); + if (statement == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01660) + "A prepared statement could not be found for " + "AuthDBDUserRealmQuery with the key '%s'", conf->realm); + return AUTH_GENERAL_ERROR; + } + if ((ret = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res, + statement, 0, user, realm, NULL)) != 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01661) + "Query execution error looking up '%s:%s' " + "in database [%s]", + user, realm, + apr_dbd_error(dbd->driver, dbd->handle, ret)); + return AUTH_GENERAL_ERROR; + } + for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1); + rv != -1; + rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) { + if (rv != 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01662) + "Error retrieving results while looking up '%s:%s' " + "in database", user, realm); + return AUTH_GENERAL_ERROR; + } + if (dbd_hash == NULL) { + /* add the rest of the columns to the environment */ + int i = 1; + const char *name; + for (name = apr_dbd_get_name(dbd->driver, res, i); + name != NULL; + name = apr_dbd_get_name(dbd->driver, res, i)) { + + char *str = apr_pstrcat(r->pool, AUTHN_PREFIX, + name, + NULL); + int j = sizeof(AUTHN_PREFIX)-1; /* string length of "AUTHENTICATE_", excluding the trailing NIL */ + while (str[j]) { + if (!apr_isalnum(str[j])) { + str[j] = '_'; + } + else { + str[j] = apr_toupper(str[j]); + } + j++; + } + apr_table_set(r->subprocess_env, str, + apr_dbd_get_entry(dbd->driver, row, i)); + i++; + } + + dbd_hash = apr_pstrdup(r->pool, + apr_dbd_get_entry(dbd->driver, row, 0)); + } + /* we can't break out here or row won't get cleaned up */ + } + + if (!dbd_hash) { + return AUTH_USER_NOT_FOUND; + } + AUTHN_CACHE_STORE(r, user, realm, dbd_hash); + *rethash = apr_pstrdup(r->pool, dbd_hash); + return AUTH_USER_FOUND; +} + +static void opt_retr(void) +{ + authn_cache_store = APR_RETRIEVE_OPTIONAL_FN(ap_authn_cache_store); +} + +static void authn_dbd_hooks(apr_pool_t *p) +{ + static const authn_provider authn_dbd_provider = { + &authn_dbd_password, + &authn_dbd_realm + }; + + ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "dbd", + AUTHN_PROVIDER_VERSION, + &authn_dbd_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_hook_optional_fn_retrieve(opt_retr, NULL, NULL, APR_HOOK_MIDDLE); +} + +AP_DECLARE_MODULE(authn_dbd) = +{ + STANDARD20_MODULE_STUFF, + authn_dbd_cr_conf, + authn_dbd_merge_conf, + NULL, + NULL, + authn_dbd_cmds, + authn_dbd_hooks +}; diff --git a/modules/aaa/mod_authn_dbd.dep b/modules/aaa/mod_authn_dbd.dep new file mode 100644 index 0000000..257ee49 --- /dev/null +++ b/modules/aaa/mod_authn_dbd.dep @@ -0,0 +1,56 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authn_dbd.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authn_dbd.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_dbd.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_md5.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apr_xlate.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr-util\include\apu_version.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_lib.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_version.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_authn_dbd.dsp b/modules/aaa/mod_authn_dbd.dsp new file mode 100644 index 0000000..9094d33 --- /dev/null +++ b/modules/aaa/mod_authn_dbd.dsp @@ -0,0 +1,115 @@ +# Microsoft Developer Studio Project File - Name="mod_authn_dbd" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authn_dbd - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_dbd.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_dbd.mak" CFG="mod_authn_dbd - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authn_dbd - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authn_dbd - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authn_dbd - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I ../database /D DBD_DECLARE_EXPORT /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_authn_dbd_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authn_dbd.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authn_dbd.so" /d LONG_NAME="authn_dbd_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authn_dbd.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_dbd.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authn_dbd.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_dbd.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authn_dbd.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authn_dbd - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I ../database /D DBD_DECLARE_EXPORT /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_authn_dbd_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authn_dbd.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authn_dbd.so" /d LONG_NAME="authn_dbd_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authn_dbd.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_dbd.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authn_dbd.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_dbd.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authn_dbd.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authn_dbd - Win32 Release" +# Name "mod_authn_dbd - Win32 Debug" +# Begin Source File + +SOURCE=..\database\mod_dbd.h +# End Source File +# Begin Source File + +SOURCE=.\mod_authn_dbd.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authn_dbd.mak b/modules/aaa/mod_authn_dbd.mak new file mode 100644 index 0000000..9c983dc --- /dev/null +++ b/modules/aaa/mod_authn_dbd.mak @@ -0,0 +1,409 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authn_dbd.dsp +!IF "$(CFG)" == "" +CFG=mod_authn_dbd - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_authn_dbd - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_authn_dbd - Win32 Release" && "$(CFG)" != "mod_authn_dbd - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_dbd.mak" CFG="mod_authn_dbd - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authn_dbd - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authn_dbd - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authn_dbd - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authn_dbd.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_dbd - Win32 Release" "mod_auth_basic - Win32 Release" "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authn_dbd.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" "mod_auth_basic - Win32 ReleaseCLEAN" "mod_dbd - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authn_dbd.obj" + -@erase "$(INTDIR)\mod_authn_dbd.res" + -@erase "$(INTDIR)\mod_authn_dbd_src.idb" + -@erase "$(INTDIR)\mod_authn_dbd_src.pdb" + -@erase "$(OUTDIR)\mod_authn_dbd.exp" + -@erase "$(OUTDIR)\mod_authn_dbd.lib" + -@erase "$(OUTDIR)\mod_authn_dbd.pdb" + -@erase "$(OUTDIR)\mod_authn_dbd.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "DBD_DECLARE_EXPORT" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authn_dbd_src" /FD /I ../database /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authn_dbd.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authn_dbd.so" /d LONG_NAME="authn_dbd_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authn_dbd.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authn_dbd.pdb" /debug /out:"$(OUTDIR)\mod_authn_dbd.so" /implib:"$(OUTDIR)\mod_authn_dbd.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_dbd.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authn_dbd.obj" \ + "$(INTDIR)\mod_authn_dbd.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" \ + "..\database\Release\mod_dbd.lib" + +"$(OUTDIR)\mod_authn_dbd.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authn_dbd.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authn_dbd.so" + if exist .\Release\mod_authn_dbd.so.manifest mt.exe -manifest .\Release\mod_authn_dbd.so.manifest -outputresource:.\Release\mod_authn_dbd.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authn_dbd - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authn_dbd.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_dbd - Win32 Debug" "mod_auth_basic - Win32 Debug" "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authn_dbd.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" "mod_auth_basic - Win32 DebugCLEAN" "mod_dbd - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authn_dbd.obj" + -@erase "$(INTDIR)\mod_authn_dbd.res" + -@erase "$(INTDIR)\mod_authn_dbd_src.idb" + -@erase "$(INTDIR)\mod_authn_dbd_src.pdb" + -@erase "$(OUTDIR)\mod_authn_dbd.exp" + -@erase "$(OUTDIR)\mod_authn_dbd.lib" + -@erase "$(OUTDIR)\mod_authn_dbd.pdb" + -@erase "$(OUTDIR)\mod_authn_dbd.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "DBD_DECLARE_EXPORT" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authn_dbd_src" /FD /EHsc /I ../database /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authn_dbd.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authn_dbd.so" /d LONG_NAME="authn_dbd_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authn_dbd.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authn_dbd.pdb" /debug /out:"$(OUTDIR)\mod_authn_dbd.so" /implib:"$(OUTDIR)\mod_authn_dbd.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_dbd.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authn_dbd.obj" \ + "$(INTDIR)\mod_authn_dbd.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" \ + "..\database\Debug\mod_dbd.lib" + +"$(OUTDIR)\mod_authn_dbd.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authn_dbd.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authn_dbd.so" + if exist .\Debug\mod_authn_dbd.so.manifest mt.exe -manifest .\Debug\mod_authn_dbd.so.manifest -outputresource:.\Debug\mod_authn_dbd.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authn_dbd.dep") +!INCLUDE "mod_authn_dbd.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authn_dbd.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authn_dbd - Win32 Release" || "$(CFG)" == "mod_authn_dbd - Win32 Debug" + +!IF "$(CFG)" == "mod_authn_dbd - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_dbd - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_dbd - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_dbd - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_dbd - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_dbd - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_dbd - Win32 Release" + +"mod_auth_basic - Win32 Release" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" + cd "." + +"mod_auth_basic - Win32 ReleaseCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" RECURSE=1 CLEAN + cd "." + +!ELSEIF "$(CFG)" == "mod_authn_dbd - Win32 Debug" + +"mod_auth_basic - Win32 Debug" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" + cd "." + +"mod_auth_basic - Win32 DebugCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" RECURSE=1 CLEAN + cd "." + +!ENDIF + +!IF "$(CFG)" == "mod_authn_dbd - Win32 Release" + +"mod_dbd - Win32 Release" : + cd ".\..\database" + $(MAKE) /$(MAKEFLAGS) /F ".\mod_dbd.mak" CFG="mod_dbd - Win32 Release" + cd "..\aaa" + +"mod_dbd - Win32 ReleaseCLEAN" : + cd ".\..\database" + $(MAKE) /$(MAKEFLAGS) /F ".\mod_dbd.mak" CFG="mod_dbd - Win32 Release" RECURSE=1 CLEAN + cd "..\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_dbd - Win32 Debug" + +"mod_dbd - Win32 Debug" : + cd ".\..\database" + $(MAKE) /$(MAKEFLAGS) /F ".\mod_dbd.mak" CFG="mod_dbd - Win32 Debug" + cd "..\aaa" + +"mod_dbd - Win32 DebugCLEAN" : + cd ".\..\database" + $(MAKE) /$(MAKEFLAGS) /F ".\mod_dbd.mak" CFG="mod_dbd - Win32 Debug" RECURSE=1 CLEAN + cd "..\aaa" + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authn_dbd - Win32 Release" + + +"$(INTDIR)\mod_authn_dbd.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authn_dbd.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authn_dbd.so" /d LONG_NAME="authn_dbd_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authn_dbd - Win32 Debug" + + +"$(INTDIR)\mod_authn_dbd.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authn_dbd.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authn_dbd.so" /d LONG_NAME="authn_dbd_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authn_dbd.c + +"$(INTDIR)\mod_authn_dbd.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authn_dbm.c b/modules/aaa/mod_authn_dbm.c new file mode 100644 index 0000000..9f47350 --- /dev/null +++ b/modules/aaa/mod_authn_dbm.c @@ -0,0 +1,231 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * http_auth: authentication + * + * Rob McCool & Brian Behlendorf. + * + * Adapted to Apache by rst. + * + */ + +#define APR_WANT_STRFUNC +#include "apr_want.h" +#include "apr_strings.h" +#include "apr_dbm.h" +#include "apr_md5.h" /* for apr_password_validate */ + +#include "ap_provider.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" /* for ap_hook_(check_user_id | auth_checker)*/ + +#include "mod_auth.h" + +#include "apr_version.h" +#if !APR_VERSION_AT_LEAST(2,0,0) +#include "apu_version.h" +#endif + +static APR_OPTIONAL_FN_TYPE(ap_authn_cache_store) *authn_cache_store = NULL; +#define AUTHN_CACHE_STORE(r,user,realm,data) \ + if (authn_cache_store != NULL) \ + authn_cache_store((r), "dbm", (user), (realm), (data)) + +typedef struct { + const char *pwfile; + const char *dbmtype; +} authn_dbm_config_rec; + +static void *create_authn_dbm_dir_config(apr_pool_t *p, char *d) +{ + authn_dbm_config_rec *conf = apr_palloc(p, sizeof(*conf)); + + conf->pwfile = NULL; + conf->dbmtype = "default"; + + return conf; +} + +static const command_rec authn_dbm_cmds[] = +{ + AP_INIT_TAKE1("AuthDBMUserFile", ap_set_file_slot, + (void *)APR_OFFSETOF(authn_dbm_config_rec, pwfile), + OR_AUTHCFG, "dbm database file containing user IDs and passwords"), + AP_INIT_TAKE1("AuthDBMType", ap_set_string_slot, + (void *)APR_OFFSETOF(authn_dbm_config_rec, dbmtype), + OR_AUTHCFG, "what type of DBM file the user file is"), + {NULL} +}; + +module AP_MODULE_DECLARE_DATA authn_dbm_module; + +static apr_status_t fetch_dbm_value(request_rec *r, const char *dbmtype, + const char *dbmfile, + const char *user, char **value) +{ +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + const apr_dbm_driver_t *driver; + const apu_err_t *err; +#endif + apr_dbm_t *f; + apr_datum_t key, val; + apr_status_t rv; + +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + rv = apr_dbm_get_driver(&driver, dbmtype, &err, r->pool); + + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(10284) + "could not load '%s' dbm library: %s", + err->reason, err->msg); + return rv; + } + + rv = apr_dbm_open2(&f, driver, dbmfile, APR_DBM_READONLY, + APR_OS_DEFAULT, r->pool); +#else + rv = apr_dbm_open_ex(&f, dbmtype, dbmfile, APR_DBM_READONLY, + APR_OS_DEFAULT, r->pool); +#endif + + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(10285) + "could not open dbm (type %s) file: %s", + dbmtype, dbmfile); + return rv; + } + + key.dptr = (char*)user; +#ifndef NETSCAPE_DBM_COMPAT + key.dsize = strlen(key.dptr); +#else + key.dsize = strlen(key.dptr) + 1; +#endif + + *value = NULL; + + if (apr_dbm_fetch(f, key, &val) == APR_SUCCESS && val.dptr) { + *value = apr_pstrmemdup(r->pool, val.dptr, val.dsize); + } + + apr_dbm_close(f); + + /* NOT FOUND is not an error case; this is indicated by a NULL result. + * Treat all NULL lookup/error results as success for the simple case + * of auth credential lookup, these are DECLINED in both cases. + */ + return APR_SUCCESS; +} + +static authn_status check_dbm_pw(request_rec *r, const char *user, + const char *password) +{ + authn_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config, + &authn_dbm_module); + apr_status_t rv; + char *dbm_password; + char *colon_pw; + + rv = fetch_dbm_value(r, conf->dbmtype, conf->pwfile, user, &dbm_password); + + if (rv != APR_SUCCESS) { + return AUTH_GENERAL_ERROR; + } + + if (!dbm_password) { + return AUTH_USER_NOT_FOUND; + } + + colon_pw = ap_strchr(dbm_password, ':'); + if (colon_pw) { + *colon_pw = '\0'; + } + AUTHN_CACHE_STORE(r, user, NULL, dbm_password); + + rv = apr_password_validate(password, dbm_password); + + if (rv != APR_SUCCESS) { + return AUTH_DENIED; + } + + return AUTH_GRANTED; +} + +static authn_status get_dbm_realm_hash(request_rec *r, const char *user, + const char *realm, char **rethash) +{ + authn_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config, + &authn_dbm_module); + apr_status_t rv; + char *dbm_hash; + char *colon_hash; + + rv = fetch_dbm_value(r, conf->dbmtype, conf->pwfile, + apr_pstrcat(r->pool, user, ":", realm, NULL), + &dbm_hash); + + if (rv != APR_SUCCESS) { + return AUTH_GENERAL_ERROR; + } + + if (!dbm_hash) { + return AUTH_USER_NOT_FOUND; + } + + colon_hash = ap_strchr(dbm_hash, ':'); + if (colon_hash) { + *colon_hash = '\0'; + } + + *rethash = dbm_hash; + AUTHN_CACHE_STORE(r, user, realm, dbm_hash); + + return AUTH_USER_FOUND; +} + +static const authn_provider authn_dbm_provider = +{ + &check_dbm_pw, + &get_dbm_realm_hash, +}; + +static void opt_retr(void) +{ + authn_cache_store = APR_RETRIEVE_OPTIONAL_FN(ap_authn_cache_store); +} +static void register_hooks(apr_pool_t *p) +{ + ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "dbm", + AUTHN_PROVIDER_VERSION, + &authn_dbm_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_hook_optional_fn_retrieve(opt_retr, NULL, NULL, APR_HOOK_MIDDLE); +} + +AP_DECLARE_MODULE(authn_dbm) = +{ + STANDARD20_MODULE_STUFF, + create_authn_dbm_dir_config, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + authn_dbm_cmds, /* command apr_table_t */ + register_hooks /* register hooks */ +}; diff --git a/modules/aaa/mod_authn_dbm.dep b/modules/aaa/mod_authn_dbm.dep new file mode 100644 index 0000000..2239b12 --- /dev/null +++ b/modules/aaa/mod_authn_dbm.dep @@ -0,0 +1,61 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authn_dbm.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authn_dbm.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_dbm.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_md5.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apr_xlate.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_authn_dbm.dsp b/modules/aaa/mod_authn_dbm.dsp new file mode 100644 index 0000000..f2c3ff8 --- /dev/null +++ b/modules/aaa/mod_authn_dbm.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_authn_dbm" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authn_dbm - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_dbm.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_dbm.mak" CFG="mod_authn_dbm - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authn_dbm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authn_dbm - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authn_dbm - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_authn_dbm_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authn_dbm.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authn_dbm.so" /d LONG_NAME="authn_dbm_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authn_dbm.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_dbm.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authn_dbm.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_dbm.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authn_dbm.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authn_dbm - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_authn_dbm_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authn_dbm.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authn_dbm.so" /d LONG_NAME="authn_dbm_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authn_dbm.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_dbm.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authn_dbm.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_dbm.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authn_dbm.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authn_dbm - Win32 Release" +# Name "mod_authn_dbm - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_authn_dbm.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authn_dbm.mak b/modules/aaa/mod_authn_dbm.mak new file mode 100644 index 0000000..e15242a --- /dev/null +++ b/modules/aaa/mod_authn_dbm.mak @@ -0,0 +1,381 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authn_dbm.dsp +!IF "$(CFG)" == "" +CFG=mod_authn_dbm - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_authn_dbm - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_authn_dbm - Win32 Release" && "$(CFG)" != "mod_authn_dbm - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_dbm.mak" CFG="mod_authn_dbm - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authn_dbm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authn_dbm - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authn_dbm - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authn_dbm.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Release" "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authn_dbm.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" "mod_auth_basic - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authn_dbm.obj" + -@erase "$(INTDIR)\mod_authn_dbm.res" + -@erase "$(INTDIR)\mod_authn_dbm_src.idb" + -@erase "$(INTDIR)\mod_authn_dbm_src.pdb" + -@erase "$(OUTDIR)\mod_authn_dbm.exp" + -@erase "$(OUTDIR)\mod_authn_dbm.lib" + -@erase "$(OUTDIR)\mod_authn_dbm.pdb" + -@erase "$(OUTDIR)\mod_authn_dbm.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authn_dbm_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authn_dbm.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authn_dbm.so" /d LONG_NAME="authn_dbm_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authn_dbm.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authn_dbm.pdb" /debug /out:"$(OUTDIR)\mod_authn_dbm.so" /implib:"$(OUTDIR)\mod_authn_dbm.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_dbm.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authn_dbm.obj" \ + "$(INTDIR)\mod_authn_dbm.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authn_dbm.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authn_dbm.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authn_dbm.so" + if exist .\Release\mod_authn_dbm.so.manifest mt.exe -manifest .\Release\mod_authn_dbm.so.manifest -outputresource:.\Release\mod_authn_dbm.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authn_dbm - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authn_dbm.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Debug" "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authn_dbm.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" "mod_auth_basic - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authn_dbm.obj" + -@erase "$(INTDIR)\mod_authn_dbm.res" + -@erase "$(INTDIR)\mod_authn_dbm_src.idb" + -@erase "$(INTDIR)\mod_authn_dbm_src.pdb" + -@erase "$(OUTDIR)\mod_authn_dbm.exp" + -@erase "$(OUTDIR)\mod_authn_dbm.lib" + -@erase "$(OUTDIR)\mod_authn_dbm.pdb" + -@erase "$(OUTDIR)\mod_authn_dbm.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authn_dbm_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authn_dbm.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authn_dbm.so" /d LONG_NAME="authn_dbm_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authn_dbm.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authn_dbm.pdb" /debug /out:"$(OUTDIR)\mod_authn_dbm.so" /implib:"$(OUTDIR)\mod_authn_dbm.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_dbm.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authn_dbm.obj" \ + "$(INTDIR)\mod_authn_dbm.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authn_dbm.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authn_dbm.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authn_dbm.so" + if exist .\Debug\mod_authn_dbm.so.manifest mt.exe -manifest .\Debug\mod_authn_dbm.so.manifest -outputresource:.\Debug\mod_authn_dbm.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authn_dbm.dep") +!INCLUDE "mod_authn_dbm.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authn_dbm.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authn_dbm - Win32 Release" || "$(CFG)" == "mod_authn_dbm - Win32 Debug" + +!IF "$(CFG)" == "mod_authn_dbm - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_dbm - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_dbm - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_dbm - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_dbm - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_dbm - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_dbm - Win32 Release" + +"mod_auth_basic - Win32 Release" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" + cd "." + +"mod_auth_basic - Win32 ReleaseCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" RECURSE=1 CLEAN + cd "." + +!ELSEIF "$(CFG)" == "mod_authn_dbm - Win32 Debug" + +"mod_auth_basic - Win32 Debug" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" + cd "." + +"mod_auth_basic - Win32 DebugCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" RECURSE=1 CLEAN + cd "." + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authn_dbm - Win32 Release" + + +"$(INTDIR)\mod_authn_dbm.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authn_dbm.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authn_dbm.so" /d LONG_NAME="authn_dbm_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authn_dbm - Win32 Debug" + + +"$(INTDIR)\mod_authn_dbm.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authn_dbm.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authn_dbm.so" /d LONG_NAME="authn_dbm_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authn_dbm.c + +"$(INTDIR)\mod_authn_dbm.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authn_file.c b/modules/aaa/mod_authn_file.c new file mode 100644 index 0000000..9909e44 --- /dev/null +++ b/modules/aaa/mod_authn_file.c @@ -0,0 +1,194 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_strings.h" +#include "apr_md5.h" /* for apr_password_validate */ + +#include "ap_config.h" +#include "ap_provider.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" + +#include "mod_auth.h" + +typedef struct { + char *pwfile; +} authn_file_config_rec; + +static APR_OPTIONAL_FN_TYPE(ap_authn_cache_store) *authn_cache_store = NULL; +#define AUTHN_CACHE_STORE(r,user,realm,data) \ + if (authn_cache_store != NULL) \ + authn_cache_store((r), "file", (user), (realm), (data)) + +static void *create_authn_file_dir_config(apr_pool_t *p, char *d) +{ + authn_file_config_rec *conf = apr_palloc(p, sizeof(*conf)); + + conf->pwfile = NULL; /* just to illustrate the default really */ + return conf; +} + +static const command_rec authn_file_cmds[] = +{ + AP_INIT_TAKE1("AuthUserFile", ap_set_file_slot, + (void *)APR_OFFSETOF(authn_file_config_rec, pwfile), + OR_AUTHCFG, "text file containing user IDs and passwords"), + {NULL} +}; + +module AP_MODULE_DECLARE_DATA authn_file_module; + +static authn_status check_password(request_rec *r, const char *user, + const char *password) +{ + authn_file_config_rec *conf = ap_get_module_config(r->per_dir_config, + &authn_file_module); + ap_configfile_t *f; + char l[MAX_STRING_LEN]; + apr_status_t status; + char *file_password = NULL; + + if (!conf->pwfile) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01619) + "AuthUserFile not specified in the configuration"); + return AUTH_GENERAL_ERROR; + } + + status = ap_pcfg_openfile(&f, r->pool, conf->pwfile); + + if (status != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01620) + "Could not open password file: %s", conf->pwfile); + return AUTH_GENERAL_ERROR; + } + + while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) { + const char *rpw, *w; + + /* Skip # or blank lines. */ + if ((l[0] == '#') || (!l[0])) { + continue; + } + + rpw = l; + w = ap_getword(r->pool, &rpw, ':'); + + if (!strcmp(user, w)) { + file_password = ap_getword(r->pool, &rpw, ':'); + break; + } + } + ap_cfg_closefile(f); + + if (!file_password) { + return AUTH_USER_NOT_FOUND; + } + AUTHN_CACHE_STORE(r, user, NULL, file_password); + + status = apr_password_validate(password, file_password); + if (status != APR_SUCCESS) { + return AUTH_DENIED; + } + + return AUTH_GRANTED; +} + +static authn_status get_realm_hash(request_rec *r, const char *user, + const char *realm, char **rethash) +{ + authn_file_config_rec *conf = ap_get_module_config(r->per_dir_config, + &authn_file_module); + ap_configfile_t *f; + char l[MAX_STRING_LEN]; + apr_status_t status; + char *file_hash = NULL; + + if (!conf->pwfile) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01621) + "AuthUserFile not specified in the configuration"); + return AUTH_GENERAL_ERROR; + } + + status = ap_pcfg_openfile(&f, r->pool, conf->pwfile); + + if (status != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01622) + "Could not open password file: %s", conf->pwfile); + return AUTH_GENERAL_ERROR; + } + + while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) { + const char *rpw, *w, *x; + + /* Skip # or blank lines. */ + if ((l[0] == '#') || (!l[0])) { + continue; + } + + rpw = l; + w = ap_getword(r->pool, &rpw, ':'); + x = ap_getword(r->pool, &rpw, ':'); + + if (x && w && !strcmp(user, w) && !strcmp(realm, x)) { + /* Remember that this is a md5 hash of user:realm:password. */ + file_hash = ap_getword(r->pool, &rpw, ':'); + break; + } + } + ap_cfg_closefile(f); + + if (!file_hash) { + return AUTH_USER_NOT_FOUND; + } + + *rethash = file_hash; + AUTHN_CACHE_STORE(r, user, realm, file_hash); + + return AUTH_USER_FOUND; +} + +static const authn_provider authn_file_provider = +{ + &check_password, + &get_realm_hash, +}; + +static void opt_retr(void) +{ + authn_cache_store = APR_RETRIEVE_OPTIONAL_FN(ap_authn_cache_store); +} +static void register_hooks(apr_pool_t *p) +{ + ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "file", + AUTHN_PROVIDER_VERSION, + &authn_file_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_hook_optional_fn_retrieve(opt_retr, NULL, NULL, APR_HOOK_MIDDLE); +} + +AP_DECLARE_MODULE(authn_file) = +{ + STANDARD20_MODULE_STUFF, + create_authn_file_dir_config, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + authn_file_cmds, /* command apr_table_t */ + register_hooks /* register hooks */ +}; diff --git a/modules/aaa/mod_authn_file.dep b/modules/aaa/mod_authn_file.dep new file mode 100644 index 0000000..a841fa6 --- /dev/null +++ b/modules/aaa/mod_authn_file.dep @@ -0,0 +1,60 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authn_file.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authn_file.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_md5.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apr_xlate.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_authn_file.dsp b/modules/aaa/mod_authn_file.dsp new file mode 100644 index 0000000..4dc03d5 --- /dev/null +++ b/modules/aaa/mod_authn_file.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_authn_file" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authn_file - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_file.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_file.mak" CFG="mod_authn_file - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authn_file - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authn_file - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authn_file - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_authn_file_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authn_file.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authn_file.so" /d LONG_NAME="authn_file_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authn_file.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_file.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authn_file.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_file.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authn_file.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authn_file - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_authn_file_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authn_file.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authn_file.so" /d LONG_NAME="authn_file_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authn_file.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_file.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authn_file.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_file.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authn_file.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authn_file - Win32 Release" +# Name "mod_authn_file - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_authn_file.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authn_file.mak b/modules/aaa/mod_authn_file.mak new file mode 100644 index 0000000..3d98ce2 --- /dev/null +++ b/modules/aaa/mod_authn_file.mak @@ -0,0 +1,381 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authn_file.dsp +!IF "$(CFG)" == "" +CFG=mod_authn_file - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_authn_file - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_authn_file - Win32 Release" && "$(CFG)" != "mod_authn_file - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_file.mak" CFG="mod_authn_file - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authn_file - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authn_file - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authn_file - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authn_file.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Release" "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authn_file.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" "mod_auth_basic - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authn_file.obj" + -@erase "$(INTDIR)\mod_authn_file.res" + -@erase "$(INTDIR)\mod_authn_file_src.idb" + -@erase "$(INTDIR)\mod_authn_file_src.pdb" + -@erase "$(OUTDIR)\mod_authn_file.exp" + -@erase "$(OUTDIR)\mod_authn_file.lib" + -@erase "$(OUTDIR)\mod_authn_file.pdb" + -@erase "$(OUTDIR)\mod_authn_file.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authn_file_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authn_file.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authn_file.so" /d LONG_NAME="authn_file_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authn_file.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authn_file.pdb" /debug /out:"$(OUTDIR)\mod_authn_file.so" /implib:"$(OUTDIR)\mod_authn_file.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_file.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authn_file.obj" \ + "$(INTDIR)\mod_authn_file.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authn_file.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authn_file.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authn_file.so" + if exist .\Release\mod_authn_file.so.manifest mt.exe -manifest .\Release\mod_authn_file.so.manifest -outputresource:.\Release\mod_authn_file.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authn_file - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authn_file.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Debug" "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authn_file.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" "mod_auth_basic - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authn_file.obj" + -@erase "$(INTDIR)\mod_authn_file.res" + -@erase "$(INTDIR)\mod_authn_file_src.idb" + -@erase "$(INTDIR)\mod_authn_file_src.pdb" + -@erase "$(OUTDIR)\mod_authn_file.exp" + -@erase "$(OUTDIR)\mod_authn_file.lib" + -@erase "$(OUTDIR)\mod_authn_file.pdb" + -@erase "$(OUTDIR)\mod_authn_file.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authn_file_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authn_file.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authn_file.so" /d LONG_NAME="authn_file_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authn_file.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authn_file.pdb" /debug /out:"$(OUTDIR)\mod_authn_file.so" /implib:"$(OUTDIR)\mod_authn_file.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_file.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authn_file.obj" \ + "$(INTDIR)\mod_authn_file.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authn_file.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authn_file.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authn_file.so" + if exist .\Debug\mod_authn_file.so.manifest mt.exe -manifest .\Debug\mod_authn_file.so.manifest -outputresource:.\Debug\mod_authn_file.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authn_file.dep") +!INCLUDE "mod_authn_file.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authn_file.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authn_file - Win32 Release" || "$(CFG)" == "mod_authn_file - Win32 Debug" + +!IF "$(CFG)" == "mod_authn_file - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_file - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_file - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_file - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_file - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_file - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_file - Win32 Release" + +"mod_auth_basic - Win32 Release" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" + cd "." + +"mod_auth_basic - Win32 ReleaseCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" RECURSE=1 CLEAN + cd "." + +!ELSEIF "$(CFG)" == "mod_authn_file - Win32 Debug" + +"mod_auth_basic - Win32 Debug" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" + cd "." + +"mod_auth_basic - Win32 DebugCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" RECURSE=1 CLEAN + cd "." + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authn_file - Win32 Release" + + +"$(INTDIR)\mod_authn_file.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authn_file.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authn_file.so" /d LONG_NAME="authn_file_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authn_file - Win32 Debug" + + +"$(INTDIR)\mod_authn_file.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authn_file.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authn_file.so" /d LONG_NAME="authn_file_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authn_file.c + +"$(INTDIR)\mod_authn_file.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authn_socache.c b/modules/aaa/mod_authn_socache.c new file mode 100644 index 0000000..0e4454a --- /dev/null +++ b/modules/aaa/mod_authn_socache.c @@ -0,0 +1,475 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_strings.h" +#include "apr_md5.h" /* for apr_password_validate */ + +#include "ap_config.h" +#include "ap_provider.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" + +#include "mod_auth.h" + +#include "ap_socache.h" +#include "util_mutex.h" +#include "apr_optional.h" + +module AP_MODULE_DECLARE_DATA authn_socache_module; + +typedef struct authn_cache_dircfg { + apr_interval_time_t timeout; + apr_array_header_t *providers; + const char *context; +} authn_cache_dircfg; + +/* FIXME: + * I think the cache and mutex should be global + */ +static apr_global_mutex_t *authn_cache_mutex = NULL; +static ap_socache_provider_t *socache_provider = NULL; +static ap_socache_instance_t *socache_instance = NULL; +static const char *const authn_cache_id = "authn-socache"; +static int configured; + +static apr_status_t remove_lock(void *data) +{ + if (authn_cache_mutex) { + apr_global_mutex_destroy(authn_cache_mutex); + authn_cache_mutex = NULL; + } + return APR_SUCCESS; +} + +static apr_status_t destroy_cache(void *data) +{ + if (socache_instance) { + socache_provider->destroy(socache_instance, (server_rec*)data); + socache_instance = NULL; + } + return APR_SUCCESS; +} + +static int authn_cache_precfg(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptmp) +{ + apr_status_t rv = ap_mutex_register(pconf, authn_cache_id, + NULL, APR_LOCK_DEFAULT, 0); + if (rv != APR_SUCCESS) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, plog, APLOGNO(01673) + "failed to register %s mutex", authn_cache_id); + return 500; /* An HTTP status would be a misnomer! */ + } + socache_provider = ap_lookup_provider(AP_SOCACHE_PROVIDER_GROUP, + AP_SOCACHE_DEFAULT_PROVIDER, + AP_SOCACHE_PROVIDER_VERSION); + configured = 0; + return OK; +} + +static int authn_cache_post_config(apr_pool_t *pconf, apr_pool_t *plog, + apr_pool_t *ptmp, server_rec *s) +{ + apr_status_t rv; + static struct ap_socache_hints authn_cache_hints = {64, 32, 60000000}; + const char *errmsg; + + if (!configured) { + return OK; /* don't waste the overhead of creating mutex & cache */ + } + if (socache_provider == NULL) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, plog, APLOGNO(01674) + "Please select a socache provider with AuthnCacheSOCache " + "(no default found on this platform). Maybe you need to " + "load mod_socache_shmcb or another socache module first"); + return 500; /* An HTTP status would be a misnomer! */ + } + + /* We have socache_provider, but do not have socache_instance. This should + * happen only when using "default" socache_provider, so create default + * socache_instance in this case. */ + if (socache_instance == NULL) { + errmsg = socache_provider->create(&socache_instance, NULL, + ptmp, pconf); + if (errmsg) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, plog, APLOGNO(02612) + "failed to create mod_socache_shmcb socache " + "instance: %s", errmsg); + return 500; + } + } + + rv = ap_global_mutex_create(&authn_cache_mutex, NULL, + authn_cache_id, NULL, s, pconf, 0); + if (rv != APR_SUCCESS) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, plog, APLOGNO(01675) + "failed to create %s mutex", authn_cache_id); + return 500; /* An HTTP status would be a misnomer! */ + } + apr_pool_cleanup_register(pconf, NULL, remove_lock, apr_pool_cleanup_null); + + rv = socache_provider->init(socache_instance, authn_cache_id, + &authn_cache_hints, s, pconf); + if (rv != APR_SUCCESS) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, plog, APLOGNO(01677) + "failed to initialise %s cache", authn_cache_id); + return 500; /* An HTTP status would be a misnomer! */ + } + apr_pool_cleanup_register(pconf, (void*)s, destroy_cache, apr_pool_cleanup_null); + return OK; +} + +static void authn_cache_child_init(apr_pool_t *p, server_rec *s) +{ + const char *lock; + apr_status_t rv; + if (!configured) { + return; /* don't waste the overhead of creating mutex & cache */ + } + lock = apr_global_mutex_lockfile(authn_cache_mutex); + rv = apr_global_mutex_child_init(&authn_cache_mutex, lock, p); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(01678) + "failed to initialise mutex in child_init"); + } +} + +static const char *authn_cache_socache(cmd_parms *cmd, void *CFG, + const char *arg) +{ + const char *errmsg = ap_check_cmd_context(cmd, GLOBAL_ONLY); + const char *sep, *name; + + if (errmsg) + return errmsg; + + /* Argument is of form 'name:args' or just 'name'. */ + sep = ap_strchr_c(arg, ':'); + if (sep) { + name = apr_pstrmemdup(cmd->pool, arg, sep - arg); + sep++; + } + else { + name = arg; + } + + socache_provider = ap_lookup_provider(AP_SOCACHE_PROVIDER_GROUP, name, + AP_SOCACHE_PROVIDER_VERSION); + if (socache_provider == NULL) { + errmsg = apr_psprintf(cmd->pool, + "Unknown socache provider '%s'. Maybe you need " + "to load the appropriate socache module " + "(mod_socache_%s?)", arg, arg); + } + else { + errmsg = socache_provider->create(&socache_instance, sep, + cmd->temp_pool, cmd->pool); + } + + if (errmsg) { + errmsg = apr_psprintf(cmd->pool, "AuthnCacheSOCache: %s", errmsg); + } + return errmsg; +} + +static const char *authn_cache_enable(cmd_parms *cmd, void *CFG) +{ + const char *errmsg = ap_check_cmd_context(cmd, GLOBAL_ONLY); + configured = 1; + return errmsg; +} + +static const char *const directory = "directory"; +static void* authn_cache_dircfg_create(apr_pool_t *pool, char *s) +{ + authn_cache_dircfg *ret = apr_palloc(pool, sizeof(authn_cache_dircfg)); + ret->timeout = apr_time_from_sec(300); + ret->providers = NULL; + ret->context = directory; + return ret; +} + +/* not sure we want this. Might be safer to document use-all-or-none */ +static void* authn_cache_dircfg_merge(apr_pool_t *pool, void *BASE, void *ADD) +{ + authn_cache_dircfg *base = BASE; + authn_cache_dircfg *add = ADD; + authn_cache_dircfg *ret = apr_pmemdup(pool, add, sizeof(authn_cache_dircfg)); + /* preserve context and timeout if not defaults */ + if (add->context == directory) { + ret->context = base->context; + } + if (add->timeout == apr_time_from_sec(300)) { + ret->timeout = base->timeout; + } + if (add->providers == NULL) { + ret->providers = base->providers; + } + return ret; +} + +static const char *authn_cache_setprovider(cmd_parms *cmd, void *CFG, + const char *arg) +{ + authn_cache_dircfg *cfg = CFG; + if (cfg->providers == NULL) { + cfg->providers = apr_array_make(cmd->pool, 4, sizeof(const char*)); + } + APR_ARRAY_PUSH(cfg->providers, const char*) = arg; + configured = 1; + return NULL; +} + +static const char *authn_cache_timeout(cmd_parms *cmd, void *CFG, + const char *arg) +{ + authn_cache_dircfg *cfg = CFG; + int secs = atoi(arg); + cfg->timeout = apr_time_from_sec(secs); + return NULL; +} + +static const command_rec authn_cache_cmds[] = +{ + /* global stuff: cache and mutex */ + AP_INIT_TAKE1("AuthnCacheSOCache", authn_cache_socache, NULL, RSRC_CONF, + "socache provider for authn cache"), + AP_INIT_NO_ARGS("AuthnCacheEnable", authn_cache_enable, NULL, RSRC_CONF, + "enable socache configuration in htaccess even if not enabled anywhere else"), + /* per-dir stuff */ + AP_INIT_ITERATE("AuthnCacheProvideFor", authn_cache_setprovider, NULL, + OR_AUTHCFG, "Determine what authn providers to cache for"), + AP_INIT_TAKE1("AuthnCacheTimeout", authn_cache_timeout, NULL, + OR_AUTHCFG, "Timeout (secs) for cached credentials"), + AP_INIT_TAKE1("AuthnCacheContext", ap_set_string_slot, + (void*)APR_OFFSETOF(authn_cache_dircfg, context), + ACCESS_CONF, "Context for authn cache"), + {NULL} +}; + +static const char *construct_key(request_rec *r, const char *context, + const char *user, const char *realm) +{ + /* handle "special" context values */ + if (!strcmp(context, directory)) { + /* FIXME: are we at risk of this blowing up? */ + char *new_context; + char *slash = strrchr(r->uri, '/'); + new_context = apr_palloc(r->pool, slash - r->uri + + strlen(r->server->server_hostname) + 1); + strcpy(new_context, r->server->server_hostname); + strncat(new_context, r->uri, slash - r->uri); + context = new_context; + } + else if (!strcmp(context, "server")) { + context = r->server->server_hostname; + } + /* any other context value is literal */ + + if (realm == NULL) { /* basic auth */ + return apr_pstrcat(r->pool, context, ":", user, NULL); + } + else { /* digest auth */ + return apr_pstrcat(r->pool, context, ":", user, ":", realm, NULL); + } +} + +static void ap_authn_cache_store(request_rec *r, const char *module, + const char *user, const char *realm, + const char* data) +{ + apr_status_t rv; + authn_cache_dircfg *dcfg; + const char *key; + apr_time_t expiry; + + /* first check whether we're caching for this module */ + dcfg = ap_get_module_config(r->per_dir_config, &authn_socache_module); + if (!configured || !dcfg->providers) { + return; + } + if (!ap_array_str_contains(dcfg->providers, module)) { + return; + } + + /* OK, we're on. Grab mutex to do our business */ + rv = apr_global_mutex_trylock(authn_cache_mutex); + if (APR_STATUS_IS_EBUSY(rv)) { + /* don't wait around; just abandon it */ + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(01679) + "authn credentials for %s not cached (mutex busy)", user); + return; + } + else if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01680) + "Failed to cache authn credentials for %s in %s", + module, dcfg->context); + return; + } + + /* We have the mutex, so go ahead */ + /* first build our key and determine expiry time */ + key = construct_key(r, dcfg->context, user, realm); + expiry = apr_time_now() + dcfg->timeout; + + /* store it */ + rv = socache_provider->store(socache_instance, r->server, + (unsigned char*)key, strlen(key), expiry, + (unsigned char*)data, strlen(data), r->pool); + if (rv == APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01681) + "Cached authn credentials for %s in %s", + user, dcfg->context); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01682) + "Failed to cache authn credentials for %s in %s", + module, dcfg->context); + } + + /* We're done with the mutex */ + rv = apr_global_mutex_unlock(authn_cache_mutex); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01683) "Failed to release mutex!"); + } +} + +#define MAX_VAL_LEN 256 +static authn_status check_password(request_rec *r, const char *user, + const char *password) +{ + /* construct key + * look it up + * if found, test password + * + * mutexing here would be a big performance drag. + * It's definitely unnecessary with some backends (like ndbm or gdbm) + * Is there a risk in the general case? I guess the only risk we + * care about is a race condition that gets us a dangling pointer + * to no-longer-defined memory. Hmmm ... + */ + apr_status_t rv; + const char *key; + authn_cache_dircfg *dcfg; + unsigned char val[MAX_VAL_LEN]; + unsigned int vallen = MAX_VAL_LEN - 1; + dcfg = ap_get_module_config(r->per_dir_config, &authn_socache_module); + if (!configured || !dcfg->providers) { + return AUTH_USER_NOT_FOUND; + } + key = construct_key(r, dcfg->context, user, NULL); + rv = socache_provider->retrieve(socache_instance, r->server, + (unsigned char*)key, strlen(key), + val, &vallen, r->pool); + + if (APR_STATUS_IS_NOTFOUND(rv)) { + /* not found - just return */ + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01684) + "Authn cache: no credentials found for %s", user); + return AUTH_USER_NOT_FOUND; + } + else if (rv == APR_SUCCESS) { + /* OK, we got a value */ + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01685) + "Authn cache: found credentials for %s", user); + val[vallen] = 0; + } + else { + /* error: give up and pass the buck */ + /* FIXME: getting this for NOTFOUND - prolly a bug in mod_socache */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01686) + "Error accessing authentication cache"); + return AUTH_USER_NOT_FOUND; + } + + rv = apr_password_validate(password, (char*) val); + if (rv != APR_SUCCESS) { + return AUTH_DENIED; + } + + return AUTH_GRANTED; +} + +static authn_status get_realm_hash(request_rec *r, const char *user, + const char *realm, char **rethash) +{ + apr_status_t rv; + const char *key; + authn_cache_dircfg *dcfg; + unsigned char val[MAX_VAL_LEN]; + unsigned int vallen = MAX_VAL_LEN - 1; + dcfg = ap_get_module_config(r->per_dir_config, &authn_socache_module); + if (!configured || !dcfg->providers) { + return AUTH_USER_NOT_FOUND; + } + key = construct_key(r, dcfg->context, user, realm); + rv = socache_provider->retrieve(socache_instance, r->server, + (unsigned char*)key, strlen(key), + val, &vallen, r->pool); + + if (APR_STATUS_IS_NOTFOUND(rv)) { + /* not found - just return */ + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01687) + "Authn cache: no credentials found for %s", user); + return AUTH_USER_NOT_FOUND; + } + else if (rv == APR_SUCCESS) { + /* OK, we got a value */ + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01688) + "Authn cache: found credentials for %s", user); + } + else { + /* error: give up and pass the buck */ + /* FIXME: getting this for NOTFOUND - prolly a bug in mod_socache */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01689) + "Error accessing authentication cache"); + return AUTH_USER_NOT_FOUND; + } + *rethash = apr_pstrmemdup(r->pool, (char *)val, vallen); + + return AUTH_USER_FOUND; +} + +static const authn_provider authn_cache_provider = +{ + &check_password, + &get_realm_hash, +}; + +static void register_hooks(apr_pool_t *p) +{ + ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "socache", + AUTHN_PROVIDER_VERSION, + &authn_cache_provider, AP_AUTH_INTERNAL_PER_CONF); + APR_REGISTER_OPTIONAL_FN(ap_authn_cache_store); + ap_hook_pre_config(authn_cache_precfg, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_post_config(authn_cache_post_config, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_child_init(authn_cache_child_init, NULL, NULL, APR_HOOK_MIDDLE); +} + +AP_DECLARE_MODULE(authn_socache) = +{ + STANDARD20_MODULE_STUFF, + authn_cache_dircfg_create, + authn_cache_dircfg_merge, + NULL, + NULL, + authn_cache_cmds, + register_hooks +}; diff --git a/modules/aaa/mod_authn_socache.dep b/modules/aaa/mod_authn_socache.dep new file mode 100644 index 0000000..c8b3d28 --- /dev/null +++ b/modules/aaa/mod_authn_socache.dep @@ -0,0 +1,62 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authn_socache.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authn_socache.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\ap_socache.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\include\util_mutex.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_md5.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apr_xlate.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_authn_socache.dsp b/modules/aaa/mod_authn_socache.dsp new file mode 100644 index 0000000..c0cad1c --- /dev/null +++ b/modules/aaa/mod_authn_socache.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_authn_socache" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authn_socache - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_socache.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_socache.mak" CFG="mod_authn_socache - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authn_socache - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authn_socache - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authn_socache - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_authn_socache_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authn_socache.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authn_socache.so" /d LONG_NAME="authn_socache_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authn_socache.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_socache.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authn_socache.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_socache.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authn_socache.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authn_socache - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_authn_socache_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authn_socache.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authn_socache.so" /d LONG_NAME="authn_socache_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authn_socache.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_socache.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authn_socache.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_socache.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authn_socache.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authn_socache - Win32 Release" +# Name "mod_authn_socache - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_authn_socache.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authn_socache.mak b/modules/aaa/mod_authn_socache.mak new file mode 100644 index 0000000..7d43473 --- /dev/null +++ b/modules/aaa/mod_authn_socache.mak @@ -0,0 +1,353 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authn_socache.dsp +!IF "$(CFG)" == "" +CFG=mod_authn_socache - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_authn_socache - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_authn_socache - Win32 Release" && "$(CFG)" != "mod_authn_socache - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authn_socache.mak" CFG="mod_authn_socache - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authn_socache - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authn_socache - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authn_socache - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authn_socache.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authn_socache.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authn_socache.obj" + -@erase "$(INTDIR)\mod_authn_socache.res" + -@erase "$(INTDIR)\mod_authn_socache_src.idb" + -@erase "$(INTDIR)\mod_authn_socache_src.pdb" + -@erase "$(OUTDIR)\mod_authn_socache.exp" + -@erase "$(OUTDIR)\mod_authn_socache.lib" + -@erase "$(OUTDIR)\mod_authn_socache.pdb" + -@erase "$(OUTDIR)\mod_authn_socache.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authn_socache_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authn_socache.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authn_socache.so" /d LONG_NAME="authn_socache_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authn_socache.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authn_socache.pdb" /debug /out:"$(OUTDIR)\mod_authn_socache.so" /implib:"$(OUTDIR)\mod_authn_socache.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_socache.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authn_socache.obj" \ + "$(INTDIR)\mod_authn_socache.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" + +"$(OUTDIR)\mod_authn_socache.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authn_socache.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authn_socache.so" + if exist .\Release\mod_authn_socache.so.manifest mt.exe -manifest .\Release\mod_authn_socache.so.manifest -outputresource:.\Release\mod_authn_socache.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authn_socache - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authn_socache.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authn_socache.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authn_socache.obj" + -@erase "$(INTDIR)\mod_authn_socache.res" + -@erase "$(INTDIR)\mod_authn_socache_src.idb" + -@erase "$(INTDIR)\mod_authn_socache_src.pdb" + -@erase "$(OUTDIR)\mod_authn_socache.exp" + -@erase "$(OUTDIR)\mod_authn_socache.lib" + -@erase "$(OUTDIR)\mod_authn_socache.pdb" + -@erase "$(OUTDIR)\mod_authn_socache.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authn_socache_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authn_socache.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authn_socache.so" /d LONG_NAME="authn_socache_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authn_socache.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authn_socache.pdb" /debug /out:"$(OUTDIR)\mod_authn_socache.so" /implib:"$(OUTDIR)\mod_authn_socache.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authn_socache.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authn_socache.obj" \ + "$(INTDIR)\mod_authn_socache.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" + +"$(OUTDIR)\mod_authn_socache.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authn_socache.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authn_socache.so" + if exist .\Debug\mod_authn_socache.so.manifest mt.exe -manifest .\Debug\mod_authn_socache.so.manifest -outputresource:.\Debug\mod_authn_socache.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authn_socache.dep") +!INCLUDE "mod_authn_socache.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authn_socache.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authn_socache - Win32 Release" || "$(CFG)" == "mod_authn_socache - Win32 Debug" + +!IF "$(CFG)" == "mod_authn_socache - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_socache - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_socache - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_socache - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authn_socache - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authn_socache - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authn_socache - Win32 Release" + + +"$(INTDIR)\mod_authn_socache.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authn_socache.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authn_socache.so" /d LONG_NAME="authn_socache_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authn_socache - Win32 Debug" + + +"$(INTDIR)\mod_authn_socache.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authn_socache.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authn_socache.so" /d LONG_NAME="authn_socache_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authn_socache.c + +"$(INTDIR)\mod_authn_socache.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authnz_fcgi.c b/modules/aaa/mod_authnz_fcgi.c new file mode 100644 index 0000000..1aadcc2 --- /dev/null +++ b/modules/aaa/mod_authnz_fcgi.c @@ -0,0 +1,1364 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_hash.h" +#include "apr_lib.h" +#include "apr_strings.h" + +#include "ap_provider.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_protocol.h" +#include "http_request.h" +#include "http_log.h" +#include "util_script.h" +#include "ap_provider.h" +#include "mod_auth.h" +#include "util_fcgi.h" +#include "ap_mmn.h" + +module AP_MODULE_DECLARE_DATA authnz_fcgi_module; + +typedef struct { + const char *name; /* provider name */ + const char *backend; /* backend address, as configured */ + const char *host; + apr_port_t port; + apr_sockaddr_t *backend_addrs; + int is_authn; + int is_authz; +} fcgi_provider_conf; + +typedef struct { + const char *name; /* provider name */ + const char *default_user; /* this is user if authorizer returns + * success and a user expression yields + * empty string + */ + ap_expr_info_t *user_expr; /* expr to evaluate to set r->user */ + char authoritative; /* fail request if user is rejected? */ + char require_basic_auth; /* fail if client didn't send credentials? */ +} fcgi_dir_conf; + +typedef struct { + /* If an "authnz" provider successfully authenticates, record + * the provider name here for checking during authz. + */ + const char *successful_authnz_provider; +} fcgi_request_notes; + +static apr_hash_t *fcgi_authn_providers, *fcgi_authz_providers; + +#define FCGI_IO_TIMEOUT apr_time_from_sec(30) + +#ifndef NON200_RESPONSE_BUF_LEN +#define NON200_RESPONSE_BUF_LEN 8192 +#endif + +/* fcgi://{hostname|IPv4|IPv6}:port[/] */ +#define FCGI_BACKEND_REGEX_STR "m%^fcgi://(.*):(\\d{1,5})/?$%" + +/* + * utility function to connect to a peer; generally useful, but + * wait for AF_UNIX support in this mod before thinking about how + * to make it available to other modules + */ +static apr_status_t connect_to_peer(apr_socket_t **newsock, + request_rec *r, + apr_sockaddr_t *backend_addrs, + const char *backend_name, + apr_interval_time_t timeout) +{ + apr_status_t rv = APR_EINVAL; /* returned if no backend addr was provided + */ + int connected = 0; + apr_sockaddr_t *addr = backend_addrs; + + while (addr && !connected) { + int loglevel = addr->next ? APLOG_DEBUG : APLOG_ERR; + rv = apr_socket_create(newsock, addr->family, + SOCK_STREAM, 0, r->pool); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, loglevel, rv, r, + APLOGNO(02494) "error creating family %d socket " + "for target %s", + addr->family, backend_name); + addr = addr->next; + continue; + } + + apr_socket_opt_set(*newsock, APR_TCP_NODELAY, 1); + apr_socket_timeout_set(*newsock, + timeout ? timeout : r->server->timeout); + + rv = apr_socket_connect(*newsock, addr); + if (rv != APR_SUCCESS) { + apr_socket_close(*newsock); + ap_log_rerror(APLOG_MARK, loglevel, rv, r, + APLOGNO(02495) "attempt to connect to %pI (%s) " + "failed", addr, backend_name); + addr = addr->next; + continue; + } + + connected = 1; + } + + return rv; +#undef FN_LOG_MARK +} + +static void log_provider_info(const fcgi_provider_conf *conf, request_rec *r) +{ + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + APLOGNO(02496) "name %s, backend %s, host %s, port %d, " + "first address %pI, %c%c", + conf->name, + conf->backend, + conf->host, + (int)conf->port, + conf->backend_addrs, + conf->is_authn ? 'N' : '_', + conf->is_authz ? 'Z' : '_'); +} + +static void setupenv(request_rec *r, const char *password, const char *apache_role) +{ + ap_add_common_vars(r); + ap_add_cgi_vars(r); + apr_table_setn(r->subprocess_env, "FCGI_ROLE", AP_FCGI_AUTHORIZER_STR); + if (apache_role) { + apr_table_setn(r->subprocess_env, "FCGI_APACHE_ROLE", apache_role); + } + if (password) { + apr_table_setn(r->subprocess_env, "REMOTE_PASSWD", password); + } + /* Drop the variables CONTENT_LENGTH, PATH_INFO, PATH_TRANSLATED, + * SCRIPT_NAME and most Hop-By-Hop headers - EXCEPT we will pass + * PROXY_AUTH to allow CGI to perform proxy auth for httpd + */ + apr_table_unset(r->subprocess_env, "CONTENT_LENGTH"); + apr_table_unset(r->subprocess_env, "PATH_INFO"); + apr_table_unset(r->subprocess_env, "PATH_TRANSLATED"); + apr_table_unset(r->subprocess_env, "SCRIPT_NAME"); + apr_table_unset(r->subprocess_env, "HTTP_KEEP_ALIVE"); + apr_table_unset(r->subprocess_env, "HTTP_TE"); + apr_table_unset(r->subprocess_env, "HTTP_TRAILER"); + apr_table_unset(r->subprocess_env, "HTTP_TRANSFER_ENCODING"); + apr_table_unset(r->subprocess_env, "HTTP_UPGRADE"); + + /* Connection hop-by-hop header to prevent the CGI from hanging */ + apr_table_setn(r->subprocess_env, "HTTP_CONNECTION", "close"); +} + +static apr_status_t recv_data(const fcgi_provider_conf *conf, + request_rec *r, + apr_socket_t *s, + char *buf, + apr_size_t *buflen) +{ + apr_status_t rv; + + rv = apr_socket_recv(s, buf, buflen); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + APLOGNO(02497) "Couldn't read from backend %s", + conf->backend); + return rv; + } + +#if AP_MODULE_MAGIC_AT_LEAST(20130702,2) + ap_log_rdata(APLOG_MARK, APLOG_TRACE5, r, "FastCGI data received", + buf, *buflen, AP_LOG_DATA_SHOW_OFFSET); +#endif + return APR_SUCCESS; +} + +static apr_status_t recv_data_full(const fcgi_provider_conf *conf, + request_rec *r, + apr_socket_t *s, + char *buf, + apr_size_t buflen) +{ + apr_size_t readlen; + apr_size_t cumulative_len = 0; + apr_status_t rv; + + do { + readlen = buflen - cumulative_len; + rv = recv_data(conf, r, s, buf + cumulative_len, &readlen); + if (rv != APR_SUCCESS) { + return rv; + } + cumulative_len += readlen; + } while (cumulative_len < buflen); + + return APR_SUCCESS; +} + +static apr_status_t sendv_data(const fcgi_provider_conf *conf, + request_rec *r, + apr_socket_t *s, + struct iovec *vec, + int nvec, + apr_size_t *len) +{ + apr_size_t to_write = 0, written = 0; + apr_status_t rv = APR_SUCCESS; + int i, offset; + + for (i = 0; i < nvec; i++) { + to_write += vec[i].iov_len; +#if AP_MODULE_MAGIC_AT_LEAST(20130702,2) + ap_log_rdata(APLOG_MARK, APLOG_TRACE5, r, "FastCGI data sent", + vec[i].iov_base, vec[i].iov_len, AP_LOG_DATA_SHOW_OFFSET); +#endif + } + + offset = 0; + while (to_write) { + apr_size_t n = 0; + rv = apr_socket_sendv(s, vec + offset, nvec - offset, &n); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + APLOGNO(02498) "Sending data to %s failed", + conf->backend); + break; + } + if (n > 0) { + written += n; + if (written >= to_write) + break; /* short circuit out */ + for (i = offset; i < nvec; ) { + if (n >= vec[i].iov_len) { + offset++; + n -= vec[i++].iov_len; + } else { + vec[i].iov_len -= n; + vec[i].iov_base = (char *) vec[i].iov_base + n; + break; + } + } + } + } + + *len = written; + + return rv; +} + +static apr_status_t send_begin_request(request_rec *r, + const fcgi_provider_conf *conf, + apr_socket_t *s, int role, + apr_uint16_t request_id) +{ + struct iovec vec[2]; + ap_fcgi_header header; + unsigned char farray[AP_FCGI_HEADER_LEN]; + ap_fcgi_begin_request_body brb; + unsigned char abrb[AP_FCGI_HEADER_LEN]; + apr_size_t len; + + ap_fcgi_fill_in_header(&header, AP_FCGI_BEGIN_REQUEST, request_id, + sizeof(abrb), 0); + ap_fcgi_fill_in_request_body(&brb, role, 0 /* *NOT* AP_FCGI_KEEP_CONN */); + + ap_fcgi_header_to_array(&header, farray); + ap_fcgi_begin_request_body_to_array(&brb, abrb); + + vec[0].iov_base = (void *)farray; + vec[0].iov_len = sizeof(farray); + vec[1].iov_base = (void *)abrb; + vec[1].iov_len = sizeof(abrb); + + return sendv_data(conf, r, s, vec, 2, &len); +} + +static apr_status_t send_environment(apr_socket_t *s, + const fcgi_provider_conf *conf, + request_rec *r, apr_uint16_t request_id, + apr_pool_t *temp_pool) +{ + const char *fn = "send_environment"; + const apr_array_header_t *envarr; + const apr_table_entry_t *elts; + struct iovec vec[2]; + ap_fcgi_header header; + unsigned char farray[AP_FCGI_HEADER_LEN]; + char *body; + apr_status_t rv; + apr_size_t avail_len, len, required_len; + int i, next_elem, starting_elem; + + envarr = apr_table_elts(r->subprocess_env); + elts = (const apr_table_entry_t *) envarr->elts; + + if (APLOG_R_IS_LEVEL(r, APLOG_TRACE2)) { + + for (i = 0; i < envarr->nelts; ++i) { + if (!elts[i].key) { + continue; + } + ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, + "%s: '%s': '%s'", + fn, elts[i].key, + !strcmp(elts[i].key, "REMOTE_PASSWD") ? + "XXXXXXXX" : elts[i].val); + } + } + + /* Send envvars over in as many FastCGI records as it takes, */ + next_elem = 0; /* starting with the first one */ + + avail_len = 16 * 1024; /* our limit per record, which could have been up + * to AP_FCGI_MAX_CONTENT_LEN + */ + + while (next_elem < envarr->nelts) { + starting_elem = next_elem; + required_len = ap_fcgi_encoded_env_len(r->subprocess_env, + avail_len, + &next_elem); + + if (!required_len) { + if (next_elem < envarr->nelts) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, + APLOGNO(02499) "couldn't encode envvar '%s' in %" + APR_SIZE_T_FMT " bytes", + elts[next_elem].key, avail_len); + /* skip this envvar and continue */ + ++next_elem; + continue; + } + /* only an unused element at the end of the array */ + break; + } + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + APLOGNO(02500) "required len for encoding envvars: %" + APR_SIZE_T_FMT ", %d/%d elems processed so far", + required_len, next_elem, envarr->nelts); + + body = apr_palloc(temp_pool, required_len); + rv = ap_fcgi_encode_env(r, r->subprocess_env, body, required_len, + &starting_elem); + /* we pre-compute, so we can't run out of space */ + ap_assert(rv == APR_SUCCESS); + /* compute and encode must be in sync */ + ap_assert(starting_elem == next_elem); + + ap_fcgi_fill_in_header(&header, AP_FCGI_PARAMS, request_id, + (apr_uint16_t)required_len, 0); + ap_fcgi_header_to_array(&header, farray); + + vec[0].iov_base = (void *)farray; + vec[0].iov_len = sizeof(farray); + vec[1].iov_base = body; + vec[1].iov_len = required_len; + + rv = sendv_data(conf, r, s, vec, 2, &len); + apr_pool_clear(temp_pool); + + if (rv) { + return rv; + } + } + + /* Envvars sent, so say we're done */ + ap_fcgi_fill_in_header(&header, AP_FCGI_PARAMS, request_id, 0, 0); + ap_fcgi_header_to_array(&header, farray); + + vec[0].iov_base = (void *)farray; + vec[0].iov_len = sizeof(farray); + + return sendv_data(conf, r, s, vec, 1, &len); +} + +/* + * This header-state logic is from mod_proxy_fcgi. + */ +enum { + HDR_STATE_READING_HEADERS, + HDR_STATE_GOT_CR, + HDR_STATE_GOT_CRLF, + HDR_STATE_GOT_CRLFCR, + HDR_STATE_GOT_LF, + HDR_STATE_DONE_WITH_HEADERS +}; + +/* Try to find the end of the script headers in the response from the back + * end fastcgi server. STATE holds the current header parsing state for this + * request. + * + * Returns 0 if it can't find the end of the headers, and 1 if it found the + * end of the headers. */ +static int handle_headers(request_rec *r, int *state, + const char *readbuf, apr_size_t readlen) +{ + const char *itr = readbuf; + + while (readlen--) { + if (*itr == '\r') { + switch (*state) { + case HDR_STATE_GOT_CRLF: + *state = HDR_STATE_GOT_CRLFCR; + break; + + default: + *state = HDR_STATE_GOT_CR; + break; + } + } + else if (*itr == '\n') { + switch (*state) { + case HDR_STATE_GOT_LF: + *state = HDR_STATE_DONE_WITH_HEADERS; + break; + + case HDR_STATE_GOT_CR: + *state = HDR_STATE_GOT_CRLF; + break; + + case HDR_STATE_GOT_CRLFCR: + *state = HDR_STATE_DONE_WITH_HEADERS; + break; + + default: + *state = HDR_STATE_GOT_LF; + break; + } + } + else { + *state = HDR_STATE_READING_HEADERS; + } + + if (*state == HDR_STATE_DONE_WITH_HEADERS) + break; + + ++itr; + } + + if (*state == HDR_STATE_DONE_WITH_HEADERS) { + return 1; + } + + return 0; +} + +/* + * handle_response() is based on mod_proxy_fcgi's dispatch() + */ +static apr_status_t handle_response(const fcgi_provider_conf *conf, + request_rec *r, apr_socket_t *s, + apr_pool_t *temp_pool, + apr_uint16_t request_id, + char *rspbuf, + apr_size_t *rspbuflen) +{ + apr_bucket *b; + apr_bucket_brigade *ob; + apr_size_t orspbuflen = 0; + apr_status_t rv = APR_SUCCESS; + const char *fn = "handle_response"; + int header_state = HDR_STATE_READING_HEADERS; + int seen_end_of_headers = 0, done = 0; + + if (rspbuflen) { + orspbuflen = *rspbuflen; + *rspbuflen = 0; /* unless we actually read something */ + } + + ob = apr_brigade_create(r->pool, r->connection->bucket_alloc); + + while (!done && rv == APR_SUCCESS) { /* Keep reading FastCGI records until + * we get AP_FCGI_END_REQUEST (done) + * or an error occurs. + */ + apr_size_t readbuflen; + apr_uint16_t clen; + apr_uint16_t rid; + char readbuf[AP_IOBUFSIZE + 1]; + unsigned char farray[AP_FCGI_HEADER_LEN]; + unsigned char plen; + unsigned char type; + unsigned char version; + + rv = recv_data_full(conf, r, s, (char *)farray, AP_FCGI_HEADER_LEN); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + APLOGNO(02501) "%s: Error occurred before reading " + "entire header", fn); + break; + } + + ap_fcgi_header_fields_from_array(&version, &type, &rid, &clen, &plen, + farray); + + if (version != AP_FCGI_VERSION_1) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + APLOGNO(02502) "%s: Got bogus FastCGI header " + "version %d", fn, (int)version); + rv = APR_EINVAL; + break; + } + + if (rid != request_id) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + APLOGNO(02503) "%s: Got bogus FastCGI header " + "request id %d, expected %d", + fn, rid, request_id); + rv = APR_EINVAL; + break; + } + + recv_again: /* if we need to keep reading more of a record's content */ + + if (clen > sizeof(readbuf) - 1) { + readbuflen = sizeof(readbuf) - 1; + } else { + readbuflen = clen; + } + + /* + * Now get the actual content of the record. + */ + if (readbuflen != 0) { + rv = recv_data(conf, r, s, readbuf, &readbuflen); + if (rv != APR_SUCCESS) { + break; + } + readbuf[readbuflen] = '\0'; + } + + switch (type) { + case AP_FCGI_STDOUT: /* Response headers and optional body */ + if (clen != 0) { + b = apr_bucket_transient_create(readbuf, + readbuflen, + r->connection->bucket_alloc); + + APR_BRIGADE_INSERT_TAIL(ob, b); + + if (!seen_end_of_headers) { + int st = handle_headers(r, &header_state, + readbuf, readbuflen); + + if (st == 1) { + int status; + + seen_end_of_headers = 1; + + status = + ap_scan_script_header_err_brigade_ex(r, ob, + NULL, + APLOG_MODULE_INDEX); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + APLOGNO(02504) "%s: script header " + "parsing -> %d/%d", + fn, status, r->status); + + if (rspbuf) { /* caller wants to see response body, + * if any + */ + apr_status_t tmprv; + + if (rspbuflen) { + *rspbuflen = orspbuflen; + } + tmprv = apr_brigade_flatten(ob, rspbuf, rspbuflen); + if (tmprv != APR_SUCCESS) { + /* should not occur for these bucket types; + * does not indicate overflow + */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, tmprv, r, + APLOGNO(02505) "%s: error " + "flattening response body", + fn); + } + } + + if (status != OK) { + r->status = status; + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + APLOGNO(02506) "%s: Error parsing " + "script headers from %s", + fn, conf->backend); + rv = APR_EINVAL; + break; + } + apr_pool_clear(temp_pool); + } + else { + /* We're still looking for the end of the + * headers, so this part of the data will need + * to persist. */ + apr_bucket_setaside(b, temp_pool); + } + } + + /* If we didn't read all the data go back and get the + * rest of it. */ + if (clen > readbuflen) { + clen -= readbuflen; + goto recv_again; + } + } + break; + + case AP_FCGI_STDERR: /* Text to log */ + if (clen) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, + APLOGNO(02507) "%s: Logged from %s: '%s'", + fn, conf->backend, readbuf); + } + + if (clen > readbuflen) { + clen -= readbuflen; + goto recv_again; /* continue reading this record */ + } + break; + + case AP_FCGI_END_REQUEST: + done = 1; + break; + + default: + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + APLOGNO(02508) "%s: Got bogus FastCGI record type " + "%d", fn, type); + break; + } + /* Leave on above switch's inner error. */ + if (rv != APR_SUCCESS) { + break; + } + + /* + * Read/discard any trailing padding. + */ + if (plen) { + rv = recv_data_full(conf, r, s, readbuf, plen); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + APLOGNO(02509) "%s: Error occurred reading " + "padding", + fn); + break; + } + } + } + + apr_brigade_cleanup(ob); + + if (rv == APR_SUCCESS && !seen_end_of_headers) { + rv = APR_EINVAL; + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + APLOGNO(02510) "%s: Never reached end of script headers", + fn); + } + + return rv; +} + +/* almost from mod_fcgid */ +static int mod_fcgid_modify_auth_header(void *vars, + const char *key, const char *val) +{ + /* When the application gives a 200 response, the server ignores response + headers whose names aren't prefixed with Variable- prefix, and ignores + any response content */ + if (ap_cstr_casecmpn(key, "Variable-", 9) == 0) + apr_table_setn(vars, key, val); + return 1; +} + +static int fix_auth_header(void *vr, const char *key, const char *val) +{ + request_rec *r = vr; + + ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "moving %s->%s", key, val); + apr_table_unset(r->err_headers_out, key); + apr_table_setn(r->subprocess_env, key + 9, val); + return 1; +} + +static void req_rsp(request_rec *r, const fcgi_provider_conf *conf, + const char *password, const char *apache_role, + char *rspbuf, apr_size_t *rspbuflen) +{ + const char *fn = "req_rsp"; + apr_pool_t *temp_pool; + apr_size_t orspbuflen = 0; + apr_socket_t *s; + apr_status_t rv; + apr_table_t *saved_subprocess_env = + apr_table_copy(r->pool, r->subprocess_env); + + if (rspbuflen) { + orspbuflen = *rspbuflen; + *rspbuflen = 0; /* unless we actually read something */ + } + + apr_pool_create(&temp_pool, r->pool); + apr_pool_tag(temp_pool, "mod_authnz_fcgi (req_rsp)"); + + setupenv(r, password, apache_role); + + rv = connect_to_peer(&s, r, conf->backend_addrs, + conf->backend, FCGI_IO_TIMEOUT); + if (rv == APR_SUCCESS) { + apr_uint16_t request_id = 1; + + rv = send_begin_request(r, conf, s, AP_FCGI_AUTHORIZER, request_id); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + APLOGNO(02511) "%s: Failed writing request to %s", + fn, conf->backend); + } + + if (rv == APR_SUCCESS) { + rv = send_environment(s, conf, r, request_id, temp_pool); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + APLOGNO(02512) "%s: Failed writing environment " + "to %s", fn, conf->backend); + } + } + + /* The responder owns the request body, not the authorizer. + * Don't even send an empty AP_FCGI_STDIN block. libfcgi doesn't care, + * but it wasn't sent to authorizers by mod_fastcgi or mod_fcgi and + * may be unhandled by the app. Additionally, the FastCGI spec does + * not mention FCGI_STDIN in the Authorizer description, though it + * does describe FCGI_STDIN elsewhere in more general terms than + * simply a wrapper for the client's request body. + */ + + if (rv == APR_SUCCESS) { + if (rspbuflen) { + *rspbuflen = orspbuflen; + } + rv = handle_response(conf, r, s, temp_pool, request_id, rspbuf, + rspbuflen); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + APLOGNO(02514) "%s: Failed handling response " + "from %s", fn, conf->backend); + } + } + + apr_socket_close(s); + } + + if (rv != APR_SUCCESS) { + /* some sort of mechanical problem */ + r->status = HTTP_INTERNAL_SERVER_ERROR; + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + APLOGNO(02515) "%s: Received HTTP status %d", + fn, r->status); + } + + r->subprocess_env = saved_subprocess_env; + + if (r->status == HTTP_OK) { + /* An Authorizer application's 200 response may include headers + * whose names are prefixed with Variable-, and they should be + * available to subsequent phases via subprocess_env (and yanked + * from the client response). + */ + apr_table_t *vars = apr_table_make(temp_pool, /* not used to allocate + * any values that end up + * in r->(anything) + */ + 10); + apr_table_do(mod_fcgid_modify_auth_header, vars, + r->err_headers_out, NULL); + apr_table_do(fix_auth_header, r, vars, NULL); + } + + apr_pool_destroy(temp_pool); +} + +static int fcgi_check_authn(request_rec *r) +{ + const char *fn = "fcgi_check_authn"; + fcgi_dir_conf *dconf = ap_get_module_config(r->per_dir_config, + &authnz_fcgi_module); + const char *password = NULL; + const fcgi_provider_conf *conf; + const char *prov; + const char *auth_type; + char rspbuf[NON200_RESPONSE_BUF_LEN + 1]; /* extra byte for '\0' */ + apr_size_t rspbuflen = sizeof rspbuf - 1; + int res; + + prov = dconf && dconf->name ? dconf->name : NULL; + + if (!prov || !ap_cstr_casecmp(prov, "None")) { + return DECLINED; + } + + auth_type = ap_auth_type(r); + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + APLOGNO(02516) "%s, prov %s, authoritative %s, " + "require-basic %s, user expr? %s type %s", + fn, prov, + dconf->authoritative ? "yes" : "no", + dconf->require_basic_auth ? "yes" : "no", + dconf->user_expr ? "yes" : "no", + auth_type); + + if (auth_type && !ap_cstr_casecmp(auth_type, "Basic")) { + if ((res = ap_get_basic_auth_pw(r, &password))) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + APLOGNO(02517) "%s: couldn't retrieve basic auth " + "password", fn); + if (dconf->require_basic_auth) { + return res; + } + password = NULL; + } + } + + conf = apr_hash_get(fcgi_authn_providers, prov, APR_HASH_KEY_STRING); + if (!conf) { + ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, + APLOGNO(02518) "%s: can't find config for provider %s", + fn, prov); + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (APLOGrdebug(r)) { + log_provider_info(conf, r); + } + + req_rsp(r, conf, password, AP_FCGI_APACHE_ROLE_AUTHENTICATOR_STR, + rspbuf, &rspbuflen); + + if (r->status == HTTP_OK) { + if (dconf->user_expr) { + const char *err; + const char *user = ap_expr_str_exec(r, dconf->user_expr, + &err); + if (user && strlen(user)) { + r->user = apr_pstrdup(r->pool, user); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + APLOGNO(02519) "%s: Setting user to '%s'", + fn, r->user); + } + else if (user && dconf->default_user) { + r->user = apr_pstrdup(r->pool, dconf->default_user); + } + else if (user) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + APLOGNO(02520) "%s: Failure extracting user " + "after calling authorizer: user expression " + "yielded empty string (variable not set?)", + fn); + r->status = HTTP_INTERNAL_SERVER_ERROR; + } + else { + /* unexpected error, not even an empty string was returned */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + APLOGNO(02521) "%s: Failure extracting user " + "after calling authorizer: %s", + fn, err); + r->status = HTTP_INTERNAL_SERVER_ERROR; + } + } + if (conf->is_authz) { + /* combined authn/authz phase, so app won't be invoked for authz + * + * Remember that the request was successfully authorized by this + * provider. + */ + fcgi_request_notes *rnotes = apr_palloc(r->pool, sizeof(*rnotes)); + rnotes->successful_authnz_provider = conf->name; + ap_set_module_config(r->request_config, &authnz_fcgi_module, + rnotes); + } + } + else { + /* From the spec: + * For Authorizer response status values other than "200" (OK), the + * Web server denies access and sends the response status, headers, + * and content back to the HTTP client. + * But: + * This only makes sense if this authorizer is authoritative. + */ + if (rspbuflen > 0 && !dconf->authoritative) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, + APLOGNO(02522) "%s: Ignoring response body from non-" + "authoritative authorizer", fn); + } + else if (rspbuflen > 0) { + if (rspbuflen == sizeof rspbuf - 1) { + /* apr_brigade_flatten() interface :( */ + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, + APLOGNO(02523) "%s: possible overflow handling " + "response body", fn); + } + rspbuf[rspbuflen] = '\0'; /* we reserved an extra byte for '\0' */ + ap_custom_response(r, r->status, rspbuf); /* API makes a copy */ + } + } + + return r->status == HTTP_OK ? + OK : dconf->authoritative ? r->status : DECLINED; +} + +static authn_status fcgi_check_password(request_rec *r, const char *user, + const char *password) +{ + const char *fn = "fcgi_check_password"; + const char *prov = apr_table_get(r->notes, AUTHN_PROVIDER_NAME_NOTE); + const fcgi_provider_conf *conf; + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + APLOGNO(02524) "%s(%s, XXX): provider %s", + fn, user, prov); + + if (!prov) { + ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, + APLOGNO(02525) "%s: provider note isn't set", fn); + return AUTH_GENERAL_ERROR; + } + + conf = apr_hash_get(fcgi_authn_providers, prov, APR_HASH_KEY_STRING); + if (!conf) { + ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, + APLOGNO(02526) "%s: can't find config for provider %s", + fn, prov); + return AUTH_GENERAL_ERROR; + } + + if (APLOGrdebug(r)) { + log_provider_info(conf, r); + } + + req_rsp(r, conf, password, + /* combined authn and authz: FCGI_APACHE_ROLE not set */ + conf->is_authz ? NULL : AP_FCGI_APACHE_ROLE_AUTHENTICATOR_STR, + NULL, NULL); + + if (r->status == HTTP_OK) { + if (conf->is_authz) { + /* combined authn/authz phase, so app won't be invoked for authz + * + * Remember that the request was successfully authorized by this + * provider. + */ + fcgi_request_notes *rnotes = apr_palloc(r->pool, sizeof(*rnotes)); + rnotes->successful_authnz_provider = conf->name; + ap_set_module_config(r->request_config, &authnz_fcgi_module, + rnotes); + } + return AUTH_GRANTED; + } + else if (r->status == HTTP_INTERNAL_SERVER_ERROR) { + return AUTH_GENERAL_ERROR; + } + else { + return AUTH_DENIED; + } +} + +static const authn_provider fcgi_authn_provider = { + &fcgi_check_password, + NULL /* get-realm-hash not supported */ +}; + +static authz_status fcgi_authz_check(request_rec *r, + const char *require_line, + const void *parsed_require_line) +{ + const char *fn = "fcgi_authz_check"; + const char *prov = apr_table_get(r->notes, AUTHZ_PROVIDER_NAME_NOTE); + const fcgi_provider_conf *conf; + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + APLOGNO(02527) "%s(%s)", fn, require_line); + + if (!prov) { + ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, + APLOGNO(02528) "%s: provider note isn't set", fn); + return AUTHZ_GENERAL_ERROR; + } + + conf = apr_hash_get(fcgi_authz_providers, prov, APR_HASH_KEY_STRING); + if (!conf) { + ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, + APLOGNO(02529) "%s: can't find config for provider %s", + fn, prov); + return AUTHZ_GENERAL_ERROR; + } + + if (APLOGrdebug(r)) { + log_provider_info(conf, r); + } + + if (!r->user) { + return AUTHZ_DENIED_NO_USER; + } + + if (conf->is_authn) { + /* combined authn/authz phase, so app won't be invoked for authz + * + * If the provider already successfully authorized this request, + * success. + */ + fcgi_request_notes *rnotes = ap_get_module_config(r->request_config, + &authnz_fcgi_module); + if (rnotes + && rnotes->successful_authnz_provider + && !strcmp(rnotes->successful_authnz_provider, conf->name)) { + return AUTHZ_GRANTED; + } + else { + return AUTHZ_DENIED; + } + } + else { + req_rsp(r, conf, NULL, AP_FCGI_APACHE_ROLE_AUTHORIZER_STR, NULL, NULL); + + if (r->status == HTTP_OK) { + return AUTHZ_GRANTED; + } + else if (r->status == HTTP_INTERNAL_SERVER_ERROR) { + return AUTHZ_GENERAL_ERROR; + } + else { + return AUTHZ_DENIED; + } + } +} + +static const char *fcgi_authz_parse(cmd_parms *cmd, const char *require_line, + const void **parsed_require_line) +{ + /* Allowed form: Require [not] registered-provider-name<EOS> + */ + if (strcmp(require_line, "")) { + return "mod_authnz_fcgi doesn't support restrictions on providers " + "(i.e., multiple require args)"; + } + + return NULL; +} + +static const authz_provider fcgi_authz_provider = { + &fcgi_authz_check, + &fcgi_authz_parse, +}; + +static const char *fcgi_check_authn_provider(cmd_parms *cmd, + void *d, + int argc, + char *const argv[]) +{ + const char *dname = "AuthnzFcgiCheckAuthnProvider"; + fcgi_dir_conf *dc = d; + int ca = 0; + + if (ca >= argc) { + return apr_pstrcat(cmd->pool, dname, ": No provider given", NULL); + } + + dc->name = argv[ca]; + ca++; + + if (!strcasecmp(dc->name, "None")) { + if (ca < argc) { + return "Options aren't supported with \"None\""; + } + } + + while (ca < argc) { + const char *var = argv[ca], *val; + int badarg = 0; + + ca++; + + /* at present, everything needs an argument */ + if (ca >= argc) { + return apr_pstrcat(cmd->pool, dname, ": ", var, + "needs an argument", NULL); + } + + val = argv[ca]; + ca++; + + if (!strcasecmp(var, "Authoritative")) { + if (!strcasecmp(val, "On")) { + dc->authoritative = 1; + } + else if (!strcasecmp(val, "Off")) { + dc->authoritative = 0; + } + else { + badarg = 1; + } + } + else if (!strcasecmp(var, "DefaultUser")) { + dc->default_user = val; + } + else if (!strcasecmp(var, "RequireBasicAuth")) { + if (!strcasecmp(val, "On")) { + dc->require_basic_auth = 1; + } + else if (!strcasecmp(val, "Off")) { + dc->require_basic_auth = 0; + } + else { + badarg = 1; + } + } + else if (!strcasecmp(var, "UserExpr")) { + const char *err; + int flags = AP_EXPR_FLAG_DONT_VARY | AP_EXPR_FLAG_RESTRICTED + | AP_EXPR_FLAG_STRING_RESULT; + + dc->user_expr = ap_expr_parse_cmd(cmd, val, + flags, &err, NULL); + if (err) { + return apr_psprintf(cmd->pool, "%s: Error parsing '%s': '%s'", + dname, val, err); + } + } + else { + return apr_pstrcat(cmd->pool, dname, ": Unexpected option '", + var, "'", NULL); + } + if (badarg) { + return apr_pstrcat(cmd->pool, dname, ": Bad argument '", + val, "' to option '", var, "'", NULL); + } + } + + return NULL; +} + +/* AuthnzFcgiAuthDefineProvider {authn|authz|authnz} provider-name \ + * fcgi://backendhost:backendport/ + */ +static const char *fcgi_define_provider(cmd_parms *cmd, + void *d, + int argc, + char *const argv[]) +{ + const char *dname = "AuthnzFcgiDefineProvider"; + ap_rxplus_t *fcgi_backend_regex; + apr_status_t rv; + char *host; + const char *err, *stype; + fcgi_provider_conf *conf = apr_pcalloc(cmd->pool, sizeof(*conf)); + int ca = 0, rc, port; + + fcgi_backend_regex = ap_rxplus_compile(cmd->pool, FCGI_BACKEND_REGEX_STR); + if (!fcgi_backend_regex) { + return apr_psprintf(cmd->pool, + "%s: failed to compile regexec '%s'", + dname, FCGI_BACKEND_REGEX_STR); + } + + err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if (err) + return err; + + if (ca >= argc) { + return apr_pstrcat(cmd->pool, dname, ": No type given", NULL); + } + + stype = argv[ca]; + ca++; + + if (!strcasecmp(stype, "authn")) { + conf->is_authn = 1; + } + else if (!strcasecmp(stype, "authz")) { + conf->is_authz = 1; + } + else if (!strcasecmp(stype, "authnz")) { + conf->is_authn = conf->is_authz = 1; + } + else { + return apr_pstrcat(cmd->pool, + dname, + ": Invalid provider type ", + stype, + NULL); + } + + if (ca >= argc) { + return apr_pstrcat(cmd->pool, dname, ": No provider name given", NULL); + } + conf->name = argv[ca]; + ca++; + + if (ca >= argc) { + return apr_pstrcat(cmd->pool, dname, ": No backend-address given", + NULL); + } + + rc = ap_rxplus_exec(cmd->pool, fcgi_backend_regex, argv[ca], NULL); + if (!rc || ap_rxplus_nmatch(fcgi_backend_regex) != 3) { + return apr_pstrcat(cmd->pool, + dname, ": backend-address '", + argv[ca], + "' has invalid form", + NULL); + } + + host = ap_rxplus_pmatch(cmd->pool, fcgi_backend_regex, 1); + if (host[0] == '[' && host[strlen(host) - 1] == ']') { + host += 1; + host[strlen(host) - 1] = '\0'; + } + + port = atoi(ap_rxplus_pmatch(cmd->pool, fcgi_backend_regex, 2)); + if (port > 65535) { + return apr_pstrcat(cmd->pool, + dname, ": backend-address '", + argv[ca], + "' has invalid port", + NULL); + } + + conf->backend = argv[ca]; + conf->host = host; + conf->port = port; + ca++; + + rv = apr_sockaddr_info_get(&conf->backend_addrs, conf->host, + APR_UNSPEC, conf->port, 0, cmd->pool); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, rv, NULL, + APLOGNO(02530) "Address %s could not be resolved", + conf->backend); + return apr_pstrcat(cmd->pool, + dname, + ": Error resolving backend address", + NULL); + } + + if (ca != argc) { + return apr_pstrcat(cmd->pool, + dname, + ": Unexpected parameter ", + argv[ca], + NULL); + } + + if (conf->is_authn) { + apr_hash_set(fcgi_authn_providers, conf->name, APR_HASH_KEY_STRING, + conf); + ap_register_auth_provider(cmd->pool, AUTHN_PROVIDER_GROUP, + conf->name, + AUTHN_PROVIDER_VERSION, + &fcgi_authn_provider, + AP_AUTH_INTERNAL_PER_CONF); + } + + if (conf->is_authz) { + apr_hash_set(fcgi_authz_providers, conf->name, APR_HASH_KEY_STRING, + conf); + ap_register_auth_provider(cmd->pool, AUTHZ_PROVIDER_GROUP, + conf->name, + AUTHZ_PROVIDER_VERSION, + &fcgi_authz_provider, + AP_AUTH_INTERNAL_PER_CONF); + } + + return NULL; +} + +static const command_rec fcgi_cmds[] = { + AP_INIT_TAKE_ARGV("AuthnzFcgiDefineProvider", + fcgi_define_provider, + NULL, + RSRC_CONF, + "Define a FastCGI authn and/or authz provider"), + + AP_INIT_TAKE_ARGV("AuthnzFcgiCheckAuthnProvider", + fcgi_check_authn_provider, + NULL, + OR_FILEINFO, + "Enable/disable a FastCGI authorizer to handle " + "check_authn phase"), + + {NULL} +}; + +static int fcgi_pre_config(apr_pool_t *pconf, apr_pool_t *plog, + apr_pool_t *ptemp) +{ + fcgi_authn_providers = apr_hash_make(pconf); + fcgi_authz_providers = apr_hash_make(pconf); + + return OK; +} + +static void fcgi_register_hooks(apr_pool_t *p) +{ + static const char * const auth_basic_runs_after_me[] = + {"mod_auth_basic.c", NULL}; /* to allow for custom response */ + + ap_hook_pre_config(fcgi_pre_config, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_check_authn(fcgi_check_authn, NULL, auth_basic_runs_after_me, + APR_HOOK_MIDDLE, AP_AUTH_INTERNAL_PER_CONF); +} + +static void *create_dir_conf(apr_pool_t *p, char *dummy) +{ + fcgi_dir_conf *dconf = apr_pcalloc(p, sizeof(fcgi_dir_conf)); + + dconf->authoritative = 1; + return dconf; +} + +static void *merge_dir_conf(apr_pool_t *p, void *basev, void *overridesv) +{ + fcgi_dir_conf *a = (fcgi_dir_conf *)apr_pcalloc(p, sizeof(*a)); + fcgi_dir_conf *base = (fcgi_dir_conf *)basev, + *over = (fcgi_dir_conf *)overridesv; + + /* currently we just have a single directive applicable to a + * directory, so if it is set then grab all fields from fcgi_dir_conf + */ + if (over->name) { + memcpy(a, over, sizeof(*a)); + } + else { + memcpy(a, base, sizeof(*a)); + } + + return a; +} + +AP_DECLARE_MODULE(authnz_fcgi) = +{ + STANDARD20_MODULE_STUFF, + create_dir_conf, /* dir config creater */ + merge_dir_conf, /* dir merger */ + NULL, /* server config */ + NULL, /* merge server config */ + fcgi_cmds, /* command apr_table_t */ + fcgi_register_hooks /* register hooks */ +}; diff --git a/modules/aaa/mod_authnz_fcgi.dep b/modules/aaa/mod_authnz_fcgi.dep new file mode 100644 index 0000000..7424929 --- /dev/null +++ b/modules/aaa/mod_authnz_fcgi.dep @@ -0,0 +1,61 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authnz_fcgi.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authnz_fcgi.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_fcgi.h"\ + "..\..\include\util_filter.h"\ + "..\..\include\util_script.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_lib.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_authnz_fcgi.dsp b/modules/aaa/mod_authnz_fcgi.dsp new file mode 100644 index 0000000..a731e4f --- /dev/null +++ b/modules/aaa/mod_authnz_fcgi.dsp @@ -0,0 +1,119 @@ +# Microsoft Developer Studio Project File - Name="mod_authnz_fcgi" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authnz_fcgi - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authnz_fcgi.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authnz_fcgi.mak" CFG="mod_authnz_fcgi - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authnz_fcgi - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authnz_fcgi - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authnz_fcgi - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../database" /D "authnz_fcgi_DECLARE_EXPORT" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_authnz_fcgi_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authnz_fcgi.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authnz_fcgi.so" /d LONG_NAME="authnz_fcgi_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authnz_fcgi.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authnz_fcgi.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authnz_fcgi.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authnz_fcgi.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authnz_fcgi.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authnz_fcgi - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../database" /D "authnz_fcgi_DECLARE_EXPORT" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_authnz_fcgi_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authnz_fcgi.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authnz_fcgi.so" /d LONG_NAME="authnz_fcgi_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authnz_fcgi.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authnz_fcgi.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authnz_fcgi.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authnz_fcgi.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authnz_fcgi.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authnz_fcgi - Win32 Release" +# Name "mod_authnz_fcgi - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_authnz_fcgi.c +# End Source File +# Begin Source File + +SOURCE=..\..\include\mod_auth.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\util_fcgi.h +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authnz_fcgi.mak b/modules/aaa/mod_authnz_fcgi.mak new file mode 100644 index 0000000..772cae2 --- /dev/null +++ b/modules/aaa/mod_authnz_fcgi.mak @@ -0,0 +1,353 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authnz_fcgi.dsp +!IF "$(CFG)" == "" +CFG=mod_authnz_fcgi - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_authnz_fcgi - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_authnz_fcgi - Win32 Release" && "$(CFG)" != "mod_authnz_fcgi - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authnz_fcgi.mak" CFG="mod_authnz_fcgi - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authnz_fcgi - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authnz_fcgi - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authnz_fcgi - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authnz_fcgi.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authnz_fcgi.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authnz_fcgi.obj" + -@erase "$(INTDIR)\mod_authnz_fcgi.res" + -@erase "$(INTDIR)\mod_authnz_fcgi_src.idb" + -@erase "$(INTDIR)\mod_authnz_fcgi_src.pdb" + -@erase "$(OUTDIR)\mod_authnz_fcgi.exp" + -@erase "$(OUTDIR)\mod_authnz_fcgi.lib" + -@erase "$(OUTDIR)\mod_authnz_fcgi.pdb" + -@erase "$(OUTDIR)\mod_authnz_fcgi.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../database" /D "authnz_fcgi_DECLARE_EXPORT" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authnz_fcgi_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authnz_fcgi.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authnz_fcgi.so" /d LONG_NAME="authnz_fcgi_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authnz_fcgi.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authnz_fcgi.pdb" /debug /out:"$(OUTDIR)\mod_authnz_fcgi.so" /implib:"$(OUTDIR)\mod_authnz_fcgi.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authnz_fcgi.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authnz_fcgi.obj" \ + "$(INTDIR)\mod_authnz_fcgi.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" + +"$(OUTDIR)\mod_authnz_fcgi.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authnz_fcgi.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authnz_fcgi.so" + if exist .\Release\mod_authnz_fcgi.so.manifest mt.exe -manifest .\Release\mod_authnz_fcgi.so.manifest -outputresource:.\Release\mod_authnz_fcgi.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authnz_fcgi - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authnz_fcgi.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authnz_fcgi.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authnz_fcgi.obj" + -@erase "$(INTDIR)\mod_authnz_fcgi.res" + -@erase "$(INTDIR)\mod_authnz_fcgi_src.idb" + -@erase "$(INTDIR)\mod_authnz_fcgi_src.pdb" + -@erase "$(OUTDIR)\mod_authnz_fcgi.exp" + -@erase "$(OUTDIR)\mod_authnz_fcgi.lib" + -@erase "$(OUTDIR)\mod_authnz_fcgi.pdb" + -@erase "$(OUTDIR)\mod_authnz_fcgi.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../database" /D "authnz_fcgi_DECLARE_EXPORT" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authnz_fcgi_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authnz_fcgi.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authnz_fcgi.so" /d LONG_NAME="authnz_fcgi_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authnz_fcgi.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authnz_fcgi.pdb" /debug /out:"$(OUTDIR)\mod_authnz_fcgi.so" /implib:"$(OUTDIR)\mod_authnz_fcgi.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authnz_fcgi.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authnz_fcgi.obj" \ + "$(INTDIR)\mod_authnz_fcgi.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" + +"$(OUTDIR)\mod_authnz_fcgi.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authnz_fcgi.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authnz_fcgi.so" + if exist .\Debug\mod_authnz_fcgi.so.manifest mt.exe -manifest .\Debug\mod_authnz_fcgi.so.manifest -outputresource:.\Debug\mod_authnz_fcgi.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authnz_fcgi.dep") +!INCLUDE "mod_authnz_fcgi.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authnz_fcgi.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authnz_fcgi - Win32 Release" || "$(CFG)" == "mod_authnz_fcgi - Win32 Debug" + +!IF "$(CFG)" == "mod_authnz_fcgi - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authnz_fcgi - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authnz_fcgi - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authnz_fcgi - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authnz_fcgi - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authnz_fcgi - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authnz_fcgi - Win32 Release" + + +"$(INTDIR)\mod_authnz_fcgi.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authnz_fcgi.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authnz_fcgi.so" /d LONG_NAME="authnz_fcgi_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authnz_fcgi - Win32 Debug" + + +"$(INTDIR)\mod_authnz_fcgi.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authnz_fcgi.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authnz_fcgi.so" /d LONG_NAME="authnz_fcgi_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authnz_fcgi.c + +"$(INTDIR)\mod_authnz_fcgi.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authnz_ldap.c b/modules/aaa/mod_authnz_ldap.c new file mode 100644 index 0000000..a7b4939 --- /dev/null +++ b/modules/aaa/mod_authnz_ldap.c @@ -0,0 +1,1977 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ap_provider.h" +#include "httpd.h" +#include "http_config.h" +#include "ap_provider.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" +#include "util_ldap.h" + +#include "mod_auth.h" + +#include "apr_strings.h" +#include "apr_xlate.h" +#define APR_WANT_STRFUNC +#include "apr_want.h" +#include "apr_lib.h" + +#include <ctype.h> + +#if !APR_HAS_LDAP +#error mod_authnz_ldap requires APR-util to have LDAP support built in. To fix add --with-ldap to ./configure. +#endif + +static char *default_attributes[3] = { "member", "uniqueMember", NULL }; + +typedef struct { + apr_pool_t *pool; /* Pool that this config is allocated from */ +#if APR_HAS_THREADS + apr_thread_mutex_t *lock; /* Lock for this config */ +#endif + + /* These parameters are all derived from the AuthLDAPURL directive */ + char *url; /* String representation of the URL */ + + char *host; /* Name of the LDAP server (or space separated list) */ + int port; /* Port of the LDAP server */ + char *basedn; /* Base DN to do all searches from */ + char *attribute; /* Attribute to search for */ + char **attributes; /* Array of all the attributes to return */ + int scope; /* Scope of the search */ + char *filter; /* Filter to further limit the search */ + deref_options deref; /* how to handle alias dereferening */ + char *binddn; /* DN to bind to server (can be NULL) */ + char *bindpw; /* Password to bind to server (can be NULL) */ + int bind_authoritative; /* If true, will return errors when bind fails */ + + int user_is_dn; /* If true, r->user is replaced by DN during authn */ + char *remote_user_attribute; /* If set, r->user is replaced by this attribute during authn */ + int compare_dn_on_server; /* If true, will use server to do DN compare */ + + int have_ldap_url; /* Set if we have found an LDAP url */ + + apr_array_header_t *groupattr; /* List of Group attributes identifying user members. Default:"member uniqueMember" */ + int group_attrib_is_dn; /* If true, the group attribute is the DN, otherwise, + it's the exact string passed by the HTTP client */ + char **sgAttributes; /* Array of strings constructed (post-config) from subgroupattrs. Last entry is NULL. */ + apr_array_header_t *subgroupclasses; /* List of object classes of sub-groups. Default:"groupOfNames groupOfUniqueNames" */ + int maxNestingDepth; /* Maximum recursive nesting depth permitted during subgroup processing. Default: 10 */ + + int secure; /* True if SSL connections are requested */ + char *authz_prefix; /* Prefix for environment variables added during authz */ + int initial_bind_as_user; /* true if we should try to bind (to lookup DN) directly with the basic auth username */ + ap_regex_t *bind_regex; /* basic auth -> bind'able username regex */ + const char *bind_subst; /* basic auth -> bind'able username substitution */ + int search_as_user; /* true if authz searches should be done with the users credentials (when we did authn) */ + int compare_as_user; /* true if authz compares should be done with the users credentials (when we did authn) */ +} authn_ldap_config_t; + +typedef struct { + char *dn; /* The saved dn from a successful search */ + char *user; /* The username provided by the client */ + const char **vals; /* The additional values pulled during the DN search*/ + char *password; /* if this module successfully authenticates, the basic auth password, else null */ +} authn_ldap_request_t; + +enum auth_ldap_phase { + LDAP_AUTHN, LDAP_AUTHZ +}; + +enum auth_ldap_optype { + LDAP_SEARCH, LDAP_COMPARE, LDAP_COMPARE_AND_SEARCH /* nested groups */ +}; + +/* maximum group elements supported */ +#define GROUPATTR_MAX_ELTS 10 + +module AP_MODULE_DECLARE_DATA authnz_ldap_module; + +static APR_OPTIONAL_FN_TYPE(uldap_connection_close) *util_ldap_connection_close; +static APR_OPTIONAL_FN_TYPE(uldap_connection_find) *util_ldap_connection_find; +static APR_OPTIONAL_FN_TYPE(uldap_cache_comparedn) *util_ldap_cache_comparedn; +static APR_OPTIONAL_FN_TYPE(uldap_cache_compare) *util_ldap_cache_compare; +static APR_OPTIONAL_FN_TYPE(uldap_cache_check_subgroups) *util_ldap_cache_check_subgroups; +static APR_OPTIONAL_FN_TYPE(uldap_cache_checkuserid) *util_ldap_cache_checkuserid; +static APR_OPTIONAL_FN_TYPE(uldap_cache_getuserdn) *util_ldap_cache_getuserdn; +static APR_OPTIONAL_FN_TYPE(uldap_ssl_supported) *util_ldap_ssl_supported; + +static apr_hash_t *charset_conversions = NULL; +static char *to_charset = NULL; /* UTF-8 identifier derived from the charset.conv file */ + + +/* Derive a code page ID give a language name or ID */ +static char* derive_codepage_from_lang (apr_pool_t *p, char *language) +{ + char *charset; + + if (!language) /* our default codepage */ + return apr_pstrdup(p, "ISO-8859-1"); + + charset = (char*) apr_hash_get(charset_conversions, language, APR_HASH_KEY_STRING); + + /* + * Test if language values like 'en-US' return a match from the charset + * conversion map when shortened to 'en'. + */ + if (!charset && strlen(language) > 3 && language[2] == '-') { + char *language_short = apr_pstrndup(p, language, 2); + charset = (char*) apr_hash_get(charset_conversions, language_short, APR_HASH_KEY_STRING); + } + + if (charset) { + charset = apr_pstrdup(p, charset); + } + + return charset; +} + +static apr_xlate_t* get_conv_set (request_rec *r) +{ + char *lang_line = (char*)apr_table_get(r->headers_in, "accept-language"); + char *lang; + apr_xlate_t *convset; + + if (lang_line) { + lang_line = apr_pstrdup(r->pool, lang_line); + for (lang = lang_line;*lang;lang++) { + if ((*lang == ',') || (*lang == ';')) { + *lang = '\0'; + break; + } + } + lang = derive_codepage_from_lang(r->pool, lang_line); + + if (lang && (apr_xlate_open(&convset, to_charset, lang, r->pool) == APR_SUCCESS)) { + return convset; + } + } + + return NULL; +} + + +static const char* authn_ldap_xlate_password(request_rec *r, + const char* sent_password) +{ + apr_xlate_t *convset = NULL; + apr_size_t inbytes; + apr_size_t outbytes; + char *outbuf; + + if (charset_conversions && (convset = get_conv_set(r)) ) { + inbytes = strlen(sent_password); + outbytes = (inbytes+1)*3; + outbuf = apr_pcalloc(r->pool, outbytes); + + /* Convert the password to UTF-8. */ + if (apr_xlate_conv_buffer(convset, sent_password, &inbytes, outbuf, + &outbytes) == APR_SUCCESS) + return outbuf; + } + + return sent_password; +} + + +/* + * Build the search filter, or at least as much of the search filter that + * will fit in the buffer. We don't worry about the buffer not being able + * to hold the entire filter. If the buffer wasn't big enough to hold the + * filter, ldap_search_s will complain, but the only situation where this + * is likely to happen is if the client sent a really, really long + * username, most likely as part of an attack. + * + * The search filter consists of the filter provided with the URL, + * combined with a filter made up of the attribute provided with the URL, + * and the actual username passed by the HTTP client. For example, assume + * that the LDAP URL is + * + * ldap://ldap.airius.com/ou=People, o=Airius?uid??(posixid=*) + * + * Further, assume that the userid passed by the client was `userj'. The + * search filter will be (&(posixid=*)(uid=userj)). + */ +#define FILTER_LENGTH MAX_STRING_LEN +static void authn_ldap_build_filter(char *filtbuf, + request_rec *r, + const char* sent_user, + const char* sent_filter, + authn_ldap_config_t *sec) +{ + char *p, *q, *filtbuf_end; + char *user, *filter; + apr_xlate_t *convset = NULL; + apr_size_t inbytes; + apr_size_t outbytes; + char *outbuf; + int nofilter = 0; + + if (sent_user != NULL) { + user = apr_pstrdup (r->pool, sent_user); + } + else + return; + + if (sent_filter != NULL) { + filter = apr_pstrdup (r->pool, sent_filter); + } + else + filter = sec->filter; + + if (charset_conversions) { + convset = get_conv_set(r); + } + + if (convset) { + inbytes = strlen(user); + outbytes = (inbytes+1)*3; + outbuf = apr_pcalloc(r->pool, outbytes); + + /* Convert the user name to UTF-8. This is only valid for LDAP v3 */ + if (apr_xlate_conv_buffer(convset, user, &inbytes, outbuf, &outbytes) == APR_SUCCESS) { + user = apr_pstrdup(r->pool, outbuf); + } + } + + /* + * Create the first part of the filter, which consists of the + * config-supplied portions. + */ + + if ((nofilter = (filter && !strcasecmp(filter, "none")))) { + apr_snprintf(filtbuf, FILTER_LENGTH, "(%s=", sec->attribute); + } + else { + apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(%s=", filter, sec->attribute); + } + + /* + * Now add the client-supplied username to the filter, ensuring that any + * LDAP filter metachars are escaped. + */ + filtbuf_end = filtbuf + FILTER_LENGTH - 1; +#if APR_HAS_MICROSOFT_LDAPSDK + for (p = user, q=filtbuf + strlen(filtbuf); + *p && q < filtbuf_end; ) { + if (strchr("*()\\", *p) != NULL) { + if ( q + 3 >= filtbuf_end) + break; /* Don't write part of escape sequence if we can't write all of it */ + *q++ = '\\'; + switch ( *p++ ) + { + case '*': + *q++ = '2'; + *q++ = 'a'; + break; + case '(': + *q++ = '2'; + *q++ = '8'; + break; + case ')': + *q++ = '2'; + *q++ = '9'; + break; + case '\\': + *q++ = '5'; + *q++ = 'c'; + break; + } + } + else + *q++ = *p++; + } +#else + for (p = user, q=filtbuf + strlen(filtbuf); + *p && q < filtbuf_end; *q++ = *p++) { + if (strchr("*()\\", *p) != NULL) { + *q++ = '\\'; + if (q >= filtbuf_end) { + break; + } + } + } +#endif + *q = '\0'; + + /* + * Append the closing parens of the filter, unless doing so would + * overrun the buffer. + */ + + if (nofilter) { + if (q + 1 <= filtbuf_end) + strcat(filtbuf, ")"); + } + else { + if (q + 2 <= filtbuf_end) + strcat(filtbuf, "))"); + } + +} + +static void *create_authnz_ldap_dir_config(apr_pool_t *p, char *d) +{ + authn_ldap_config_t *sec = + (authn_ldap_config_t *)apr_pcalloc(p, sizeof(authn_ldap_config_t)); + + sec->pool = p; +#if APR_HAS_THREADS + apr_thread_mutex_create(&sec->lock, APR_THREAD_MUTEX_DEFAULT, p); +#endif +/* + sec->authz_enabled = 1; +*/ + sec->groupattr = apr_array_make(p, GROUPATTR_MAX_ELTS, + sizeof(struct mod_auth_ldap_groupattr_entry_t)); + sec->subgroupclasses = apr_array_make(p, GROUPATTR_MAX_ELTS, + sizeof(struct mod_auth_ldap_groupattr_entry_t)); + + sec->have_ldap_url = 0; + sec->url = ""; + sec->host = NULL; + sec->binddn = NULL; + sec->bindpw = NULL; + sec->bind_authoritative = 1; + sec->deref = always; + sec->group_attrib_is_dn = 1; + sec->secure = -1; /*Initialize to unset*/ + sec->maxNestingDepth = 10; + sec->sgAttributes = apr_pcalloc(p, sizeof (char *) * GROUPATTR_MAX_ELTS + 1); + + sec->user_is_dn = 0; + sec->remote_user_attribute = NULL; + sec->compare_dn_on_server = 0; + + sec->authz_prefix = AUTHZ_PREFIX; + + return sec; +} + +static apr_status_t authnz_ldap_cleanup_connection_close(void *param) +{ + util_ldap_connection_t *ldc = param; + util_ldap_connection_close(ldc); + return APR_SUCCESS; +} + +static int set_request_vars(request_rec *r, enum auth_ldap_phase phase) { + char *prefix = NULL; + int prefix_len; + int remote_user_attribute_set = 0; + authn_ldap_request_t *req = + (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module); + authn_ldap_config_t *sec = + (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module); + const char **vals = req->vals; + + prefix = (phase == LDAP_AUTHN) ? AUTHN_PREFIX : sec->authz_prefix; + prefix_len = strlen(prefix); + + if (sec->attributes && vals) { + apr_table_t *e = r->subprocess_env; + int i = 0; + while (sec->attributes[i]) { + char *str = apr_pstrcat(r->pool, prefix, sec->attributes[i], NULL); + int j = prefix_len; + while (str[j]) { + str[j] = apr_toupper(str[j]); + j++; + } + apr_table_setn(e, str, vals[i] ? vals[i] : ""); + + /* handle remote_user_attribute, if set */ + if ((phase == LDAP_AUTHN) && + sec->remote_user_attribute && + !strcmp(sec->remote_user_attribute, sec->attributes[i])) { + r->user = (char *)apr_pstrdup(r->pool, vals[i]); + remote_user_attribute_set = 1; + } + i++; + } + } + return remote_user_attribute_set; +} + +static const char *ldap_determine_binddn(request_rec *r, const char *user) { + authn_ldap_config_t *sec = + (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module); + const char *result = user; + ap_regmatch_t regm[AP_MAX_REG_MATCH]; + + if (NULL == user || NULL == sec || !sec->bind_regex || !sec->bind_subst) { + return result; + } + + if (!ap_regexec(sec->bind_regex, user, AP_MAX_REG_MATCH, regm, 0)) { + char *substituted = ap_pregsub(r->pool, sec->bind_subst, user, AP_MAX_REG_MATCH, regm); + if (NULL != substituted) { + result = substituted; + } + } + + apr_table_set(r->subprocess_env, "LDAP_BINDASUSER", result); + + return result; +} + + +/* Some LDAP servers restrict who can search or compare, and the hard-coded ID + * might be good for the DN lookup but not for later operations. + */ +static util_ldap_connection_t *get_connection_for_authz(request_rec *r, enum auth_ldap_optype type) { + authn_ldap_request_t *req = + (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module); + authn_ldap_config_t *sec = + (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module); + + char *binddn = sec->binddn; + char *bindpw = sec->bindpw; + + /* If the per-request config isn't set, we didn't authenticate this user, and leave the default credentials */ + if (req && req->password && + ((type == LDAP_SEARCH && sec->search_as_user) || + (type == LDAP_COMPARE && sec->compare_as_user) || + (type == LDAP_COMPARE_AND_SEARCH && sec->compare_as_user && sec->search_as_user))){ + binddn = req->dn; + bindpw = req->password; + } + + return util_ldap_connection_find(r, sec->host, sec->port, + binddn, bindpw, + sec->deref, sec->secure); +} +/* + * Authentication Phase + * -------------------- + * + * This phase authenticates the credentials the user has sent with + * the request (ie the username and password are checked). This is done + * by making an attempt to bind to the LDAP server using this user's + * DN and the supplied password. + * + */ +static authn_status authn_ldap_check_password(request_rec *r, const char *user, + const char *password) +{ + char filtbuf[FILTER_LENGTH]; + authn_ldap_config_t *sec = + (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module); + + util_ldap_connection_t *ldc = NULL; + int result = 0; + int remote_user_attribute_set = 0; + const char *dn = NULL; + const char *utfpassword; + + authn_ldap_request_t *req = + (authn_ldap_request_t *)apr_pcalloc(r->pool, sizeof(authn_ldap_request_t)); + ap_set_module_config(r->request_config, &authnz_ldap_module, req); + +/* + if (!sec->enabled) { + return AUTH_USER_NOT_FOUND; + } +*/ + + /* + * Basic sanity checks before any LDAP operations even happen. + */ + if (!sec->have_ldap_url) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02558) + "no AuthLDAPURL"); + + return AUTH_GENERAL_ERROR; + } + + /* Get the password that the client sent */ + if (password == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01692) + "auth_ldap authenticate: no password specified"); + return AUTH_GENERAL_ERROR; + } + + if (user == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01693) + "auth_ldap authenticate: no user specified"); + return AUTH_GENERAL_ERROR; + } + + /* + * A bind to the server with an empty password always succeeds, so + * we check to ensure that the password is not empty. This implies + * that users who actually do have empty passwords will never be + * able to authenticate with this module. I don't see this as a big + * problem. + */ + if (!(*password)) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(10263) + "auth_ldap authenticate: empty password specified"); + return AUTH_DENIED; + } + + /* There is a good AuthLDAPURL, right? */ + if (sec->host) { + const char *binddn = sec->binddn; + const char *bindpw = sec->bindpw; + if (sec->initial_bind_as_user) { + bindpw = password; + binddn = ldap_determine_binddn(r, user); + } + + ldc = util_ldap_connection_find(r, sec->host, sec->port, + binddn, bindpw, + sec->deref, sec->secure); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01690) + "auth_ldap authenticate: no sec->host - weird...?"); + return AUTH_GENERAL_ERROR; + } + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01691) + "auth_ldap authenticate: using URL %s", sec->url); + + /* build the username filter */ + authn_ldap_build_filter(filtbuf, r, user, NULL, sec); + + ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, + "auth_ldap authenticate: final authn filter is %s", filtbuf); + + /* convert password to utf-8 */ + utfpassword = authn_ldap_xlate_password(r, password); + + /* do the user search */ + result = util_ldap_cache_checkuserid(r, ldc, sec->url, sec->basedn, sec->scope, + sec->attributes, filtbuf, utfpassword, + &dn, &(req->vals)); + util_ldap_connection_close(ldc); + + /* handle bind failure */ + if (result != LDAP_SUCCESS) { + if (!sec->bind_authoritative) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01694) + "auth_ldap authenticate: user %s authentication failed; " + "URI %s [%s][%s] (not authoritative)", + user, r->uri, ldc->reason, ldap_err2string(result)); + return AUTH_USER_NOT_FOUND; + } + + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01695) + "auth_ldap authenticate: " + "user %s authentication failed; URI %s [%s][%s]", + user, r->uri, ldc->reason, ldap_err2string(result)); + + /* talking to a primitive LDAP server (like RACF-over-LDAP) that doesn't return specific errors */ + if (!strcasecmp(sec->filter, "none") && LDAP_OTHER == result) { + return AUTH_USER_NOT_FOUND; + } + + return (LDAP_NO_SUCH_OBJECT == result) ? AUTH_USER_NOT_FOUND +#ifdef LDAP_SECURITY_ERROR + : (LDAP_SECURITY_ERROR(result)) ? AUTH_DENIED +#else + : (LDAP_INAPPROPRIATE_AUTH == result) ? AUTH_DENIED + : (LDAP_INVALID_CREDENTIALS == result) ? AUTH_DENIED +#ifdef LDAP_INSUFFICIENT_ACCESS + : (LDAP_INSUFFICIENT_ACCESS == result) ? AUTH_DENIED +#endif +#ifdef LDAP_INSUFFICIENT_RIGHTS + : (LDAP_INSUFFICIENT_RIGHTS == result) ? AUTH_DENIED +#endif +#endif +#ifdef LDAP_CONSTRAINT_VIOLATION + /* At least Sun Directory Server sends this if a user is + * locked. This is not covered by LDAP_SECURITY_ERROR. + */ + : (LDAP_CONSTRAINT_VIOLATION == result) ? AUTH_DENIED +#endif + : AUTH_GENERAL_ERROR; + } + + /* mark the user and DN */ + req->dn = apr_pstrdup(r->pool, dn); + req->user = apr_pstrdup(r->pool, user); + req->password = apr_pstrdup(r->pool, password); + if (sec->user_is_dn) { + r->user = req->dn; + } + + /* add environment variables */ + remote_user_attribute_set = set_request_vars(r, LDAP_AUTHN); + + /* sanity check */ + if (sec->remote_user_attribute && !remote_user_attribute_set) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01696) + "auth_ldap authenticate: " + "REMOTE_USER was to be set with attribute '%s', " + "but this attribute was not requested for in the " + "LDAP query for the user. REMOTE_USER will fall " + "back to username or DN as appropriate.", + sec->remote_user_attribute); + } + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01697) + "auth_ldap authenticate: accepting %s", user); + + return AUTH_GRANTED; +} + +static authz_status ldapuser_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + int result = 0; + authn_ldap_request_t *req = + (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module); + authn_ldap_config_t *sec = + (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module); + + util_ldap_connection_t *ldc = NULL; + + const char *err = NULL; + const ap_expr_info_t *expr = parsed_require_args; + const char *require; + + const char *t; + char *w; + + char filtbuf[FILTER_LENGTH]; + const char *dn = NULL; + + if (!r->user) { + return AUTHZ_DENIED_NO_USER; + } + + if (!sec->have_ldap_url) { + return AUTHZ_DENIED; + } + + if (sec->host) { + ldc = get_connection_for_authz(r, LDAP_COMPARE); + apr_pool_cleanup_register(r->pool, ldc, + authnz_ldap_cleanup_connection_close, + apr_pool_cleanup_null); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01698) + "auth_ldap authorize: no sec->host - weird...?"); + return AUTHZ_DENIED; + } + + /* + * If we have been authenticated by some other module than mod_authnz_ldap, + * the req structure needed for authorization needs to be created + * and populated with the userid and DN of the account in LDAP + */ + + + if (!strlen(r->user)) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01699) + "ldap authorize: Userid is blank, AuthType=%s", + r->ap_auth_type); + } + + if(!req) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01700) + "ldap authorize: Creating LDAP req structure"); + + req = (authn_ldap_request_t *)apr_pcalloc(r->pool, + sizeof(authn_ldap_request_t)); + + /* Build the username filter */ + authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec); + + /* Search for the user DN */ + result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn, + sec->scope, sec->attributes, filtbuf, &dn, &(req->vals)); + + /* Search failed, log error and return failure */ + if(result != LDAP_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01701) + "auth_ldap authorise: User DN not found, %s", ldc->reason); + return AUTHZ_DENIED; + } + + ap_set_module_config(r->request_config, &authnz_ldap_module, req); + req->dn = apr_pstrdup(r->pool, dn); + req->user = r->user; + + } + + if (req->dn == NULL || strlen(req->dn) == 0) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01702) + "auth_ldap authorize: require user: user's DN has not " + "been defined; failing authorization"); + return AUTHZ_DENIED; + } + + require = ap_expr_str_exec(r, expr, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02585) + "auth_ldap authorize: require user: Can't evaluate expression: %s", + err); + return AUTHZ_DENIED; + } + + /* + * First do a whole-line compare, in case it's something like + * require user Babs Jensen + */ + result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, require); + switch(result) { + case LDAP_COMPARE_TRUE: { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01703) + "auth_ldap authorize: require user: authorization " + "successful"); + set_request_vars(r, LDAP_AUTHZ); + return AUTHZ_GRANTED; + } + default: { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01704) + "auth_ldap authorize: require user: " + "authorization failed [%s][%s]", + ldc->reason, ldap_err2string(result)); + } + } + + /* + * Now break apart the line and compare each word on it + */ + t = require; + while ((w = ap_getword_conf(r->pool, &t)) && w[0]) { + result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, w); + switch(result) { + case LDAP_COMPARE_TRUE: { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01705) + "auth_ldap authorize: " + "require user: authorization successful"); + set_request_vars(r, LDAP_AUTHZ); + return AUTHZ_GRANTED; + } + default: { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01706) + "auth_ldap authorize: " + "require user: authorization failed [%s][%s]", + ldc->reason, ldap_err2string(result)); + } + } + } + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01707) + "auth_ldap authorize user: authorization denied for " + "user %s to %s", + r->user, r->uri); + + return AUTHZ_DENIED; +} + +static authz_status ldapgroup_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + int result = 0; + authn_ldap_request_t *req = + (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module); + authn_ldap_config_t *sec = + (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module); + + util_ldap_connection_t *ldc = NULL; + + const char *err = NULL; + const ap_expr_info_t *expr = parsed_require_args; + const char *require; + + const char *t; + + char filtbuf[FILTER_LENGTH]; + const char *dn = NULL; + struct mod_auth_ldap_groupattr_entry_t *ent; + int i; + + if (!r->user) { + return AUTHZ_DENIED_NO_USER; + } + + if (!sec->have_ldap_url) { + return AUTHZ_DENIED; + } + + if (sec->host) { + ldc = get_connection_for_authz(r, LDAP_COMPARE); /* for the top-level group only */ + apr_pool_cleanup_register(r->pool, ldc, + authnz_ldap_cleanup_connection_close, + apr_pool_cleanup_null); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01708) + "auth_ldap authorize: no sec->host - weird...?"); + return AUTHZ_DENIED; + } + + /* + * If there are no elements in the group attribute array, the default should be + * member and uniquemember; populate the array now. + */ + if (sec->groupattr->nelts == 0) { + struct mod_auth_ldap_groupattr_entry_t *grp; +#if APR_HAS_THREADS + apr_thread_mutex_lock(sec->lock); +#endif + grp = apr_array_push(sec->groupattr); + grp->name = "member"; + grp = apr_array_push(sec->groupattr); + grp->name = "uniqueMember"; +#if APR_HAS_THREADS + apr_thread_mutex_unlock(sec->lock); +#endif + } + + /* + * If there are no elements in the sub group classes array, the default + * should be groupOfNames and groupOfUniqueNames; populate the array now. + */ + if (sec->subgroupclasses->nelts == 0) { + struct mod_auth_ldap_groupattr_entry_t *grp; +#if APR_HAS_THREADS + apr_thread_mutex_lock(sec->lock); +#endif + grp = apr_array_push(sec->subgroupclasses); + grp->name = "groupOfNames"; + grp = apr_array_push(sec->subgroupclasses); + grp->name = "groupOfUniqueNames"; +#if APR_HAS_THREADS + apr_thread_mutex_unlock(sec->lock); +#endif + } + + /* + * If we have been authenticated by some other module than mod_auth_ldap, + * the req structure needed for authorization needs to be created + * and populated with the userid and DN of the account in LDAP + */ + + if (!strlen(r->user)) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01709) + "ldap authorize: Userid is blank, AuthType=%s", + r->ap_auth_type); + } + + if(!req) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01710) + "ldap authorize: Creating LDAP req structure"); + + req = (authn_ldap_request_t *)apr_pcalloc(r->pool, + sizeof(authn_ldap_request_t)); + /* Build the username filter */ + authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec); + + /* Search for the user DN */ + result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn, + sec->scope, sec->attributes, filtbuf, &dn, &(req->vals)); + + /* Search failed, log error and return failure */ + if(result != LDAP_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01711) + "auth_ldap authorise: User DN not found, %s", ldc->reason); + return AUTHZ_DENIED; + } + + ap_set_module_config(r->request_config, &authnz_ldap_module, req); + req->dn = apr_pstrdup(r->pool, dn); + req->user = r->user; + } + + ent = (struct mod_auth_ldap_groupattr_entry_t *) sec->groupattr->elts; + + if (sec->group_attrib_is_dn) { + if (req->dn == NULL || strlen(req->dn) == 0) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01712) + "auth_ldap authorize: require group: user's DN has " + "not been defined; failing authorization for user %s", + r->user); + return AUTHZ_DENIED; + } + } + else { + if (req->user == NULL || strlen(req->user) == 0) { + /* We weren't called in the authentication phase, so we didn't have a + * chance to set the user field. Do so now. */ + req->user = r->user; + } + } + + require = ap_expr_str_exec(r, expr, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02586) + "auth_ldap authorize: require group: Can't evaluate expression: %s", + err); + return AUTHZ_DENIED; + } + + t = require; + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01713) + "auth_ldap authorize: require group: testing for group " + "membership in \"%s\"", + t); + + /* PR52464 exhaust attrs in base group before checking subgroups */ + for (i = 0; i < sec->groupattr->nelts; i++) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01714) + "auth_ldap authorize: require group: testing for %s: " + "%s (%s)", + ent[i].name, + sec->group_attrib_is_dn ? req->dn : req->user, t); + + result = util_ldap_cache_compare(r, ldc, sec->url, t, ent[i].name, + sec->group_attrib_is_dn ? req->dn : req->user); + if (result == LDAP_COMPARE_TRUE) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01715) + "auth_ldap authorize: require group: " + "authorization successful (attribute %s) " + "[%s][%d - %s]", + ent[i].name, ldc->reason, result, + ldap_err2string(result)); + set_request_vars(r, LDAP_AUTHZ); + return AUTHZ_GRANTED; + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01719) + "auth_ldap authorize: require group \"%s\": " + "didn't match with attr %s [%s][%d - %s]", + t, ent[i].name, ldc->reason, result, + ldap_err2string(result)); + } + } + + for (i = 0; i < sec->groupattr->nelts; i++) { + /* nested groups need searches and compares, so grab a new handle */ + authnz_ldap_cleanup_connection_close(ldc); + apr_pool_cleanup_kill(r->pool, ldc,authnz_ldap_cleanup_connection_close); + + ldc = get_connection_for_authz(r, LDAP_COMPARE_AND_SEARCH); + apr_pool_cleanup_register(r->pool, ldc, + authnz_ldap_cleanup_connection_close, + apr_pool_cleanup_null); + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01716) + "auth_ldap authorise: require group \"%s\": " + "failed [%s][%d - %s], checking sub-groups", + t, ldc->reason, result, ldap_err2string(result)); + + result = util_ldap_cache_check_subgroups(r, ldc, sec->url, t, ent[i].name, + sec->group_attrib_is_dn ? req->dn : req->user, + sec->sgAttributes[0] ? sec->sgAttributes : default_attributes, + sec->subgroupclasses, + 0, sec->maxNestingDepth); + if (result == LDAP_COMPARE_TRUE) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01717) + "auth_ldap authorise: require group " + "(sub-group): authorisation successful " + "(attribute %s) [%s][%d - %s]", + ent[i].name, ldc->reason, result, + ldap_err2string(result)); + set_request_vars(r, LDAP_AUTHZ); + return AUTHZ_GRANTED; + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01718) + "auth_ldap authorise: require group " + "(sub-group) \"%s\": didn't match with attr %s " + "[%s][%d - %s]", + t, ldc->reason, ent[i].name, result, + ldap_err2string(result)); + } + } + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01720) + "auth_ldap authorize group: authorization denied for " + "user %s to %s", + r->user, r->uri); + + return AUTHZ_DENIED; +} + +static authz_status ldapdn_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + int result = 0; + authn_ldap_request_t *req = + (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module); + authn_ldap_config_t *sec = + (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module); + + util_ldap_connection_t *ldc = NULL; + + const char *err = NULL; + const ap_expr_info_t *expr = parsed_require_args; + const char *require; + + const char *t; + + char filtbuf[FILTER_LENGTH]; + const char *dn = NULL; + + if (!r->user) { + return AUTHZ_DENIED_NO_USER; + } + + if (!sec->have_ldap_url) { + return AUTHZ_DENIED; + } + + if (sec->host) { + ldc = get_connection_for_authz(r, LDAP_SEARCH); /* _comparedn is a searche */ + apr_pool_cleanup_register(r->pool, ldc, + authnz_ldap_cleanup_connection_close, + apr_pool_cleanup_null); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01721) + "auth_ldap authorize: no sec->host - weird...?"); + return AUTHZ_DENIED; + } + + /* + * If we have been authenticated by some other module than mod_auth_ldap, + * the req structure needed for authorization needs to be created + * and populated with the userid and DN of the account in LDAP + */ + + if (!strlen(r->user)) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01722) + "ldap authorize: Userid is blank, AuthType=%s", + r->ap_auth_type); + } + + if(!req) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01723) + "ldap authorize: Creating LDAP req structure"); + + req = (authn_ldap_request_t *)apr_pcalloc(r->pool, + sizeof(authn_ldap_request_t)); + /* Build the username filter */ + authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec); + + /* Search for the user DN */ + result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn, + sec->scope, sec->attributes, filtbuf, &dn, &(req->vals)); + + /* Search failed, log error and return failure */ + if(result != LDAP_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01724) + "auth_ldap authorise: User DN not found with filter %s: %s", filtbuf, ldc->reason); + return AUTHZ_DENIED; + } + + ap_set_module_config(r->request_config, &authnz_ldap_module, req); + req->dn = apr_pstrdup(r->pool, dn); + req->user = r->user; + } + + require = ap_expr_str_exec(r, expr, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02587) + "auth_ldap authorize: require dn: Can't evaluate expression: %s", + err); + return AUTHZ_DENIED; + } + + t = require; + + if (req->dn == NULL || strlen(req->dn) == 0) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01725) + "auth_ldap authorize: require dn: user's DN has not " + "been defined; failing authorization"); + return AUTHZ_DENIED; + } + + result = util_ldap_cache_comparedn(r, ldc, sec->url, req->dn, t, sec->compare_dn_on_server); + switch(result) { + case LDAP_COMPARE_TRUE: { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01726) + "auth_ldap authorize: " + "require dn: authorization successful"); + set_request_vars(r, LDAP_AUTHZ); + return AUTHZ_GRANTED; + } + default: { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01727) + "auth_ldap authorize: " + "require dn \"%s\": LDAP error [%s][%s]", + t, ldc->reason, ldap_err2string(result)); + } + } + + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01728) + "auth_ldap authorize dn: authorization denied for " + "user %s to %s", + r->user, r->uri); + + return AUTHZ_DENIED; +} + +static authz_status ldapattribute_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + int result = 0; + authn_ldap_request_t *req = + (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module); + authn_ldap_config_t *sec = + (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module); + + util_ldap_connection_t *ldc = NULL; + + const char *err = NULL; + const ap_expr_info_t *expr = parsed_require_args; + const char *require; + + const char *t; + char *w, *value; + + char filtbuf[FILTER_LENGTH]; + const char *dn = NULL; + + if (!r->user) { + return AUTHZ_DENIED_NO_USER; + } + + if (!sec->have_ldap_url) { + return AUTHZ_DENIED; + } + + if (sec->host) { + ldc = get_connection_for_authz(r, LDAP_COMPARE); + apr_pool_cleanup_register(r->pool, ldc, + authnz_ldap_cleanup_connection_close, + apr_pool_cleanup_null); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01729) + "auth_ldap authorize: no sec->host - weird...?"); + return AUTHZ_DENIED; + } + + /* + * If we have been authenticated by some other module than mod_auth_ldap, + * the req structure needed for authorization needs to be created + * and populated with the userid and DN of the account in LDAP + */ + + if (!strlen(r->user)) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01730) + "ldap authorize: Userid is blank, AuthType=%s", + r->ap_auth_type); + } + + if(!req) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01731) + "ldap authorize: Creating LDAP req structure"); + + req = (authn_ldap_request_t *)apr_pcalloc(r->pool, + sizeof(authn_ldap_request_t)); + /* Build the username filter */ + authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec); + + /* Search for the user DN */ + result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn, + sec->scope, sec->attributes, filtbuf, &dn, &(req->vals)); + + /* Search failed, log error and return failure */ + if(result != LDAP_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01732) + "auth_ldap authorise: User DN not found with filter %s: %s", filtbuf, ldc->reason); + return AUTHZ_DENIED; + } + + ap_set_module_config(r->request_config, &authnz_ldap_module, req); + req->dn = apr_pstrdup(r->pool, dn); + req->user = r->user; + } + + if (req->dn == NULL || strlen(req->dn) == 0) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01733) + "auth_ldap authorize: require ldap-attribute: user's DN " + "has not been defined; failing authorization"); + return AUTHZ_DENIED; + } + + require = ap_expr_str_exec(r, expr, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02588) + "auth_ldap authorize: require ldap-attribute: Can't " + "evaluate expression: %s", err); + return AUTHZ_DENIED; + } + + t = require; + + while (t[0]) { + w = ap_getword(r->pool, &t, '='); + value = ap_getword_conf(r->pool, &t); + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01734) + "auth_ldap authorize: checking attribute %s has value %s", + w, value); + result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, w, value); + switch(result) { + case LDAP_COMPARE_TRUE: { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01735) + "auth_ldap authorize: " + "require attribute: authorization successful"); + set_request_vars(r, LDAP_AUTHZ); + return AUTHZ_GRANTED; + } + default: { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01736) + "auth_ldap authorize: require attribute: " + "authorization failed [%s][%s]", + ldc->reason, ldap_err2string(result)); + } + } + } + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01737) + "auth_ldap authorize attribute: authorization denied for " + "user %s to %s", + r->user, r->uri); + + return AUTHZ_DENIED; +} + +static authz_status ldapfilter_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + int result = 0; + authn_ldap_request_t *req = + (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module); + authn_ldap_config_t *sec = + (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module); + + util_ldap_connection_t *ldc = NULL; + + const char *err = NULL; + const ap_expr_info_t *expr = parsed_require_args; + const char *require; + + const char *t; + + char filtbuf[FILTER_LENGTH]; + const char *dn = NULL; + + if (!r->user) { + return AUTHZ_DENIED_NO_USER; + } + + if (!sec->have_ldap_url) { + return AUTHZ_DENIED; + } + + if (sec->host) { + ldc = get_connection_for_authz(r, LDAP_SEARCH); + apr_pool_cleanup_register(r->pool, ldc, + authnz_ldap_cleanup_connection_close, + apr_pool_cleanup_null); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01738) + "auth_ldap authorize: no sec->host - weird...?"); + return AUTHZ_DENIED; + } + + /* + * If we have been authenticated by some other module than mod_auth_ldap, + * the req structure needed for authorization needs to be created + * and populated with the userid and DN of the account in LDAP + */ + + if (!strlen(r->user)) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01739) + "ldap authorize: Userid is blank, AuthType=%s", + r->ap_auth_type); + } + + if(!req) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01740) + "ldap authorize: Creating LDAP req structure"); + + req = (authn_ldap_request_t *)apr_pcalloc(r->pool, + sizeof(authn_ldap_request_t)); + /* Build the username filter */ + authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec); + + /* Search for the user DN */ + result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn, + sec->scope, sec->attributes, filtbuf, &dn, &(req->vals)); + + /* Search failed, log error and return failure */ + if(result != LDAP_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01741) + "auth_ldap authorise: User DN not found with filter %s: %s", filtbuf, ldc->reason); + return AUTHZ_DENIED; + } + + ap_set_module_config(r->request_config, &authnz_ldap_module, req); + req->dn = apr_pstrdup(r->pool, dn); + req->user = r->user; + } + + if (req->dn == NULL || strlen(req->dn) == 0) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01742) + "auth_ldap authorize: require ldap-filter: user's DN " + "has not been defined; failing authorization"); + return AUTHZ_DENIED; + } + + require = ap_expr_str_exec(r, expr, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02589) + "auth_ldap authorize: require ldap-filter: Can't " + "evaluate require expression: %s", err); + return AUTHZ_DENIED; + } + + t = require; + + if (t[0]) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01743) + "auth_ldap authorize: checking filter %s", t); + + /* Build the username filter */ + authn_ldap_build_filter(filtbuf, r, req->user, t, sec); + + /* Search for the user DN */ + result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn, + sec->scope, sec->attributes, filtbuf, &dn, &(req->vals)); + + /* Make sure that the filtered search returned the correct user dn */ + if (result == LDAP_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01744) + "auth_ldap authorize: checking dn match %s", dn); + if (sec->compare_as_user) { + /* ldap-filter is the only authz that requires a search and a compare */ + apr_pool_cleanup_kill(r->pool, ldc, authnz_ldap_cleanup_connection_close); + authnz_ldap_cleanup_connection_close(ldc); + ldc = get_connection_for_authz(r, LDAP_COMPARE); + } + result = util_ldap_cache_comparedn(r, ldc, sec->url, req->dn, dn, + sec->compare_dn_on_server); + } + + switch(result) { + case LDAP_COMPARE_TRUE: { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01745) + "auth_ldap authorize: require ldap-filter: " + "authorization successful"); + set_request_vars(r, LDAP_AUTHZ); + return AUTHZ_GRANTED; + } + case LDAP_FILTER_ERROR: { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01746) + "auth_ldap authorize: require ldap-filter: " + "%s authorization failed [%s][%s]", + filtbuf, ldc->reason, ldap_err2string(result)); + break; + } + default: { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01747) + "auth_ldap authorize: require ldap-filter: " + "authorization failed [%s][%s]", + ldc->reason, ldap_err2string(result)); + } + } + } + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01748) + "auth_ldap authorize filter: authorization denied for " + "user %s to %s", + r->user, r->uri); + + return AUTHZ_DENIED; +} + +static const char *ldap_parse_config(cmd_parms *cmd, const char *require_line, + const void **parsed_require_line) +{ + const char *expr_err = NULL; + ap_expr_info_t *expr; + + expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT, + &expr_err, NULL); + + if (expr_err) + return apr_pstrcat(cmd->temp_pool, + "Cannot parse expression in require line: ", + expr_err, NULL); + + *parsed_require_line = expr; + + return NULL; +} + + +/* + * Use the ldap url parsing routines to break up the ldap url into + * host and port. + */ +static const char *mod_auth_ldap_parse_url(cmd_parms *cmd, + void *config, + const char *url, + const char *mode) +{ + int rc; + apr_ldap_url_desc_t *urld; + apr_ldap_err_t *result; + + authn_ldap_config_t *sec = config; + + rc = apr_ldap_url_parse(cmd->pool, url, &(urld), &(result)); + if (rc != APR_SUCCESS) { + return result->reason; + } + sec->url = apr_pstrdup(cmd->pool, url); + + /* Set all the values, or at least some sane defaults */ + if (sec->host) { + sec->host = apr_pstrcat(cmd->pool, urld->lud_host, " ", sec->host, NULL); + } + else { + sec->host = urld->lud_host? apr_pstrdup(cmd->pool, urld->lud_host) : "localhost"; + } + sec->basedn = urld->lud_dn? apr_pstrdup(cmd->pool, urld->lud_dn) : ""; + if (urld->lud_attrs && urld->lud_attrs[0]) { + int i = 1; + while (urld->lud_attrs[i]) { + i++; + } + sec->attributes = apr_pcalloc(cmd->pool, sizeof(char *) * (i+1)); + i = 0; + while (urld->lud_attrs[i]) { + sec->attributes[i] = apr_pstrdup(cmd->pool, urld->lud_attrs[i]); + i++; + } + sec->attribute = sec->attributes[0]; + } + else { + sec->attribute = "uid"; + } + + sec->scope = urld->lud_scope == LDAP_SCOPE_ONELEVEL ? + LDAP_SCOPE_ONELEVEL : LDAP_SCOPE_SUBTREE; + + if (urld->lud_filter) { + if (urld->lud_filter[0] == '(') { + /* + * Get rid of the surrounding parens; later on when generating the + * filter, they'll be put back. + */ + sec->filter = apr_pstrmemdup(cmd->pool, urld->lud_filter+1, + strlen(urld->lud_filter)-2); + } + else { + sec->filter = apr_pstrdup(cmd->pool, urld->lud_filter); + } + } + else { + sec->filter = "objectclass=*"; + } + + if (mode) { + if (0 == strcasecmp("NONE", mode)) { + sec->secure = APR_LDAP_NONE; + } + else if (0 == strcasecmp("SSL", mode)) { + sec->secure = APR_LDAP_SSL; + } + else if (0 == strcasecmp("TLS", mode) || 0 == strcasecmp("STARTTLS", mode)) { + sec->secure = APR_LDAP_STARTTLS; + } + else { + return "Invalid LDAP connection mode setting: must be one of NONE, " + "SSL, or TLS/STARTTLS"; + } + } + + /* "ldaps" indicates secure ldap connections desired + */ + if (strncasecmp(url, "ldaps", 5) == 0) + { + sec->secure = APR_LDAP_SSL; + sec->port = urld->lud_port? urld->lud_port : LDAPS_PORT; + } + else + { + sec->port = urld->lud_port? urld->lud_port : LDAP_PORT; + } + + sec->have_ldap_url = 1; + + ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, cmd->server, + "auth_ldap url parse: `%s', Host: %s, Port: %d, DN: %s, " + "attrib: %s, scope: %s, filter: %s, connection mode: %s", + url, + urld->lud_host, + urld->lud_port, + urld->lud_dn, + urld->lud_attrs? urld->lud_attrs[0] : "(null)", + (urld->lud_scope == LDAP_SCOPE_SUBTREE? "subtree" : + urld->lud_scope == LDAP_SCOPE_BASE? "base" : + urld->lud_scope == LDAP_SCOPE_ONELEVEL? "onelevel" : "unknown"), + urld->lud_filter, + sec->secure == APR_LDAP_SSL ? "using SSL": "not using SSL" + ); + + return NULL; +} + +static const char *mod_auth_ldap_set_deref(cmd_parms *cmd, void *config, const char *arg) +{ + authn_ldap_config_t *sec = config; + + if (strcmp(arg, "never") == 0 || strcasecmp(arg, "off") == 0) { + sec->deref = never; + } + else if (strcmp(arg, "searching") == 0) { + sec->deref = searching; + } + else if (strcmp(arg, "finding") == 0) { + sec->deref = finding; + } + else if (strcmp(arg, "always") == 0 || strcasecmp(arg, "on") == 0) { + sec->deref = always; + } + else { + return "Unrecognized value for AuthLDAPDereferenceAliases directive"; + } + return NULL; +} + +static const char *mod_auth_ldap_add_subgroup_attribute(cmd_parms *cmd, void *config, const char *arg) +{ + int i = 0; + + authn_ldap_config_t *sec = config; + + for (i = 0; sec->sgAttributes[i]; i++) { + ; + } + if (i == GROUPATTR_MAX_ELTS) + return "Too many AuthLDAPSubGroupAttribute values"; + + sec->sgAttributes[i] = apr_pstrdup(cmd->pool, arg); + + return NULL; +} + +static const char *mod_auth_ldap_add_subgroup_class(cmd_parms *cmd, void *config, const char *arg) +{ + struct mod_auth_ldap_groupattr_entry_t *new; + + authn_ldap_config_t *sec = config; + + if (sec->subgroupclasses->nelts > GROUPATTR_MAX_ELTS) + return "Too many AuthLDAPSubGroupClass values"; + + new = apr_array_push(sec->subgroupclasses); + new->name = apr_pstrdup(cmd->pool, arg); + + return NULL; +} + +static const char *mod_auth_ldap_set_subgroup_maxdepth(cmd_parms *cmd, + void *config, + const char *max_depth) +{ + authn_ldap_config_t *sec = config; + + sec->maxNestingDepth = atol(max_depth); + + return NULL; +} + +static const char *mod_auth_ldap_add_group_attribute(cmd_parms *cmd, void *config, const char *arg) +{ + struct mod_auth_ldap_groupattr_entry_t *new; + + authn_ldap_config_t *sec = config; + + if (sec->groupattr->nelts > GROUPATTR_MAX_ELTS) + return "Too many AuthLDAPGroupAttribute directives"; + + new = apr_array_push(sec->groupattr); + new->name = apr_pstrdup(cmd->pool, arg); + + return NULL; +} + +static const char *set_charset_config(cmd_parms *cmd, void *config, const char *arg) +{ + ap_set_module_config(cmd->server->module_config, &authnz_ldap_module, + (void *)arg); + return NULL; +} + +static const char *set_bind_pattern(cmd_parms *cmd, void *_cfg, const char *exp, const char *subst) +{ + authn_ldap_config_t *sec = _cfg; + ap_regex_t *regexp; + + regexp = ap_pregcomp(cmd->pool, exp, AP_REG_EXTENDED); + + if (!regexp) { + return apr_pstrcat(cmd->pool, "AuthLDAPInitialBindPattern: cannot compile regular " + "expression '", exp, "'", NULL); + } + + sec->bind_regex = regexp; + sec->bind_subst = subst; + + return NULL; +} + +static const char *set_bind_password(cmd_parms *cmd, void *_cfg, const char *arg) +{ + authn_ldap_config_t *sec = _cfg; + int arglen = strlen(arg); + char **argv; + char *result; + + if ((arglen > 5) && strncmp(arg, "exec:", 5) == 0) { + if (apr_tokenize_to_argv(arg+5, &argv, cmd->temp_pool) != APR_SUCCESS) { + return apr_pstrcat(cmd->pool, + "Unable to parse exec arguments from ", + arg+5, NULL); + } + argv[0] = ap_server_root_relative(cmd->temp_pool, argv[0]); + + if (!argv[0]) { + return apr_pstrcat(cmd->pool, + "Invalid AuthLDAPBindPassword exec location:", + arg+5, NULL); + } + result = ap_get_exec_line(cmd->pool, + (const char*)argv[0], (const char * const *)argv); + + if (!result) { + return apr_pstrcat(cmd->pool, + "Unable to get bind password from exec of ", + arg+5, NULL); + } + sec->bindpw = result; + } + else { + sec->bindpw = (char *)arg; + } + + if (!(*sec->bindpw)) { + return "Empty passwords are invalid for AuthLDAPBindPassword"; + } + + return NULL; +} + +static const command_rec authnz_ldap_cmds[] = +{ + AP_INIT_TAKE12("AuthLDAPURL", mod_auth_ldap_parse_url, NULL, OR_AUTHCFG, + "URL to define LDAP connection. This should be an RFC 2255 compliant\n" + "URL of the form ldap://host[:port]/basedn[?attrib[?scope[?filter]]].\n" + "<ul>\n" + "<li>Host is the name of the LDAP server. Use a space separated list of hosts \n" + "to specify redundant servers.\n" + "<li>Port is optional, and specifies the port to connect to.\n" + "<li>basedn specifies the base DN to start searches from\n" + "<li>Attrib specifies what attribute to search for in the directory. If not " + "provided, it defaults to <b>uid</b>.\n" + "<li>Scope is the scope of the search, and can be either <b>sub</b> or " + "<b>one</b>. If not provided, the default is <b>sub</b>.\n" + "<li>Filter is a filter to use in the search. If not provided, " + "defaults to <b>(objectClass=*)</b>.\n" + "</ul>\n" + "Searches are performed using the attribute and the filter combined. " + "For example, assume that the\n" + "LDAP URL is <b>ldap://ldap.airius.com/ou=People, o=Airius?uid?sub?(posixid=*)</b>. " + "Searches will\n" + "be done using the filter <b>(&((posixid=*))(uid=<i>username</i>))</b>, " + "where <i>username</i>\n" + "is the user name passed by the HTTP client. The search will be a subtree " + "search on the branch <b>ou=People, o=Airius</b>."), + + AP_INIT_TAKE1("AuthLDAPBindDN", ap_set_string_slot, + (void *)APR_OFFSETOF(authn_ldap_config_t, binddn), OR_AUTHCFG, + "DN to use to bind to LDAP server. If not provided, will do an anonymous bind."), + + AP_INIT_TAKE1("AuthLDAPBindPassword", set_bind_password, NULL, OR_AUTHCFG, + "Password to use to bind to LDAP server. If not provided, will do an anonymous bind."), + + AP_INIT_FLAG("AuthLDAPBindAuthoritative", ap_set_flag_slot, + (void *)APR_OFFSETOF(authn_ldap_config_t, bind_authoritative), OR_AUTHCFG, + "Set to 'on' to return failures when user-specific bind fails - defaults to on."), + + AP_INIT_FLAG("AuthLDAPRemoteUserIsDN", ap_set_flag_slot, + (void *)APR_OFFSETOF(authn_ldap_config_t, user_is_dn), OR_AUTHCFG, + "Set to 'on' to set the REMOTE_USER environment variable to be the full " + "DN of the remote user. By default, this is set to off, meaning that " + "the REMOTE_USER variable will contain whatever value the remote user sent."), + + AP_INIT_TAKE1("AuthLDAPRemoteUserAttribute", ap_set_string_slot, + (void *)APR_OFFSETOF(authn_ldap_config_t, remote_user_attribute), OR_AUTHCFG, + "Override the user supplied username and place the " + "contents of this attribute in the REMOTE_USER " + "environment variable."), + + AP_INIT_FLAG("AuthLDAPCompareDNOnServer", ap_set_flag_slot, + (void *)APR_OFFSETOF(authn_ldap_config_t, compare_dn_on_server), OR_AUTHCFG, + "Set to 'on' to force auth_ldap to do DN compares (for the \"require dn\" " + "directive) using the server, and set it 'off' to do the compares locally " + "(at the expense of possible false matches). See the documentation for " + "a complete description of this option."), + + AP_INIT_ITERATE("AuthLDAPSubGroupAttribute", mod_auth_ldap_add_subgroup_attribute, NULL, OR_AUTHCFG, + "Attribute labels used to define sub-group (or nested group) membership in groups - " + "defaults to member and uniqueMember"), + + AP_INIT_ITERATE("AuthLDAPSubGroupClass", mod_auth_ldap_add_subgroup_class, NULL, OR_AUTHCFG, + "LDAP objectClass values used to identify sub-group instances - " + "defaults to groupOfNames and groupOfUniqueNames"), + + AP_INIT_TAKE1("AuthLDAPMaxSubGroupDepth", mod_auth_ldap_set_subgroup_maxdepth, NULL, OR_AUTHCFG, + "Maximum subgroup nesting depth to be evaluated - defaults to 10 (top-level group = 0)"), + + AP_INIT_ITERATE("AuthLDAPGroupAttribute", mod_auth_ldap_add_group_attribute, NULL, OR_AUTHCFG, + "A list of attribute labels used to identify the user members of groups - defaults to " + "member and uniquemember"), + + AP_INIT_FLAG("AuthLDAPGroupAttributeIsDN", ap_set_flag_slot, + (void *)APR_OFFSETOF(authn_ldap_config_t, group_attrib_is_dn), OR_AUTHCFG, + "If set to 'on', auth_ldap uses the DN that is retrieved from the server for " + "subsequent group comparisons. If set to 'off', auth_ldap uses the string " + "provided by the client directly. Defaults to 'on'."), + + AP_INIT_TAKE1("AuthLDAPDereferenceAliases", mod_auth_ldap_set_deref, NULL, OR_AUTHCFG, + "Determines how aliases are handled during a search. Can be one of the " + "values \"never\", \"searching\", \"finding\", or \"always\". " + "Defaults to always."), + + AP_INIT_TAKE1("AuthLDAPCharsetConfig", set_charset_config, NULL, RSRC_CONF, + "Character set conversion configuration file. If omitted, character set " + "conversion is disabled."), + + AP_INIT_TAKE1("AuthLDAPAuthorizePrefix", ap_set_string_slot, + (void *)APR_OFFSETOF(authn_ldap_config_t, authz_prefix), OR_AUTHCFG, + "The prefix to add to environment variables set during " + "successful authorization, default '" AUTHZ_PREFIX "'"), + + AP_INIT_FLAG("AuthLDAPInitialBindAsUser", ap_set_flag_slot, + (void *)APR_OFFSETOF(authn_ldap_config_t, initial_bind_as_user), OR_AUTHCFG, + "Set to 'on' to perform the initial DN lookup with the basic auth credentials " + "instead of anonymous or hard-coded credentials"), + + AP_INIT_TAKE2("AuthLDAPInitialBindPattern", set_bind_pattern, NULL, OR_AUTHCFG, + "The regex and substitution to determine a username that can bind based on an HTTP basic auth username"), + + AP_INIT_FLAG("AuthLDAPSearchAsUser", ap_set_flag_slot, + (void *)APR_OFFSETOF(authn_ldap_config_t, search_as_user), OR_AUTHCFG, + "Set to 'on' to perform authorization-based searches with the users credentials, when this module " + "has also performed authentication. Does not affect nested groups lookup."), + AP_INIT_FLAG("AuthLDAPCompareAsUser", ap_set_flag_slot, + (void *)APR_OFFSETOF(authn_ldap_config_t, compare_as_user), OR_AUTHCFG, + "Set to 'on' to perform authorization-based compares with the users credentials, when this module " + "has also performed authentication. Does not affect nested groups lookups."), + {NULL} +}; + +static int authnz_ldap_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) +{ + ap_configfile_t *f; + char l[MAX_STRING_LEN]; + const char *charset_confname = ap_get_module_config(s->module_config, + &authnz_ldap_module); + apr_status_t status; + + /* + authn_ldap_config_t *sec = (authn_ldap_config_t *) + ap_get_module_config(s->module_config, + &authnz_ldap_module); + + if (sec->secure) + { + if (!util_ldap_ssl_supported(s)) + { + ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, APLOGNO(03159) + "LDAP: SSL connections (ldaps://) not supported by utilLDAP"); + return(!OK); + } + } + */ + + /* make sure that mod_ldap (util_ldap) is loaded */ + if (ap_find_linked_module("util_ldap.c") == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01749) + "Module mod_ldap missing. Mod_ldap (aka. util_ldap) " + "must be loaded in order for mod_authnz_ldap to function properly"); + return HTTP_INTERNAL_SERVER_ERROR; + + } + + if (!charset_confname) { + return OK; + } + + charset_confname = ap_server_root_relative(p, charset_confname); + if (!charset_confname) { + ap_log_error(APLOG_MARK, APLOG_ERR, APR_EBADPATH, s, APLOGNO(01750) + "Invalid charset conversion config path %s", + (const char *)ap_get_module_config(s->module_config, + &authnz_ldap_module)); + return HTTP_INTERNAL_SERVER_ERROR; + } + if ((status = ap_pcfg_openfile(&f, ptemp, charset_confname)) + != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, status, s, APLOGNO(01751) + "could not open charset conversion config file %s.", + charset_confname); + return HTTP_INTERNAL_SERVER_ERROR; + } + + charset_conversions = apr_hash_make(p); + + while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) { + const char *ll = l; + char *lang; + + if (l[0] == '#') { + continue; + } + lang = ap_getword_conf(p, &ll); + ap_str_tolower(lang); + + if (ll[0]) { + char *charset = ap_getword_conf(p, &ll); + apr_hash_set(charset_conversions, lang, APR_HASH_KEY_STRING, charset); + } + } + ap_cfg_closefile(f); + + to_charset = derive_codepage_from_lang (p, "utf-8"); + if (to_charset == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, status, s, APLOGNO(01752) + "could not find the UTF-8 charset in the file %s.", + charset_confname); + return HTTP_INTERNAL_SERVER_ERROR; + } + + return OK; +} + +static const authn_provider authn_ldap_provider = +{ + &authn_ldap_check_password, + NULL, +}; + +static const authz_provider authz_ldapuser_provider = +{ + &ldapuser_check_authorization, + &ldap_parse_config, +}; +static const authz_provider authz_ldapgroup_provider = +{ + &ldapgroup_check_authorization, + &ldap_parse_config, +}; + +static const authz_provider authz_ldapdn_provider = +{ + &ldapdn_check_authorization, + &ldap_parse_config, +}; + +static const authz_provider authz_ldapattribute_provider = +{ + &ldapattribute_check_authorization, + &ldap_parse_config, +}; + +static const authz_provider authz_ldapfilter_provider = +{ + &ldapfilter_check_authorization, + &ldap_parse_config, +}; + +static void ImportULDAPOptFn(void) +{ + util_ldap_connection_close = APR_RETRIEVE_OPTIONAL_FN(uldap_connection_close); + util_ldap_connection_find = APR_RETRIEVE_OPTIONAL_FN(uldap_connection_find); + util_ldap_cache_comparedn = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_comparedn); + util_ldap_cache_compare = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_compare); + util_ldap_cache_checkuserid = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_checkuserid); + util_ldap_cache_getuserdn = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_getuserdn); + util_ldap_ssl_supported = APR_RETRIEVE_OPTIONAL_FN(uldap_ssl_supported); + util_ldap_cache_check_subgroups = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_check_subgroups); +} + +static void register_hooks(apr_pool_t *p) +{ + /* Register authn provider */ + ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "ldap", + AUTHN_PROVIDER_VERSION, + &authn_ldap_provider, AP_AUTH_INTERNAL_PER_CONF); + + /* Register authz providers */ + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-user", + AUTHZ_PROVIDER_VERSION, + &authz_ldapuser_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-group", + AUTHZ_PROVIDER_VERSION, + &authz_ldapgroup_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-dn", + AUTHZ_PROVIDER_VERSION, + &authz_ldapdn_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-attribute", + AUTHZ_PROVIDER_VERSION, + &authz_ldapattribute_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-filter", + AUTHZ_PROVIDER_VERSION, + &authz_ldapfilter_provider, + AP_AUTH_INTERNAL_PER_CONF); + + ap_hook_post_config(authnz_ldap_post_config,NULL,NULL,APR_HOOK_MIDDLE); + + ap_hook_optional_fn_retrieve(ImportULDAPOptFn,NULL,NULL,APR_HOOK_MIDDLE); +} + +AP_DECLARE_MODULE(authnz_ldap) = +{ + STANDARD20_MODULE_STUFF, + create_authnz_ldap_dir_config, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + authnz_ldap_cmds, /* command apr_table_t */ + register_hooks /* register hooks */ +}; diff --git a/modules/aaa/mod_authnz_ldap.dep b/modules/aaa/mod_authnz_ldap.dep new file mode 100644 index 0000000..906e060 --- /dev/null +++ b/modules/aaa/mod_authnz_ldap.dep @@ -0,0 +1,70 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authnz_ldap.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authnz_ldap.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\include\util_ldap.h"\ + "..\..\srclib\apr-util\include\apr_anylock.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_ldap.h"\ + "..\..\srclib\apr-util\include\apr_ldap_init.h"\ + "..\..\srclib\apr-util\include\apr_ldap_option.h"\ + "..\..\srclib\apr-util\include\apr_ldap_rebind.h"\ + "..\..\srclib\apr-util\include\apr_ldap_url.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_rmm.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apr_xlate.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_lib.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_thread_rwlock.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_version.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_authnz_ldap.dsp b/modules/aaa/mod_authnz_ldap.dsp new file mode 100644 index 0000000..e2ed929 --- /dev/null +++ b/modules/aaa/mod_authnz_ldap.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_authnz_ldap" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authnz_ldap - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authnz_ldap.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authnz_ldap.mak" CFG="mod_authnz_ldap - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authnz_ldap - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authnz_ldap - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authnz_ldap - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../ldap" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "LDAP_DECLARE_EXPORT" /Fd"Release\mod_authnz_ldap_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authnz_ldap.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authnz_ldap.so" /d LONG_NAME="authnz_ldap_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authnz_ldap.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authnz_ldap.so +# ADD LINK32 kernel32.lib wldap32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authnz_ldap.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authnz_ldap.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authnz_ldap.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authnz_ldap - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../ldap" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "LDAP_DECLARE_EXPORT" /Fd"Debug\mod_authnz_ldap_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authnz_ldap.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authnz_ldap.so" /d LONG_NAME="authnz_ldap_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authnz_ldap.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authnz_ldap.so +# ADD LINK32 kernel32.lib wldap32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authnz_ldap.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authnz_ldap.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authnz_ldap.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authnz_ldap - Win32 Release" +# Name "mod_authnz_ldap - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_authnz_ldap.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authnz_ldap.mak b/modules/aaa/mod_authnz_ldap.mak new file mode 100644 index 0000000..96cc044 --- /dev/null +++ b/modules/aaa/mod_authnz_ldap.mak @@ -0,0 +1,381 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authnz_ldap.dsp +!IF "$(CFG)" == "" +CFG=mod_authnz_ldap - Win32 Release +!MESSAGE No configuration specified. Defaulting to mod_authnz_ldap - Win32 Release. +!ENDIF + +!IF "$(CFG)" != "mod_authnz_ldap - Win32 Release" && "$(CFG)" != "mod_authnz_ldap - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authnz_ldap.mak" CFG="mod_authnz_ldap - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authnz_ldap - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authnz_ldap - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authnz_ldap - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authnz_ldap.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_ldap - Win32 Release" "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authnz_ldap.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" "mod_ldap - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authnz_ldap.obj" + -@erase "$(INTDIR)\mod_authnz_ldap.res" + -@erase "$(INTDIR)\mod_authnz_ldap_src.idb" + -@erase "$(INTDIR)\mod_authnz_ldap_src.pdb" + -@erase "$(OUTDIR)\mod_authnz_ldap.exp" + -@erase "$(OUTDIR)\mod_authnz_ldap.lib" + -@erase "$(OUTDIR)\mod_authnz_ldap.pdb" + -@erase "$(OUTDIR)\mod_authnz_ldap.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../ldap" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "LDAP_DECLARE_EXPORT" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authnz_ldap_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authnz_ldap.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authnz_ldap.so" /d LONG_NAME="authnz_ldap_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authnz_ldap.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib wldap32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authnz_ldap.pdb" /debug /out:"$(OUTDIR)\mod_authnz_ldap.so" /implib:"$(OUTDIR)\mod_authnz_ldap.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authnz_ldap.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authnz_ldap.obj" \ + "$(INTDIR)\mod_authnz_ldap.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" \ + "..\ldap\Release\mod_ldap.lib" + +"$(OUTDIR)\mod_authnz_ldap.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authnz_ldap.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authnz_ldap.so" + if exist .\Release\mod_authnz_ldap.so.manifest mt.exe -manifest .\Release\mod_authnz_ldap.so.manifest -outputresource:.\Release\mod_authnz_ldap.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authnz_ldap - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authnz_ldap.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_ldap - Win32 Debug" "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authnz_ldap.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" "mod_ldap - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authnz_ldap.obj" + -@erase "$(INTDIR)\mod_authnz_ldap.res" + -@erase "$(INTDIR)\mod_authnz_ldap_src.idb" + -@erase "$(INTDIR)\mod_authnz_ldap_src.pdb" + -@erase "$(OUTDIR)\mod_authnz_ldap.exp" + -@erase "$(OUTDIR)\mod_authnz_ldap.lib" + -@erase "$(OUTDIR)\mod_authnz_ldap.pdb" + -@erase "$(OUTDIR)\mod_authnz_ldap.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../ldap" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "LDAP_DECLARE_EXPORT" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authnz_ldap_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authnz_ldap.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authnz_ldap.so" /d LONG_NAME="authnz_ldap_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authnz_ldap.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib wldap32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authnz_ldap.pdb" /debug /out:"$(OUTDIR)\mod_authnz_ldap.so" /implib:"$(OUTDIR)\mod_authnz_ldap.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authnz_ldap.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authnz_ldap.obj" \ + "$(INTDIR)\mod_authnz_ldap.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" \ + "..\ldap\Debug\mod_ldap.lib" + +"$(OUTDIR)\mod_authnz_ldap.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authnz_ldap.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authnz_ldap.so" + if exist .\Debug\mod_authnz_ldap.so.manifest mt.exe -manifest .\Debug\mod_authnz_ldap.so.manifest -outputresource:.\Debug\mod_authnz_ldap.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authnz_ldap.dep") +!INCLUDE "mod_authnz_ldap.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authnz_ldap.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authnz_ldap - Win32 Release" || "$(CFG)" == "mod_authnz_ldap - Win32 Debug" + +!IF "$(CFG)" == "mod_authnz_ldap - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authnz_ldap - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authnz_ldap - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authnz_ldap - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authnz_ldap - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authnz_ldap - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authnz_ldap - Win32 Release" + +"mod_ldap - Win32 Release" : + cd ".\..\ldap" + $(MAKE) /$(MAKEFLAGS) /F ".\mod_ldap.mak" CFG="mod_ldap - Win32 Release" + cd "..\aaa" + +"mod_ldap - Win32 ReleaseCLEAN" : + cd ".\..\ldap" + $(MAKE) /$(MAKEFLAGS) /F ".\mod_ldap.mak" CFG="mod_ldap - Win32 Release" RECURSE=1 CLEAN + cd "..\aaa" + +!ELSEIF "$(CFG)" == "mod_authnz_ldap - Win32 Debug" + +"mod_ldap - Win32 Debug" : + cd ".\..\ldap" + $(MAKE) /$(MAKEFLAGS) /F ".\mod_ldap.mak" CFG="mod_ldap - Win32 Debug" + cd "..\aaa" + +"mod_ldap - Win32 DebugCLEAN" : + cd ".\..\ldap" + $(MAKE) /$(MAKEFLAGS) /F ".\mod_ldap.mak" CFG="mod_ldap - Win32 Debug" RECURSE=1 CLEAN + cd "..\aaa" + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authnz_ldap - Win32 Release" + + +"$(INTDIR)\mod_authnz_ldap.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authnz_ldap.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authnz_ldap.so" /d LONG_NAME="authnz_ldap_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authnz_ldap - Win32 Debug" + + +"$(INTDIR)\mod_authnz_ldap.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authnz_ldap.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authnz_ldap.so" /d LONG_NAME="authnz_ldap_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authnz_ldap.c + +"$(INTDIR)\mod_authnz_ldap.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authz_core.c b/modules/aaa/mod_authz_core.c new file mode 100644 index 0000000..40e5fe1 --- /dev/null +++ b/modules/aaa/mod_authz_core.c @@ -0,0 +1,1173 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Security options etc. + * + * Module derived from code originally written by Rob McCool + * + */ + +#include "apr_strings.h" +#include "apr_network_io.h" +#include "apr_md5.h" + +#define APR_WANT_STRFUNC +#define APR_WANT_BYTEFUNC +#include "apr_want.h" + +#include "ap_config.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_request.h" +#include "http_protocol.h" +#include "ap_provider.h" +#include "ap_expr.h" + +#include "mod_auth.h" + +#if APR_HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +#undef AUTHZ_EXTRA_CONFIGS + +typedef struct provider_alias_rec { + char *provider_name; + char *provider_alias; + char *provider_args; + const void *provider_parsed_args; + ap_conf_vector_t *sec_auth; + const authz_provider *provider; +} provider_alias_rec; + +typedef enum { + AUTHZ_LOGIC_AND, + AUTHZ_LOGIC_OR, + AUTHZ_LOGIC_OFF, + AUTHZ_LOGIC_UNSET +} authz_logic_op; + +typedef struct authz_section_conf authz_section_conf; + +struct authz_section_conf { + const char *provider_name; + const char *provider_args; + const void *provider_parsed_args; + const authz_provider *provider; + apr_int64_t limited; + authz_logic_op op; + int negate; + /** true if this is not a real container but produced by AuthMerging; + * only used for logging */ + int is_merged; + authz_section_conf *first; + authz_section_conf *next; +}; + +typedef struct authz_core_dir_conf authz_core_dir_conf; + +struct authz_core_dir_conf { + authz_section_conf *section; + authz_core_dir_conf *next; + authz_logic_op op; + signed char authz_forbidden_on_fail; +}; + +#define UNSET -1 + +typedef struct authz_core_srv_conf { + apr_hash_t *alias_rec; +} authz_core_srv_conf; + +module AP_MODULE_DECLARE_DATA authz_core_module; + +static authz_core_dir_conf *authz_core_first_dir_conf; + +static void *create_authz_core_dir_config(apr_pool_t *p, char *dummy) +{ + authz_core_dir_conf *conf = apr_pcalloc(p, sizeof(*conf)); + + conf->op = AUTHZ_LOGIC_UNSET; + conf->authz_forbidden_on_fail = UNSET; + + conf->next = authz_core_first_dir_conf; + authz_core_first_dir_conf = conf; + + return (void *)conf; +} + +static void *merge_authz_core_dir_config(apr_pool_t *p, + void *basev, void *newv) +{ + authz_core_dir_conf *base = (authz_core_dir_conf *)basev; + authz_core_dir_conf *new = (authz_core_dir_conf *)newv; + authz_core_dir_conf *conf; + + if (new->op == AUTHZ_LOGIC_UNSET && !new->section && base->section ) { + /* Only authz_forbidden_on_fail has been set in new. Don't treat + * it as a new auth config w.r.t. AuthMerging */ + conf = apr_pmemdup(p, base, sizeof(*base)); + } + else if (new->op == AUTHZ_LOGIC_OFF || new->op == AUTHZ_LOGIC_UNSET || + !(base->section || new->section)) { + conf = apr_pmemdup(p, new, sizeof(*new)); + } + else { + authz_section_conf *section; + + if (base->section) { + if (new->section) { + section = apr_pcalloc(p, sizeof(*section)); + + section->limited = + base->section->limited | new->section->limited; + + section->op = new->op; + section->is_merged = 1; + + section->first = apr_pmemdup(p, base->section, + sizeof(*base->section)); + section->first->next = apr_pmemdup(p, new->section, + sizeof(*new->section)); + } else { + section = apr_pmemdup(p, base->section, + sizeof(*base->section)); + } + } + else { + section = apr_pmemdup(p, new->section, sizeof(*new->section)); + } + + conf = apr_pcalloc(p, sizeof(*conf)); + + conf->section = section; + conf->op = new->op; + } + + if (new->authz_forbidden_on_fail == UNSET) + conf->authz_forbidden_on_fail = base->authz_forbidden_on_fail; + else + conf->authz_forbidden_on_fail = new->authz_forbidden_on_fail; + + return (void*)conf; +} + +/* Only per-server directive we have is GLOBAL_ONLY */ +static void *merge_authz_core_svr_config(apr_pool_t *p, + void *basev, void *newv) +{ + return basev; +} + +static void *create_authz_core_svr_config(apr_pool_t *p, server_rec *s) +{ + authz_core_srv_conf *authcfg; + + authcfg = apr_pcalloc(p, sizeof(*authcfg)); + authcfg->alias_rec = apr_hash_make(p); + + return (void *)authcfg; +} + +/* This is a fake authz provider that really merges various authz alias + * configurations and then invokes them. + */ +static authz_status authz_alias_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + const char *provider_name; + + /* Look up the provider alias in the alias list. + * Get the dir_config and call ap_merge_per_dir_configs() + * Call the real provider->check_authorization() function + * Return the result of the above function call + */ + + provider_name = apr_table_get(r->notes, AUTHZ_PROVIDER_NAME_NOTE); + + if (provider_name) { + authz_core_srv_conf *authcfg; + provider_alias_rec *prvdraliasrec; + + authcfg = ap_get_module_config(r->server->module_config, + &authz_core_module); + + prvdraliasrec = apr_hash_get(authcfg->alias_rec, provider_name, + APR_HASH_KEY_STRING); + + /* If we found the alias provider in the list, then merge the directory + configurations and call the real provider */ + if (prvdraliasrec) { + ap_conf_vector_t *orig_dir_config = r->per_dir_config; + authz_status ret; + + r->per_dir_config = + ap_merge_per_dir_configs(r->pool, orig_dir_config, + prvdraliasrec->sec_auth); + + ret = prvdraliasrec->provider-> + check_authorization(r, prvdraliasrec->provider_args, + prvdraliasrec->provider_parsed_args); + + r->per_dir_config = orig_dir_config; + + return ret; + } + } + + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02305) + "no alias provider found for '%s' (BUG?)", + provider_name ? provider_name : "n/a"); + + return AUTHZ_DENIED; +} + +static const authz_provider authz_alias_provider = +{ + &authz_alias_check_authorization, + NULL, +}; + +static const char *authz_require_alias_section(cmd_parms *cmd, void *mconfig, + const char *args) +{ + const char *endp = ap_strrchr_c(args, '>'); + char *provider_name; + char *provider_alias; + char *provider_args, *extra_args; + ap_conf_vector_t *new_authz_config; + int old_overrides = cmd->override; + const char *errmsg; + + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if (err != NULL) { + return err; + } + + if (endp == NULL) { + return apr_pstrcat(cmd->pool, cmd->cmd->name, + "> directive missing closing '>'", NULL); + } + + args = apr_pstrndup(cmd->temp_pool, args, endp - args); + + if (!args[0]) { + return apr_pstrcat(cmd->pool, cmd->cmd->name, + "> directive requires additional arguments", NULL); + } + + /* Pull the real provider name and the alias name from the block header */ + provider_name = ap_getword_conf(cmd->pool, &args); + provider_alias = ap_getword_conf(cmd->pool, &args); + provider_args = ap_getword_conf(cmd->pool, &args); + extra_args = ap_getword_conf(cmd->pool, &args); + + if (!provider_name[0] || !provider_alias[0]) { + return apr_pstrcat(cmd->pool, cmd->cmd->name, + "> directive requires additional arguments", NULL); + } + + /* We only handle one "Require-Parameters" parameter. If several parameters + are needed, they must be enclosed between quotes */ + if (extra_args && *extra_args) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(10142) + "When several arguments (%s %s...) are passed to a %s directive, " + "they must be enclosed in quotation marks. Otherwise, only the " + "first one is taken into account", + provider_args, extra_args, cmd->cmd->name); + } + + new_authz_config = ap_create_per_dir_config(cmd->pool); + + /* Walk the subsection configuration to get the per_dir config that we will + * merge just before the real provider is called. + */ + cmd->override = OR_AUTHCFG | ACCESS_CONF; + errmsg = ap_walk_config(cmd->directive->first_child, cmd, + new_authz_config); + cmd->override = old_overrides; + + if (!errmsg) { + provider_alias_rec *prvdraliasrec; + authz_core_srv_conf *authcfg; + + prvdraliasrec = apr_pcalloc(cmd->pool, sizeof(*prvdraliasrec)); + + /* Save off the new directory config along with the original + * provider name and function pointer data + */ + prvdraliasrec->provider_name = provider_name; + prvdraliasrec->provider_alias = provider_alias; + prvdraliasrec->provider_args = provider_args; + prvdraliasrec->sec_auth = new_authz_config; + prvdraliasrec->provider = + ap_lookup_provider(AUTHZ_PROVIDER_GROUP, provider_name, + AUTHZ_PROVIDER_VERSION); + + /* by the time the config file is used, the provider should be loaded + * and registered with us. + */ + if (!prvdraliasrec->provider) { + return apr_psprintf(cmd->pool, + "Unknown Authz provider: %s", + provider_name); + } + if (prvdraliasrec->provider->parse_require_line) { + err = prvdraliasrec->provider->parse_require_line(cmd, + provider_args, &prvdraliasrec->provider_parsed_args); + if (err) + return apr_psprintf(cmd->pool, + "Can't parse 'Require %s %s': %s", + provider_name, provider_args, err); + } + + authcfg = ap_get_module_config(cmd->server->module_config, + &authz_core_module); + + apr_hash_set(authcfg->alias_rec, provider_alias, + APR_HASH_KEY_STRING, prvdraliasrec); + + /* Register the fake provider so that we get called first */ + ap_register_auth_provider(cmd->pool, AUTHZ_PROVIDER_GROUP, + provider_alias, AUTHZ_PROVIDER_VERSION, + &authz_alias_provider, + AP_AUTH_INTERNAL_PER_CONF); + } + + return errmsg; +} + +static const char* format_authz_result(authz_status result) +{ + return ((result == AUTHZ_DENIED) + ? "denied" + : ((result == AUTHZ_GRANTED) + ? "granted" + : ((result == AUTHZ_DENIED_NO_USER) + ? "denied (no authenticated user yet)" + : "neutral"))); +} + +static const char* format_authz_command(apr_pool_t *p, + authz_section_conf *section) +{ + return (section->provider + ? apr_pstrcat(p, "Require ", (section->negate ? "not " : ""), + section->provider_name, " ", + section->provider_args, NULL) + : apr_pstrcat(p, section->is_merged ? "AuthMerging " : "<Require", + ((section->op == AUTHZ_LOGIC_AND) + ? (section->negate ? "NotAll" : "All") + : (section->negate ? "None" : "Any")), + section->is_merged ? "" : ">", NULL)); +} + +static authz_section_conf* create_default_section(apr_pool_t *p) +{ + authz_section_conf *section = apr_pcalloc(p, sizeof(*section)); + + section->op = AUTHZ_LOGIC_OR; + + return section; +} + +static const char *add_authz_provider(cmd_parms *cmd, void *config, + const char *args) +{ + authz_core_dir_conf *conf = (authz_core_dir_conf*)config; + authz_section_conf *section = apr_pcalloc(cmd->pool, sizeof(*section)); + authz_section_conf *child; + + section->provider_name = ap_getword_conf(cmd->pool, &args); + + if (!strcasecmp(section->provider_name, "not")) { + section->provider_name = ap_getword_conf(cmd->pool, &args); + section->negate = 1; + } + + section->provider_args = args; + + /* lookup and cache the actual provider now */ + section->provider = ap_lookup_provider(AUTHZ_PROVIDER_GROUP, + section->provider_name, + AUTHZ_PROVIDER_VERSION); + + /* by the time the config file is used, the provider should be loaded + * and registered with us. + */ + if (!section->provider) { + return apr_psprintf(cmd->pool, + "Unknown Authz provider: %s", + section->provider_name); + } + + /* if the provider doesn't provide the appropriate function, reject it */ + if (!section->provider->check_authorization) { + return apr_psprintf(cmd->pool, + "The '%s' Authz provider is not supported by any " + "of the loaded authorization modules", + section->provider_name); + } + + section->limited = cmd->limited; + + if (section->provider->parse_require_line) { + const char *err; + apr_pool_userdata_setn(section->provider_name, + AUTHZ_PROVIDER_NAME_NOTE, + apr_pool_cleanup_null, + cmd->temp_pool); + err = section->provider->parse_require_line(cmd, args, + §ion->provider_parsed_args); + + if (err) + return err; + } + + if (!conf->section) { + conf->section = create_default_section(cmd->pool); + } + + if (section->negate && conf->section->op == AUTHZ_LOGIC_OR) { + return apr_psprintf(cmd->pool, "negative %s directive has no effect " + "in %s directive", + cmd->cmd->name, + format_authz_command(cmd->pool, conf->section)); + } + + conf->section->limited |= section->limited; + + child = conf->section->first; + + if (child) { + while (child->next) { + child = child->next; + } + + child->next = section; + } + else { + conf->section->first = section; + } + + return NULL; +} + +static const char *add_authz_section(cmd_parms *cmd, void *mconfig, + const char *args) +{ + authz_core_dir_conf *conf = mconfig; + const char *endp = ap_strrchr_c(args, '>'); + authz_section_conf *old_section = conf->section; + authz_section_conf *section; + int old_overrides = cmd->override; + apr_int64_t old_limited = cmd->limited; + const char *errmsg; + + if (endp == NULL) { + return apr_pstrcat(cmd->pool, cmd->cmd->name, + "> directive missing closing '>'", NULL); + } + + args = apr_pstrndup(cmd->temp_pool, args, endp - args); + + if (args[0]) { + return apr_pstrcat(cmd->pool, cmd->cmd->name, + "> directive doesn't take additional arguments", + NULL); + } + + section = apr_pcalloc(cmd->pool, sizeof(*section)); + + if (!strcasecmp(cmd->cmd->name, "<RequireAll")) { + section->op = AUTHZ_LOGIC_AND; + } + else if (!strcasecmp(cmd->cmd->name, "<RequireAny")) { + section->op = AUTHZ_LOGIC_OR; + } + else if (!strcasecmp(cmd->cmd->name, "<RequireNotAll")) { + section->op = AUTHZ_LOGIC_AND; + section->negate = 1; + } + else { + section->op = AUTHZ_LOGIC_OR; + section->negate = 1; + } + + conf->section = section; + + /* trigger NOT_IN_LIMIT errors as if this were a <Limit> directive */ + cmd->limited &= ~(AP_METHOD_BIT << (METHODS - 1)); + + cmd->override = OR_AUTHCFG; + errmsg = ap_walk_config(cmd->directive->first_child, cmd, cmd->context); + cmd->override = old_overrides; + + cmd->limited = old_limited; + + conf->section = old_section; + + if (errmsg) { + return errmsg; + } + + if (section->first) { + authz_section_conf *child; + + if (!old_section) { + old_section = conf->section = create_default_section(cmd->pool); + } + + if (section->negate && old_section->op == AUTHZ_LOGIC_OR) { + return apr_psprintf(cmd->pool, "%s directive has " + "no effect in %s directive", + format_authz_command(cmd->pool, section), + format_authz_command(cmd->pool, old_section)); + } + + old_section->limited |= section->limited; + + if (!section->negate && section->op == old_section->op) { + /* be associative */ + section = section->first; + } + + child = old_section->first; + + if (child) { + while (child->next) { + child = child->next; + } + + child->next = section; + } + else { + old_section->first = section; + } + } + else { + return apr_pstrcat(cmd->pool, + format_authz_command(cmd->pool, section), + " directive contains no authorization directives", + NULL); + } + + return NULL; +} + +static const char *authz_merge_sections(cmd_parms *cmd, void *mconfig, + const char *arg) +{ + authz_core_dir_conf *conf = mconfig; + + if (!strcasecmp(arg, "Off")) { + conf->op = AUTHZ_LOGIC_OFF; + } + else if (!strcasecmp(arg, "And")) { + conf->op = AUTHZ_LOGIC_AND; + } + else if (!strcasecmp(arg, "Or")) { + conf->op = AUTHZ_LOGIC_OR; + } + else { + return apr_pstrcat(cmd->pool, cmd->cmd->name, " must be one of: " + "Off | And | Or", NULL); + } + + return NULL; +} + +static int authz_core_check_section(apr_pool_t *p, server_rec *s, + authz_section_conf *section, int is_conf) +{ + authz_section_conf *prev = NULL; + authz_section_conf *child = section->first; + int ret = !OK; + + while (child) { + if (child->first) { + if (authz_core_check_section(p, s, child, 0) != OK) { + return !OK; + } + + if (child->negate && child->op != section->op) { + authz_section_conf *next = child->next; + + /* avoid one level of recursion when De Morgan permits */ + child = child->first; + + if (prev) { + prev->next = child; + } + else { + section->first = child; + } + + do { + child->negate = !child->negate; + } while (child->next && (child = child->next)); + + child->next = next; + } + } + + prev = child; + child = child->next; + } + + child = section->first; + + while (child) { + if (!child->negate) { + ret = OK; + break; + } + + child = child->next; + } + + if (ret != OK) { + ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, APR_SUCCESS, s, APLOGNO(01624) + "%s directive contains only negative authorization directives", + is_conf ? "<Directory>, <Location>, or similar" + : format_authz_command(p, section)); + } + + return ret; +} + +static int authz_core_pre_config(apr_pool_t *p, apr_pool_t *plog, + apr_pool_t *ptemp) +{ + authz_core_first_dir_conf = NULL; + + return OK; +} + +static int authz_core_check_config(apr_pool_t *p, apr_pool_t *plog, + apr_pool_t *ptemp, server_rec *s) +{ + authz_core_dir_conf *conf = authz_core_first_dir_conf; + + while (conf) { + if (conf->section) { + if (authz_core_check_section(p, s, conf->section, 1) != OK) { + return !OK; + } + } + + conf = conf->next; + } + + return OK; +} + +static const command_rec authz_cmds[] = +{ + AP_INIT_RAW_ARGS("<AuthzProviderAlias", authz_require_alias_section, + NULL, RSRC_CONF, + "container for grouping an authorization provider's " + "directives under a provider alias"), + AP_INIT_RAW_ARGS("Require", add_authz_provider, NULL, OR_AUTHCFG, + "specifies authorization directives " + "which one must pass (or not) for a request to suceeed"), + AP_INIT_RAW_ARGS("<RequireAll", add_authz_section, NULL, OR_AUTHCFG, + "container for grouping authorization directives " + "of which none must fail and at least one must pass " + "for a request to succeed"), + AP_INIT_RAW_ARGS("<RequireAny", add_authz_section, NULL, OR_AUTHCFG, + "container for grouping authorization directives " + "of which one must pass " + "for a request to succeed"), +#ifdef AUTHZ_EXTRA_CONFIGS + AP_INIT_RAW_ARGS("<RequireNotAll", add_authz_section, NULL, OR_AUTHCFG, + "container for grouping authorization directives " + "of which some must fail or none must pass " + "for a request to succeed"), +#endif + AP_INIT_RAW_ARGS("<RequireNone", add_authz_section, NULL, OR_AUTHCFG, + "container for grouping authorization directives " + "of which none must pass " + "for a request to succeed"), + AP_INIT_TAKE1("AuthMerging", authz_merge_sections, NULL, OR_AUTHCFG, + "controls how a <Directory>, <Location>, or similar " + "directive's authorization directives are combined with " + "those of its predecessor"), + AP_INIT_FLAG("AuthzSendForbiddenOnFailure", ap_set_flag_slot_char, + (void *)APR_OFFSETOF(authz_core_dir_conf, authz_forbidden_on_fail), + OR_AUTHCFG, + "Controls if an authorization failure should result in a " + "'403 FORBIDDEN' response instead of the HTTP-conforming " + "'401 UNAUTHORIZED'"), + {NULL} +}; + +static authz_status apply_authz_sections(request_rec *r, + authz_section_conf *section, + authz_logic_op parent_op) +{ + authz_status auth_result; + + /* check to make sure that the request method requires authorization */ + if (!(section->limited & (AP_METHOD_BIT << r->method_number))) { + auth_result = + (parent_op == AUTHZ_LOGIC_AND) ? AUTHZ_GRANTED : AUTHZ_NEUTRAL; + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(01625) + "authorization result of %s: %s " + "(directive limited to other methods)", + format_authz_command(r->pool, section), + format_authz_result(auth_result)); + + return auth_result; + } + + if (section->provider) { + apr_table_setn(r->notes, AUTHZ_PROVIDER_NAME_NOTE, + section->provider_name); + + auth_result = + section->provider->check_authorization(r, section->provider_args, + section->provider_parsed_args); + + apr_table_unset(r->notes, AUTHZ_PROVIDER_NAME_NOTE); + } + else { + authz_section_conf *child = section->first; + + auth_result = AUTHZ_NEUTRAL; + + while (child) { + authz_status child_result; + + child_result = apply_authz_sections(r, child, section->op); + + if (child_result == AUTHZ_GENERAL_ERROR) { + return AUTHZ_GENERAL_ERROR; + } + + if (child_result != AUTHZ_NEUTRAL) { + /* + * Handling of AUTHZ_DENIED/AUTHZ_DENIED_NO_USER: Return + * AUTHZ_DENIED_NO_USER if providing a user may change the + * result, AUTHZ_DENIED otherwise. + */ + if (section->op == AUTHZ_LOGIC_AND) { + if (child_result == AUTHZ_DENIED) { + auth_result = child_result; + break; + } + if ((child_result == AUTHZ_DENIED_NO_USER + && auth_result != AUTHZ_DENIED) + || (auth_result == AUTHZ_NEUTRAL)) { + auth_result = child_result; + } + } + else { + /* AUTHZ_LOGIC_OR */ + if (child_result == AUTHZ_GRANTED) { + auth_result = child_result; + break; + } + if ((child_result == AUTHZ_DENIED_NO_USER + && auth_result == AUTHZ_DENIED) + || (auth_result == AUTHZ_NEUTRAL)) { + auth_result = child_result; + } + } + } + + child = child->next; + } + } + + if (section->negate) { + if (auth_result == AUTHZ_GRANTED) { + auth_result = AUTHZ_DENIED; + } + else if (auth_result == AUTHZ_DENIED || + auth_result == AUTHZ_DENIED_NO_USER) { + /* For negated directives, if the original result was denied + * then the new result is neutral since we can not grant + * access simply because authorization was not rejected. + */ + auth_result = AUTHZ_NEUTRAL; + } + } + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(01626) + "authorization result of %s: %s", + format_authz_command(r->pool, section), + format_authz_result(auth_result)); + + return auth_result; +} + +static int authorize_user_core(request_rec *r, int after_authn) +{ + authz_core_dir_conf *conf; + authz_status auth_result; + + conf = ap_get_module_config(r->per_dir_config, &authz_core_module); + + if (!conf->section) { + if (ap_auth_type(r)) { + /* there's an AuthType configured, but no authorization + * directives applied to support it + */ + + ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, APLOGNO(01627) + "AuthType configured with no corresponding " + "authorization directives"); + + return HTTP_INTERNAL_SERVER_ERROR; + } + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(01628) + "authorization result: granted (no directives)"); + + return OK; + } + + auth_result = apply_authz_sections(r, conf->section, AUTHZ_LOGIC_AND); + + if (auth_result == AUTHZ_GRANTED) { + return OK; + } + else if (auth_result == AUTHZ_DENIED_NO_USER) { + if (after_authn) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, APLOGNO(01629) + "authorization failure (no authenticated user): %s", + r->uri); + /* + * If we're returning 401 to an authenticated user, tell them to + * try again. If unauthenticated, note_auth_failure has already + * been called during auth. + */ + if (r->user) + ap_note_auth_failure(r); + + return HTTP_UNAUTHORIZED; + } + else { + /* + * We need a user before we can decide what to do. + * Get out of the way and proceed with authentication. + */ + return DECLINED; + } + } + else if (auth_result == AUTHZ_DENIED || auth_result == AUTHZ_NEUTRAL) { + if (!after_authn || ap_auth_type(r) == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, APLOGNO(01630) + "client denied by server configuration: %s%s", + r->filename ? "" : "uri ", + r->filename ? r->filename : r->uri); + + return HTTP_FORBIDDEN; + } + else { + ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, APLOGNO(01631) + "user %s: authorization failure for \"%s\": ", + r->user, r->uri); + + if (conf->authz_forbidden_on_fail > 0) { + return HTTP_FORBIDDEN; + } + else { + /* + * If we're returning 401 to an authenticated user, tell them to + * try again. If unauthenticated, note_auth_failure has already + * been called during auth. + */ + if (r->user) + ap_note_auth_failure(r); + return HTTP_UNAUTHORIZED; + } + } + } + else { + /* We'll assume that the module has already said what its + * error was in the logs. + */ + return HTTP_INTERNAL_SERVER_ERROR; + } +} + +static int authorize_userless(request_rec *r) +{ + return authorize_user_core(r, 0); +} + +static int authorize_user(request_rec *r) +{ + return authorize_user_core(r, 1); +} + +static int authz_some_auth_required(request_rec *r) +{ + authz_core_dir_conf *conf; + + conf = ap_get_module_config(r->per_dir_config, &authz_core_module); + + if (conf->section + && (conf->section->limited & (AP_METHOD_BIT << r->method_number))) { + return 1; + } + + return 0; +} + +/* + * env authz provider + */ + +static authz_status env_check_authorization(request_rec *r, + const char *require_line, + const void *parsed_require_line) +{ + const char *t, *w; + + /* The 'env' provider will allow the configuration to specify a list of + env variables to check rather than a single variable. This is different + from the previous host based syntax. */ + t = require_line; + while ((w = ap_getword_conf(r->pool, &t)) && w[0]) { + if (apr_table_get(r->subprocess_env, w)) { + return AUTHZ_GRANTED; + } + } + + return AUTHZ_DENIED; +} + +static const authz_provider authz_env_provider = +{ + &env_check_authorization, + NULL, +}; + + +/* + * all authz provider + */ + +static authz_status all_check_authorization(request_rec *r, + const char *require_line, + const void *parsed_require_line) +{ + if (parsed_require_line) { + return AUTHZ_GRANTED; + } + return AUTHZ_DENIED; +} + +static const char *all_parse_config(cmd_parms *cmd, const char *require_line, + const void **parsed_require_line) +{ + /* + * If the argument to the 'all' provider is 'granted' then just let + * everybody in. This would be equivalent to the previous syntax of + * 'allow from all'. If the argument is 'denied' we reject everybody, + * which is equivalent to 'deny from all'. + */ + if (strcasecmp(require_line, "granted") == 0) { + *parsed_require_line = (void *)1; + return NULL; + } + else if (strcasecmp(require_line, "denied") == 0) { + /* *parsed_require_line is already NULL */ + return NULL; + } + else { + return "Argument for 'Require all' must be 'granted' or 'denied'"; + } +} + +static const authz_provider authz_all_provider = +{ + &all_check_authorization, + &all_parse_config, +}; + + +/* + * method authz provider + */ + +static authz_status method_check_authorization(request_rec *r, + const char *require_line, + const void *parsed_require_line) +{ + const apr_int64_t *allowed = parsed_require_line; + if (*allowed & (AP_METHOD_BIT << r->method_number)) + return AUTHZ_GRANTED; + else + return AUTHZ_DENIED; +} + +static const char *method_parse_config(cmd_parms *cmd, const char *require_line, + const void **parsed_require_line) +{ + const char *w, *t; + apr_int64_t *allowed = apr_pcalloc(cmd->pool, sizeof(apr_int64_t)); + + t = require_line; + + while ((w = ap_getword_conf(cmd->temp_pool, &t)) && w[0]) { + int m = ap_method_number_of(w); + if (m == M_INVALID) { + return apr_pstrcat(cmd->pool, "Invalid Method '", w, "'", NULL); + } + + *allowed |= (AP_METHOD_BIT << m); + } + + *parsed_require_line = allowed; + return NULL; +} + +static const authz_provider authz_method_provider = +{ + &method_check_authorization, + &method_parse_config, +}; + +/* + * expr authz provider + */ + +#define REQUIRE_EXPR_NOTE "Require_expr_info" +struct require_expr_info { + ap_expr_info_t *expr; + int want_user; +}; + +static int expr_lookup_fn(ap_expr_lookup_parms *parms) +{ + if (parms->type == AP_EXPR_FUNC_VAR + && strcasecmp(parms->name, "REMOTE_USER") == 0) { + struct require_expr_info *info; + apr_pool_userdata_get((void**)&info, REQUIRE_EXPR_NOTE, parms->ptemp); + AP_DEBUG_ASSERT(info != NULL); + info->want_user = 1; + } + return ap_expr_lookup_default(parms); +} + +static const char *expr_parse_config(cmd_parms *cmd, const char *require_line, + const void **parsed_require_line) +{ + const char *expr_err = NULL; + struct require_expr_info *info = apr_pcalloc(cmd->pool, sizeof(*info)); + + /* if the expression happens to be surrounded by quotes, skip them */ + if (require_line[0] == '"') { + apr_size_t len = strlen(require_line); + + if (require_line[len-1] == '"') + require_line = apr_pstrndup(cmd->temp_pool, + require_line + 1, + len - 2); + } + + apr_pool_userdata_setn(info, REQUIRE_EXPR_NOTE, apr_pool_cleanup_null, + cmd->temp_pool); + info->expr = ap_expr_parse_cmd(cmd, require_line, 0, &expr_err, + expr_lookup_fn); + + if (expr_err) + return apr_pstrcat(cmd->temp_pool, + "Cannot parse expression in require line: ", + expr_err, NULL); + + *parsed_require_line = info; + + return NULL; +} + +static authz_status expr_check_authorization(request_rec *r, + const char *require_line, + const void *parsed_require_line) +{ + const char *err = NULL; + const struct require_expr_info *info = parsed_require_line; + int rc = ap_expr_exec(r, info->expr, &err); + + if (rc < 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02320) + "Error evaluating expression in 'Require expr': %s", + err); + return AUTHZ_GENERAL_ERROR; + } + else if (rc == 0) { + if (info->want_user) + return AUTHZ_DENIED_NO_USER; + else + return AUTHZ_DENIED; + } + else { + return AUTHZ_GRANTED; + } +} + +static const authz_provider authz_expr_provider = +{ + &expr_check_authorization, + &expr_parse_config, +}; + + +static void register_hooks(apr_pool_t *p) +{ + APR_REGISTER_OPTIONAL_FN(authz_some_auth_required); + + ap_hook_pre_config(authz_core_pre_config, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_check_config(authz_core_check_config, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_check_authz(authorize_user, NULL, NULL, APR_HOOK_LAST, + AP_AUTH_INTERNAL_PER_CONF); + ap_hook_check_access_ex(authorize_userless, NULL, NULL, APR_HOOK_LAST, + AP_AUTH_INTERNAL_PER_CONF); + + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "env", + AUTHZ_PROVIDER_VERSION, + &authz_env_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "all", + AUTHZ_PROVIDER_VERSION, + &authz_all_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "method", + AUTHZ_PROVIDER_VERSION, + &authz_method_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "expr", + AUTHZ_PROVIDER_VERSION, + &authz_expr_provider, AP_AUTH_INTERNAL_PER_CONF); +} + +AP_DECLARE_MODULE(authz_core) = +{ + STANDARD20_MODULE_STUFF, + create_authz_core_dir_config, /* dir config creater */ + merge_authz_core_dir_config, /* dir merger */ + create_authz_core_svr_config, /* server config */ + merge_authz_core_svr_config , /* merge server config */ + authz_cmds, + register_hooks /* register hooks */ +}; + diff --git a/modules/aaa/mod_authz_core.dep b/modules/aaa/mod_authz_core.dep new file mode 100644 index 0000000..04300cc --- /dev/null +++ b/modules/aaa/mod_authz_core.dep @@ -0,0 +1,60 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authz_core.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authz_core.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_md5.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apr_xlate.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_authz_core.dsp b/modules/aaa/mod_authz_core.dsp new file mode 100644 index 0000000..8e9f124 --- /dev/null +++ b/modules/aaa/mod_authz_core.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_authz_core" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authz_core - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_core.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_core.mak" CFG="mod_authz_core - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authz_core - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authz_core - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authz_core - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_authz_core_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authz_core.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authz_core.so" /d LONG_NAME="authz_core_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authz_core.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_core.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authz_core.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_core.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authz_core.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authz_core - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_authz_core_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authz_core.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authz_core.so" /d LONG_NAME="authz_core_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authz_core.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_core.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authz_core.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_core.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authz_core.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authz_core - Win32 Release" +# Name "mod_authz_core - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_authz_core.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authz_core.mak b/modules/aaa/mod_authz_core.mak new file mode 100644 index 0000000..7351f67 --- /dev/null +++ b/modules/aaa/mod_authz_core.mak @@ -0,0 +1,381 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authz_core.dsp +!IF "$(CFG)" == "" +CFG=mod_authz_core - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_authz_core - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_authz_core - Win32 Release" && "$(CFG)" != "mod_authz_core - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_core.mak" CFG="mod_authz_core - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authz_core - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authz_core - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authz_core - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authz_core.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Release" "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authz_core.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" "mod_auth_basic - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authz_core.obj" + -@erase "$(INTDIR)\mod_authz_core.res" + -@erase "$(INTDIR)\mod_authz_core_src.idb" + -@erase "$(INTDIR)\mod_authz_core_src.pdb" + -@erase "$(OUTDIR)\mod_authz_core.exp" + -@erase "$(OUTDIR)\mod_authz_core.lib" + -@erase "$(OUTDIR)\mod_authz_core.pdb" + -@erase "$(OUTDIR)\mod_authz_core.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authz_core_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authz_core.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authz_core.so" /d LONG_NAME="authz_core_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authz_core.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authz_core.pdb" /debug /out:"$(OUTDIR)\mod_authz_core.so" /implib:"$(OUTDIR)\mod_authz_core.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_core.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authz_core.obj" \ + "$(INTDIR)\mod_authz_core.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authz_core.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authz_core.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authz_core.so" + if exist .\Release\mod_authz_core.so.manifest mt.exe -manifest .\Release\mod_authz_core.so.manifest -outputresource:.\Release\mod_authz_core.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authz_core - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authz_core.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Debug" "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authz_core.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" "mod_auth_basic - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authz_core.obj" + -@erase "$(INTDIR)\mod_authz_core.res" + -@erase "$(INTDIR)\mod_authz_core_src.idb" + -@erase "$(INTDIR)\mod_authz_core_src.pdb" + -@erase "$(OUTDIR)\mod_authz_core.exp" + -@erase "$(OUTDIR)\mod_authz_core.lib" + -@erase "$(OUTDIR)\mod_authz_core.pdb" + -@erase "$(OUTDIR)\mod_authz_core.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authz_core_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authz_core.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authz_core.so" /d LONG_NAME="authz_core_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authz_core.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authz_core.pdb" /debug /out:"$(OUTDIR)\mod_authz_core.so" /implib:"$(OUTDIR)\mod_authz_core.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_core.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authz_core.obj" \ + "$(INTDIR)\mod_authz_core.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authz_core.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authz_core.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authz_core.so" + if exist .\Debug\mod_authz_core.so.manifest mt.exe -manifest .\Debug\mod_authz_core.so.manifest -outputresource:.\Debug\mod_authz_core.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authz_core.dep") +!INCLUDE "mod_authz_core.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authz_core.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authz_core - Win32 Release" || "$(CFG)" == "mod_authz_core - Win32 Debug" + +!IF "$(CFG)" == "mod_authz_core - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_core - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_core - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_core - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_core - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_core - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_core - Win32 Release" + +"mod_auth_basic - Win32 Release" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" + cd "." + +"mod_auth_basic - Win32 ReleaseCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" RECURSE=1 CLEAN + cd "." + +!ELSEIF "$(CFG)" == "mod_authz_core - Win32 Debug" + +"mod_auth_basic - Win32 Debug" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" + cd "." + +"mod_auth_basic - Win32 DebugCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" RECURSE=1 CLEAN + cd "." + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authz_core - Win32 Release" + + +"$(INTDIR)\mod_authz_core.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authz_core.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authz_core.so" /d LONG_NAME="authz_core_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authz_core - Win32 Debug" + + +"$(INTDIR)\mod_authz_core.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authz_core.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authz_core.so" /d LONG_NAME="authz_core_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authz_core.c + +"$(INTDIR)\mod_authz_core.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authz_dbd.c b/modules/aaa/mod_authz_dbd.c new file mode 100644 index 0000000..5d169e1 --- /dev/null +++ b/modules/aaa/mod_authz_dbd.c @@ -0,0 +1,409 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "httpd.h" +#include "http_log.h" +#include "http_config.h" +#include "ap_provider.h" +#include "http_request.h" +#include "http_protocol.h" +#include "http_core.h" +#include "apr_dbd.h" +#include "mod_dbd.h" +#include "apr_strings.h" +#include "mod_authz_dbd.h" + +#include "mod_auth.h" + + +module AP_MODULE_DECLARE_DATA authz_dbd_module; + +/* Export a hook for modules that manage clientside sessions + * (e.g. mod_auth_cookie) + * to deal with those when we successfully login/logout at the server + * + * XXX: WHY would this be specific to dbd_authz? Why wouldn't we track + * this across all authz user providers in a lower level mod, such as + * mod_auth_basic/digest? + */ +APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(authz_dbd, AUTHZ_DBD, int, client_login, + (request_rec *r, int code, const char *action), + (r, code, action), OK, DECLINED) + + +typedef struct { + const char *query; + const char *redir_query; + int redirect; +} authz_dbd_cfg ; + +static ap_dbd_t *(*dbd_handle)(request_rec*) = NULL; +static void (*dbd_prepare)(server_rec*, const char*, const char*) = NULL; + +static const char *const noerror = "???"; + +static void *authz_dbd_cr_cfg(apr_pool_t *pool, char *dummy) +{ + authz_dbd_cfg *ret = apr_pcalloc(pool, sizeof(authz_dbd_cfg)); + ret->redirect = -1; + return ret; +} + +static void *authz_dbd_merge_cfg(apr_pool_t *pool, void *BASE, void *ADD) +{ + authz_dbd_cfg *base = BASE; + authz_dbd_cfg *add = ADD; + authz_dbd_cfg *ret = apr_palloc(pool, sizeof(authz_dbd_cfg)); + + ret->query = (add->query == NULL) ? base->query : add->query; + ret->redir_query = (add->redir_query == NULL) + ? base->redir_query : add->redir_query; + ret->redirect = (add->redirect == -1) ? base->redirect : add->redirect; + return ret; +} + +static const char *authz_dbd_prepare(cmd_parms *cmd, void *cfg, + const char *query) +{ + static unsigned int label_num = 0; + char *label; + const char *err = ap_check_cmd_context(cmd, NOT_IN_HTACCESS); + if (err) + return err; + + if (dbd_prepare == NULL) { + dbd_prepare = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_prepare); + if (dbd_prepare == NULL) { + return "You must load mod_dbd to enable AuthzDBD functions"; + } + dbd_handle = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_acquire); + } + label = apr_psprintf(cmd->pool, "authz_dbd_%d", ++label_num); + + dbd_prepare(cmd->server, query, label); + + /* save the label here for our own use */ + return ap_set_string_slot(cmd, cfg, label); +} + +static const command_rec authz_dbd_cmds[] = { + AP_INIT_FLAG("AuthzDBDLoginToReferer", ap_set_flag_slot, + (void*)APR_OFFSETOF(authz_dbd_cfg, redirect), ACCESS_CONF, + "Whether to redirect to referer on successful login"), + AP_INIT_TAKE1("AuthzDBDQuery", authz_dbd_prepare, + (void*)APR_OFFSETOF(authz_dbd_cfg, query), ACCESS_CONF, + "SQL query for DBD Authz or login"), + AP_INIT_TAKE1("AuthzDBDRedirectQuery", authz_dbd_prepare, + (void*)APR_OFFSETOF(authz_dbd_cfg, redir_query), ACCESS_CONF, + "SQL query to get per-user redirect URL after login"), + {NULL} +}; + +static int authz_dbd_login(request_rec *r, authz_dbd_cfg *cfg, + const char *action) +{ + int rv; + const char *newuri = NULL; + int nrows; + const char *message; + ap_dbd_t *dbd; + apr_dbd_prepared_t *query; + apr_dbd_results_t *res = NULL; + apr_dbd_row_t *row = NULL; + + if (cfg->query == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01642) + "No query configured for %s!", action); + return HTTP_INTERNAL_SERVER_ERROR; + } + + dbd = dbd_handle(r); + if (dbd == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02902) + "No db handle available for %s! " + "Check your database access", + action); + return HTTP_INTERNAL_SERVER_ERROR; + } + + query = apr_hash_get(dbd->prepared, cfg->query, APR_HASH_KEY_STRING); + if (query == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01643) + "Error retrieving Query for %s!", action); + return HTTP_INTERNAL_SERVER_ERROR; + } + + rv = apr_dbd_pvquery(dbd->driver, r->pool, dbd->handle, &nrows, + query, r->user, NULL); + if (rv == 0) { + if (nrows != 1) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01644) + "authz_dbd: %s of user %s updated %d rows", + action, r->user, nrows); + } + } + else { + message = apr_dbd_error(dbd->driver, dbd->handle, rv); + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01645) + "authz_dbd: query for %s failed; user %s [%s]", + action, r->user, message?message:noerror); + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (cfg->redirect == 1) { + newuri = apr_table_get(r->headers_in, "Referer"); + } + + if (!newuri && cfg->redir_query) { + query = apr_hash_get(dbd->prepared, cfg->redir_query, + APR_HASH_KEY_STRING); + if (query == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01646) + "authz_dbd: no redirect query!"); + /* OK, this is non-critical; we can just not-redirect */ + } + else if ((rv = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, + &res, query, 0, r->user, NULL)) == 0) { + for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1); + rv != -1; + rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) { + if (rv != 0) { + message = apr_dbd_error(dbd->driver, dbd->handle, rv); + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01647) + "authz_dbd in get_row; action=%s user=%s [%s]", + action, r->user, message?message:noerror); + } + else if (newuri == NULL) { + newuri = + apr_pstrdup(r->pool, + apr_dbd_get_entry(dbd->driver, row, 0)); + } + /* we can't break out here or row won't get cleaned up */ + } + } + else { + message = apr_dbd_error(dbd->driver, dbd->handle, rv); + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01648) + "authz_dbd/redirect for %s of %s [%s]", + action, r->user, message?message:noerror); + } + } + if (newuri != NULL) { + r->status = HTTP_MOVED_TEMPORARILY; + apr_table_set(r->err_headers_out, "Location", newuri); + } + authz_dbd_run_client_login(r, OK, action); + return OK; +} + +static int authz_dbd_group_query(request_rec *r, authz_dbd_cfg *cfg, + apr_array_header_t *groups) +{ + /* SELECT user_group FROM authz WHERE user = %s */ + int rv; + const char *message; + ap_dbd_t *dbd; + apr_dbd_prepared_t *query; + apr_dbd_results_t *res = NULL; + apr_dbd_row_t *row = NULL; + + if (cfg->query == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01649) + "No query configured for dbd-group!"); + return HTTP_INTERNAL_SERVER_ERROR; + } + + dbd = dbd_handle(r); + if (dbd == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02903) + "No db handle available for dbd-query! " + "Check your database access"); + return HTTP_INTERNAL_SERVER_ERROR; + } + + query = apr_hash_get(dbd->prepared, cfg->query, APR_HASH_KEY_STRING); + if (query == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01650) + "Error retrieving query for dbd-group!"); + return HTTP_INTERNAL_SERVER_ERROR; + } + rv = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res, + query, 0, r->user, NULL); + if (rv == 0) { + for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1); + rv != -1; + rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) { + if (rv == 0) { + APR_ARRAY_PUSH(groups, const char *) = + apr_pstrdup(r->pool, + apr_dbd_get_entry(dbd->driver, row, 0)); + } + else { + message = apr_dbd_error(dbd->driver, dbd->handle, rv); + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01651) + "authz_dbd in get_row; user_group query for user=%s [%s]", + r->user, message?message:noerror); + return HTTP_INTERNAL_SERVER_ERROR; + } + } + } + else { + message = apr_dbd_error(dbd->driver, dbd->handle, rv); + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01652) + "authz_dbd, in groups query for %s [%s]", + r->user, message?message:noerror); + return HTTP_INTERNAL_SERVER_ERROR; + } + return OK; +} + +static authz_status dbdgroup_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + int rv; + const char *w; + apr_array_header_t *groups; + + const char *err = NULL; + const ap_expr_info_t *expr = parsed_require_args; + const char *require; + + const char *t; + authz_dbd_cfg *cfg = ap_get_module_config(r->per_dir_config, + &authz_dbd_module); + + if (!r->user) { + return AUTHZ_DENIED_NO_USER; + } + + groups = apr_array_make(r->pool, 4, sizeof(const char*)); + rv = authz_dbd_group_query(r, cfg, groups); + if (rv != OK) { + return AUTHZ_GENERAL_ERROR; + } + + require = ap_expr_str_exec(r, expr, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02590) + "authz_dbd authorize: require dbd-group: Can't " + "evaluate require expression: %s", err); + return AUTHZ_DENIED; + } + + t = require; + while (t[0]) { + w = ap_getword_white(r->pool, &t); + if (ap_array_str_contains(groups, w)) { + return AUTHZ_GRANTED; + } + } + + return AUTHZ_DENIED; +} + +static authz_status dbdlogin_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + authz_dbd_cfg *cfg = ap_get_module_config(r->per_dir_config, + &authz_dbd_module); + + if (!r->user) { + return AUTHZ_DENIED_NO_USER; + } + + return (authz_dbd_login(r, cfg, "login") == OK ? AUTHZ_GRANTED : AUTHZ_DENIED); +} + +static authz_status dbdlogout_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + authz_dbd_cfg *cfg = ap_get_module_config(r->per_dir_config, + &authz_dbd_module); + + if (!r->user) { + return AUTHZ_DENIED_NO_USER; + } + + return (authz_dbd_login(r, cfg, "logout") == OK ? AUTHZ_GRANTED : AUTHZ_DENIED); +} + +static const char *dbd_parse_config(cmd_parms *cmd, const char *require_line, + const void **parsed_require_line) +{ + const char *expr_err = NULL; + ap_expr_info_t *expr; + + expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT, + &expr_err, NULL); + + if (expr_err) { + return apr_pstrcat(cmd->temp_pool, + "Cannot parse expression in require line: ", + expr_err, NULL); + } + + *parsed_require_line = expr; + + return NULL; +} + +static const authz_provider authz_dbdgroup_provider = +{ + &dbdgroup_check_authorization, + &dbd_parse_config, +}; + +static const authz_provider authz_dbdlogin_provider = +{ + &dbdlogin_check_authorization, + NULL, +}; + +static const authz_provider authz_dbdlogout_provider = +{ + &dbdlogout_check_authorization, + NULL, +}; + +static void authz_dbd_hooks(apr_pool_t *p) +{ + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "dbd-group", + AUTHZ_PROVIDER_VERSION, + &authz_dbdgroup_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "dbd-login", + AUTHZ_PROVIDER_VERSION, + &authz_dbdlogin_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "dbd-logout", + AUTHZ_PROVIDER_VERSION, + &authz_dbdlogout_provider, + AP_AUTH_INTERNAL_PER_CONF); +} + +AP_DECLARE_MODULE(authz_dbd) = +{ + STANDARD20_MODULE_STUFF, + authz_dbd_cr_cfg, + authz_dbd_merge_cfg, + NULL, + NULL, + authz_dbd_cmds, + authz_dbd_hooks +}; diff --git a/modules/aaa/mod_authz_dbd.dep b/modules/aaa/mod_authz_dbd.dep new file mode 100644 index 0000000..6f0138b --- /dev/null +++ b/modules/aaa/mod_authz_dbd.dep @@ -0,0 +1,61 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authz_dbd.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authz_dbd.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_dbd.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + "..\database\mod_dbd.h"\ + ".\mod_authz_dbd.h"\ + diff --git a/modules/aaa/mod_authz_dbd.dsp b/modules/aaa/mod_authz_dbd.dsp new file mode 100644 index 0000000..abba141 --- /dev/null +++ b/modules/aaa/mod_authz_dbd.dsp @@ -0,0 +1,119 @@ +# Microsoft Developer Studio Project File - Name="mod_authz_dbd" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authz_dbd - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_dbd.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_dbd.mak" CFG="mod_authz_dbd - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authz_dbd - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authz_dbd - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authz_dbd - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../database" /D "AUTHZ_DBD_DECLARE_EXPORT" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_authz_dbd_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authz_dbd.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authz_dbd.so" /d LONG_NAME="authz_dbd_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authz_dbd.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_dbd.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authz_dbd.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_dbd.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authz_dbd.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authz_dbd - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../database" /D "AUTHZ_DBD_DECLARE_EXPORT" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_authz_dbd_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authz_dbd.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authz_dbd.so" /d LONG_NAME="authz_dbd_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authz_dbd.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_dbd.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authz_dbd.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_dbd.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authz_dbd.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authz_dbd - Win32 Release" +# Name "mod_authz_dbd - Win32 Debug" +# Begin Source File + +SOURCE=..\database\mod_dbd.h +# End Source File +# Begin Source File + +SOURCE=.\mod_authz_dbd.c +# End Source File +# Begin Source File + +SOURCE=.\mod_authz_dbd.h +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authz_dbd.h b/modules/aaa/mod_authz_dbd.h new file mode 100644 index 0000000..5d55a8e --- /dev/null +++ b/modules/aaa/mod_authz_dbd.h @@ -0,0 +1,44 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOD_AUTHZ_DBD_H +#define MOD_AUTHZ_DBD_H +#include "httpd.h" + +/* Create a set of AUTHZ_DBD_DECLARE(type), AUTHZ_DBD_DECLARE_NONSTD(type) and + * AUTHZ_DBD_DECLARE_DATA with appropriate export and import tags + */ +#if !defined(WIN32) +#define AUTHZ_DBD_DECLARE(type) type +#define AUTHZ_DBD_DECLARE_NONSTD(type) type +#define AUTHZ_DBD_DECLARE_DATA +#elif defined(AUTHZ_DBD_DECLARE_STATIC) +#define AUTHZ_DBD_DECLARE(type) type __stdcall +#define AUTHZ_DBD_DECLARE_NONSTD(type) type +#define AUTHZ_DBD_DECLARE_DATA +#elif defined(AUTHZ_DBD_DECLARE_EXPORT) +#define AUTHZ_DBD_DECLARE(type) __declspec(dllexport) type __stdcall +#define AUTHZ_DBD_DECLARE_NONSTD(type) __declspec(dllexport) type +#define AUTHZ_DBD_DECLARE_DATA __declspec(dllexport) +#else +#define AUTHZ_DBD_DECLARE(type) __declspec(dllimport) type __stdcall +#define AUTHZ_DBD_DECLARE_NONSTD(type) __declspec(dllimport) type +#define AUTHZ_DBD_DECLARE_DATA __declspec(dllimport) +#endif + +APR_DECLARE_EXTERNAL_HOOK(authz_dbd, AUTHZ_DBD, int, client_login, + (request_rec *r, int code, const char *action)) +#endif diff --git a/modules/aaa/mod_authz_dbd.mak b/modules/aaa/mod_authz_dbd.mak new file mode 100644 index 0000000..da7a453 --- /dev/null +++ b/modules/aaa/mod_authz_dbd.mak @@ -0,0 +1,409 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authz_dbd.dsp +!IF "$(CFG)" == "" +CFG=mod_authz_dbd - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_authz_dbd - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_authz_dbd - Win32 Release" && "$(CFG)" != "mod_authz_dbd - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_dbd.mak" CFG="mod_authz_dbd - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authz_dbd - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authz_dbd - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authz_dbd - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authz_dbd.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_dbd - Win32 Release" "mod_auth_basic - Win32 Release" "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authz_dbd.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" "mod_auth_basic - Win32 ReleaseCLEAN" "mod_dbd - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authz_dbd.obj" + -@erase "$(INTDIR)\mod_authz_dbd.res" + -@erase "$(INTDIR)\mod_authz_dbd_src.idb" + -@erase "$(INTDIR)\mod_authz_dbd_src.pdb" + -@erase "$(OUTDIR)\mod_authz_dbd.exp" + -@erase "$(OUTDIR)\mod_authz_dbd.lib" + -@erase "$(OUTDIR)\mod_authz_dbd.pdb" + -@erase "$(OUTDIR)\mod_authz_dbd.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../database" /D "AUTHZ_DBD_DECLARE_EXPORT" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authz_dbd_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authz_dbd.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authz_dbd.so" /d LONG_NAME="authz_dbd_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authz_dbd.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authz_dbd.pdb" /debug /out:"$(OUTDIR)\mod_authz_dbd.so" /implib:"$(OUTDIR)\mod_authz_dbd.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_dbd.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authz_dbd.obj" \ + "$(INTDIR)\mod_authz_dbd.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" \ + "..\database\Release\mod_dbd.lib" + +"$(OUTDIR)\mod_authz_dbd.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authz_dbd.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authz_dbd.so" + if exist .\Release\mod_authz_dbd.so.manifest mt.exe -manifest .\Release\mod_authz_dbd.so.manifest -outputresource:.\Release\mod_authz_dbd.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authz_dbd - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authz_dbd.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_dbd - Win32 Debug" "mod_auth_basic - Win32 Debug" "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authz_dbd.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" "mod_auth_basic - Win32 DebugCLEAN" "mod_dbd - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authz_dbd.obj" + -@erase "$(INTDIR)\mod_authz_dbd.res" + -@erase "$(INTDIR)\mod_authz_dbd_src.idb" + -@erase "$(INTDIR)\mod_authz_dbd_src.pdb" + -@erase "$(OUTDIR)\mod_authz_dbd.exp" + -@erase "$(OUTDIR)\mod_authz_dbd.lib" + -@erase "$(OUTDIR)\mod_authz_dbd.pdb" + -@erase "$(OUTDIR)\mod_authz_dbd.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../database" /D "AUTHZ_DBD_DECLARE_EXPORT" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authz_dbd_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authz_dbd.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authz_dbd.so" /d LONG_NAME="authz_dbd_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authz_dbd.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authz_dbd.pdb" /debug /out:"$(OUTDIR)\mod_authz_dbd.so" /implib:"$(OUTDIR)\mod_authz_dbd.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_dbd.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authz_dbd.obj" \ + "$(INTDIR)\mod_authz_dbd.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" \ + "..\database\Debug\mod_dbd.lib" + +"$(OUTDIR)\mod_authz_dbd.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authz_dbd.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authz_dbd.so" + if exist .\Debug\mod_authz_dbd.so.manifest mt.exe -manifest .\Debug\mod_authz_dbd.so.manifest -outputresource:.\Debug\mod_authz_dbd.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authz_dbd.dep") +!INCLUDE "mod_authz_dbd.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authz_dbd.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authz_dbd - Win32 Release" || "$(CFG)" == "mod_authz_dbd - Win32 Debug" + +!IF "$(CFG)" == "mod_authz_dbd - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_dbd - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_dbd - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_dbd - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_dbd - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_dbd - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_dbd - Win32 Release" + +"mod_auth_basic - Win32 Release" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" + cd "." + +"mod_auth_basic - Win32 ReleaseCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" RECURSE=1 CLEAN + cd "." + +!ELSEIF "$(CFG)" == "mod_authz_dbd - Win32 Debug" + +"mod_auth_basic - Win32 Debug" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" + cd "." + +"mod_auth_basic - Win32 DebugCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" RECURSE=1 CLEAN + cd "." + +!ENDIF + +!IF "$(CFG)" == "mod_authz_dbd - Win32 Release" + +"mod_dbd - Win32 Release" : + cd ".\..\database" + $(MAKE) /$(MAKEFLAGS) /F ".\mod_dbd.mak" CFG="mod_dbd - Win32 Release" + cd "..\aaa" + +"mod_dbd - Win32 ReleaseCLEAN" : + cd ".\..\database" + $(MAKE) /$(MAKEFLAGS) /F ".\mod_dbd.mak" CFG="mod_dbd - Win32 Release" RECURSE=1 CLEAN + cd "..\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_dbd - Win32 Debug" + +"mod_dbd - Win32 Debug" : + cd ".\..\database" + $(MAKE) /$(MAKEFLAGS) /F ".\mod_dbd.mak" CFG="mod_dbd - Win32 Debug" + cd "..\aaa" + +"mod_dbd - Win32 DebugCLEAN" : + cd ".\..\database" + $(MAKE) /$(MAKEFLAGS) /F ".\mod_dbd.mak" CFG="mod_dbd - Win32 Debug" RECURSE=1 CLEAN + cd "..\aaa" + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authz_dbd - Win32 Release" + + +"$(INTDIR)\mod_authz_dbd.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authz_dbd.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authz_dbd.so" /d LONG_NAME="authz_dbd_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authz_dbd - Win32 Debug" + + +"$(INTDIR)\mod_authz_dbd.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authz_dbd.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authz_dbd.so" /d LONG_NAME="authz_dbd_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authz_dbd.c + +"$(INTDIR)\mod_authz_dbd.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authz_dbm.c b/modules/aaa/mod_authz_dbm.c new file mode 100644 index 0000000..f11de68 --- /dev/null +++ b/modules/aaa/mod_authz_dbm.c @@ -0,0 +1,356 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define APR_WANT_STRFUNC +#include "apr_want.h" +#include "apr_strings.h" +#include "apr_dbm.h" +#include "apr_md5.h" + +#include "apr_version.h" +#if !APR_VERSION_AT_LEAST(2,0,0) +#include "apu_version.h" +#endif + +#include "httpd.h" +#include "http_config.h" +#include "ap_provider.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" /* for ap_hook_(check_user_id | auth_checker)*/ + +#include "mod_auth.h" +#include "mod_authz_owner.h" + +typedef struct { + const char *grpfile; + const char *dbmtype; +} authz_dbm_config_rec; + + +/* This should go into APR; perhaps with some nice + * caching/locking/flocking of the open dbm file. + */ +static char *get_dbm_entry_as_str(apr_pool_t *pool, apr_dbm_t *f, char *key) +{ + apr_datum_t d, q; + q.dptr = key; + +#ifndef NETSCAPE_DBM_COMPAT + q.dsize = strlen(q.dptr); +#else + q.dsize = strlen(q.dptr) + 1; +#endif + + if (apr_dbm_fetch(f, q, &d) == APR_SUCCESS && d.dptr) { + return apr_pstrmemdup(pool, d.dptr, d.dsize); + } + + return NULL; +} + +static void *create_authz_dbm_dir_config(apr_pool_t *p, char *d) +{ + authz_dbm_config_rec *conf = apr_palloc(p, sizeof(*conf)); + + conf->grpfile = NULL; + conf->dbmtype = "default"; + + return conf; +} + +static const command_rec authz_dbm_cmds[] = +{ + AP_INIT_TAKE1("AuthDBMGroupFile", ap_set_file_slot, + (void *)APR_OFFSETOF(authz_dbm_config_rec, grpfile), + OR_AUTHCFG, "database file containing group names and member user IDs"), + AP_INIT_TAKE1("AuthzDBMType", ap_set_string_slot, + (void *)APR_OFFSETOF(authz_dbm_config_rec, dbmtype), + OR_AUTHCFG, "what type of DBM file the group file is"), + {NULL} +}; + +module AP_MODULE_DECLARE_DATA authz_dbm_module; + +/* We do something strange with the group file. If the group file + * contains any : we assume the format is + * key=username value=":"groupname [":"anything here is ignored] + * otherwise we now (0.8.14+) assume that the format is + * key=username value=groupname + * The first allows the password and group files to be the same + * physical DBM file; key=username value=password":"groupname[":"anything] + * + * mark@telescope.org, 22Sep95 + */ + +static apr_status_t get_dbm_grp(request_rec *r, char *key1, char *key2, + const char *dbmgrpfile, const char *dbtype, + const char ** out) +{ +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + const apr_dbm_driver_t *driver; + const apu_err_t *err; +#endif + char *grp_colon, *val; + apr_status_t retval; + apr_dbm_t *f; + +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + retval = apr_dbm_get_driver(&driver, dbtype, &err, r->pool); + + if (retval != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, retval, r, APLOGNO(10286) + "could not load '%s' dbm library: %s", + err->reason, err->msg); + return retval; + } + + retval = apr_dbm_open2(&f, driver, dbmgrpfile, APR_DBM_READONLY, + APR_OS_DEFAULT, r->pool); +#else + retval = apr_dbm_open_ex(&f, dbtype, dbmgrpfile, APR_DBM_READONLY, + APR_OS_DEFAULT, r->pool); +#endif + + if (retval != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, retval, r, APLOGNO(01799) + "could not open dbm (type %s) group access " + "file: %s", dbtype, dbmgrpfile); + return retval; + } + + /* Try key2 only if key1 failed */ + if (!(val = get_dbm_entry_as_str(r->pool, f, key1))) { + val = get_dbm_entry_as_str(r->pool, f, key2); + } + + apr_dbm_close(f); + + if (val && (grp_colon = ap_strchr(val, ':')) != NULL) { + char *grp_colon2 = ap_strchr(++grp_colon, ':'); + + if (grp_colon2) { + *grp_colon2 = '\0'; + } + *out = grp_colon; + } + else { + *out = val; + } + + return retval; +} + +static authz_status dbmgroup_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + authz_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config, + &authz_dbm_module); + char *user = r->user; + + const char *err = NULL; + const ap_expr_info_t *expr = parsed_require_args; + const char *require; + + const char *t; + char *w; + const char *orig_groups = NULL; + const char *realm = ap_auth_name(r); + const char *groups; + char *v; + + if (!user) { + return AUTHZ_DENIED_NO_USER; + } + + if (!conf->grpfile) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01798) + "No group file was specified in the configuration"); + return AUTHZ_DENIED; + } + + /* fetch group data from dbm file only once. */ + if (!orig_groups) { + apr_status_t status; + + status = get_dbm_grp(r, apr_pstrcat(r->pool, user, ":", realm, NULL), + user, conf->grpfile, conf->dbmtype, &groups); + + if (status != APR_SUCCESS) { + return AUTHZ_GENERAL_ERROR; + } + + if (groups == NULL) { + /* no groups available, so exit immediately */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01800) + "Authorization of user %s to access %s failed, reason: " + "user doesn't appear in DBM group file (%s).", + r->user, r->uri, conf->grpfile); + return AUTHZ_DENIED; + } + + orig_groups = groups; + } + + require = ap_expr_str_exec(r, expr, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02591) + "authz_dbm authorize: require dbm-group: Can't " + "evaluate require expression: %s", err); + return AUTHZ_DENIED; + } + + t = require; + while ((w = ap_getword_white(r->pool, &t)) && w[0]) { + groups = orig_groups; + while (groups[0]) { + v = ap_getword(r->pool, &groups, ','); + if (!strcmp(v, w)) { + return AUTHZ_GRANTED; + } + } + } + + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01801) + "Authorization of user %s to access %s failed, reason: " + "user is not part of the 'require'ed group(s).", + r->user, r->uri); + + return AUTHZ_DENIED; +} + +static APR_OPTIONAL_FN_TYPE(authz_owner_get_file_group) *authz_owner_get_file_group; + +static authz_status dbmfilegroup_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + authz_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config, + &authz_dbm_module); + char *user = r->user; + const char *realm = ap_auth_name(r); + const char *filegroup = NULL; + apr_status_t status; + const char *groups; + char *v; + + if (!user) { + return AUTHZ_DENIED_NO_USER; + } + + if (!conf->grpfile) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01802) + "No group file was specified in the configuration"); + return AUTHZ_DENIED; + } + + /* fetch group data from dbm file. */ + status = get_dbm_grp(r, apr_pstrcat(r->pool, user, ":", realm, NULL), + user, conf->grpfile, conf->dbmtype, &groups); + + if (status != APR_SUCCESS) { + return AUTHZ_DENIED; + } + + if (groups == NULL) { + /* no groups available, so exit immediately */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01804) + "Authorization of user %s to access %s failed, reason: " + "user doesn't appear in DBM group file (%s).", + r->user, r->uri, conf->grpfile); + return AUTHZ_DENIED; + } + + filegroup = authz_owner_get_file_group(r); + + if (filegroup) { + while (groups[0]) { + v = ap_getword(r->pool, &groups, ','); + if (!strcmp(v, filegroup)) { + return AUTHZ_GRANTED; + } + } + } + + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01805) + "Authorization of user %s to access %s failed, reason: " + "user is not part of the 'require'ed group(s).", + r->user, r->uri); + + return AUTHZ_DENIED; +} + +static const char *dbm_parse_config(cmd_parms *cmd, const char *require_line, + const void **parsed_require_line) +{ + const char *expr_err = NULL; + ap_expr_info_t *expr; + + expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT, + &expr_err, NULL); + + if (expr_err) + return apr_pstrcat(cmd->temp_pool, + "Cannot parse expression in require line: ", + expr_err, NULL); + + *parsed_require_line = expr; + + return NULL; +} + +static const authz_provider authz_dbmgroup_provider = +{ + &dbmgroup_check_authorization, + &dbm_parse_config, +}; + +static const authz_provider authz_dbmfilegroup_provider = +{ + &dbmfilegroup_check_authorization, + NULL, +}; + +static void authz_dbm_getfns(void) +{ + authz_owner_get_file_group = APR_RETRIEVE_OPTIONAL_FN(authz_owner_get_file_group); +} + +static void register_hooks(apr_pool_t *p) +{ + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "dbm-group", + AUTHZ_PROVIDER_VERSION, + &authz_dbmgroup_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "dbm-file-group", + AUTHZ_PROVIDER_VERSION, + &authz_dbmfilegroup_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_hook_optional_fn_retrieve(authz_dbm_getfns, NULL, NULL, APR_HOOK_MIDDLE); +} + +AP_DECLARE_MODULE(authz_dbm) = +{ + STANDARD20_MODULE_STUFF, + create_authz_dbm_dir_config, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + authz_dbm_cmds, /* command apr_table_t */ + register_hooks /* register hooks */ +}; diff --git a/modules/aaa/mod_authz_dbm.dep b/modules/aaa/mod_authz_dbm.dep new file mode 100644 index 0000000..1b4bf3a --- /dev/null +++ b/modules/aaa/mod_authz_dbm.dep @@ -0,0 +1,62 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authz_dbm.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authz_dbm.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_dbm.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_md5.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apr_xlate.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + ".\mod_authz_owner.h"\ + diff --git a/modules/aaa/mod_authz_dbm.dsp b/modules/aaa/mod_authz_dbm.dsp new file mode 100644 index 0000000..9ac2993 --- /dev/null +++ b/modules/aaa/mod_authz_dbm.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_authz_dbm" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authz_dbm - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_dbm.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_dbm.mak" CFG="mod_authz_dbm - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authz_dbm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authz_dbm - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authz_dbm - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_authz_dbm_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authz_dbm.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authz_dbm.so" /d LONG_NAME="authz_dbm_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authz_dbm.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_dbm.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authz_dbm.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_dbm.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authz_dbm.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authz_dbm - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_authz_dbm_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authz_dbm.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authz_dbm.so" /d LONG_NAME="authz_dbm_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authz_dbm.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_dbm.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authz_dbm.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_dbm.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authz_dbm.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authz_dbm - Win32 Release" +# Name "mod_authz_dbm - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_authz_dbm.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authz_dbm.mak b/modules/aaa/mod_authz_dbm.mak new file mode 100644 index 0000000..4be17d5 --- /dev/null +++ b/modules/aaa/mod_authz_dbm.mak @@ -0,0 +1,381 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authz_dbm.dsp +!IF "$(CFG)" == "" +CFG=mod_authz_dbm - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_authz_dbm - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_authz_dbm - Win32 Release" && "$(CFG)" != "mod_authz_dbm - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_dbm.mak" CFG="mod_authz_dbm - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authz_dbm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authz_dbm - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authz_dbm - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authz_dbm.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Release" "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authz_dbm.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" "mod_auth_basic - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authz_dbm.obj" + -@erase "$(INTDIR)\mod_authz_dbm.res" + -@erase "$(INTDIR)\mod_authz_dbm_src.idb" + -@erase "$(INTDIR)\mod_authz_dbm_src.pdb" + -@erase "$(OUTDIR)\mod_authz_dbm.exp" + -@erase "$(OUTDIR)\mod_authz_dbm.lib" + -@erase "$(OUTDIR)\mod_authz_dbm.pdb" + -@erase "$(OUTDIR)\mod_authz_dbm.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authz_dbm_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authz_dbm.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authz_dbm.so" /d LONG_NAME="authz_dbm_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authz_dbm.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authz_dbm.pdb" /debug /out:"$(OUTDIR)\mod_authz_dbm.so" /implib:"$(OUTDIR)\mod_authz_dbm.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_dbm.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authz_dbm.obj" \ + "$(INTDIR)\mod_authz_dbm.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authz_dbm.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authz_dbm.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authz_dbm.so" + if exist .\Release\mod_authz_dbm.so.manifest mt.exe -manifest .\Release\mod_authz_dbm.so.manifest -outputresource:.\Release\mod_authz_dbm.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authz_dbm - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authz_dbm.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Debug" "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authz_dbm.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" "mod_auth_basic - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authz_dbm.obj" + -@erase "$(INTDIR)\mod_authz_dbm.res" + -@erase "$(INTDIR)\mod_authz_dbm_src.idb" + -@erase "$(INTDIR)\mod_authz_dbm_src.pdb" + -@erase "$(OUTDIR)\mod_authz_dbm.exp" + -@erase "$(OUTDIR)\mod_authz_dbm.lib" + -@erase "$(OUTDIR)\mod_authz_dbm.pdb" + -@erase "$(OUTDIR)\mod_authz_dbm.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authz_dbm_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authz_dbm.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authz_dbm.so" /d LONG_NAME="authz_dbm_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authz_dbm.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authz_dbm.pdb" /debug /out:"$(OUTDIR)\mod_authz_dbm.so" /implib:"$(OUTDIR)\mod_authz_dbm.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_dbm.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authz_dbm.obj" \ + "$(INTDIR)\mod_authz_dbm.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authz_dbm.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authz_dbm.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authz_dbm.so" + if exist .\Debug\mod_authz_dbm.so.manifest mt.exe -manifest .\Debug\mod_authz_dbm.so.manifest -outputresource:.\Debug\mod_authz_dbm.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authz_dbm.dep") +!INCLUDE "mod_authz_dbm.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authz_dbm.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authz_dbm - Win32 Release" || "$(CFG)" == "mod_authz_dbm - Win32 Debug" + +!IF "$(CFG)" == "mod_authz_dbm - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_dbm - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_dbm - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_dbm - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_dbm - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_dbm - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_dbm - Win32 Release" + +"mod_auth_basic - Win32 Release" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" + cd "." + +"mod_auth_basic - Win32 ReleaseCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" RECURSE=1 CLEAN + cd "." + +!ELSEIF "$(CFG)" == "mod_authz_dbm - Win32 Debug" + +"mod_auth_basic - Win32 Debug" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" + cd "." + +"mod_auth_basic - Win32 DebugCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" RECURSE=1 CLEAN + cd "." + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authz_dbm - Win32 Release" + + +"$(INTDIR)\mod_authz_dbm.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authz_dbm.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authz_dbm.so" /d LONG_NAME="authz_dbm_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authz_dbm - Win32 Debug" + + +"$(INTDIR)\mod_authz_dbm.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authz_dbm.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authz_dbm.so" /d LONG_NAME="authz_dbm_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authz_dbm.c + +"$(INTDIR)\mod_authz_dbm.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authz_groupfile.c b/modules/aaa/mod_authz_groupfile.c new file mode 100644 index 0000000..c2431e0 --- /dev/null +++ b/modules/aaa/mod_authz_groupfile.c @@ -0,0 +1,333 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This module is triggered by an + * + * AuthGroupFile standard /path/to/file + * + * and the presence of a + * + * require group <list-of-groups> + * + * In an applicable limit/directory block for that method. + * + * If there are no AuthGroupFile directives valid for + * the request; we DECLINED. + * + * If the AuthGroupFile is defined; but somehow not + * accessible: we SERVER_ERROR (was DECLINED). + * + * If there are no 'require ' directives defined for + * this request then we DECLINED (was OK). + * + * If there are no 'require ' directives valid for + * this request method then we DECLINED. (was OK) + * + * If there are any 'require group' blocks and we + * are not in any group - we HTTP_UNAUTHORIZE + * + */ + +#include "apr_strings.h" +#include "apr_lib.h" /* apr_isspace */ + +#include "ap_config.h" +#include "ap_provider.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" +#include "util_varbuf.h" + +#include "mod_auth.h" +#include "mod_authz_owner.h" + +typedef struct { + char *groupfile; +} authz_groupfile_config_rec; + +static void *create_authz_groupfile_dir_config(apr_pool_t *p, char *d) +{ + authz_groupfile_config_rec *conf = apr_palloc(p, sizeof(*conf)); + + conf->groupfile = NULL; + return conf; +} + +static const command_rec authz_groupfile_cmds[] = +{ + AP_INIT_TAKE1("AuthGroupFile", ap_set_file_slot, + (void *)APR_OFFSETOF(authz_groupfile_config_rec, groupfile), + OR_AUTHCFG, + "text file containing group names and member user IDs"), + {NULL} +}; + +module AP_MODULE_DECLARE_DATA authz_groupfile_module; + +#define VARBUF_INIT_LEN 512 +#define VARBUF_MAX_LEN (16*1024*1024) +static apr_status_t groups_for_user(apr_pool_t *p, char *user, char *grpfile, + apr_table_t ** out) +{ + ap_configfile_t *f; + apr_table_t *grps = apr_table_make(p, 15); + apr_pool_t *sp; + struct ap_varbuf vb; + const char *group_name, *ll, *w; + apr_status_t status; + apr_size_t group_len; + + if ((status = ap_pcfg_openfile(&f, p, grpfile)) != APR_SUCCESS) { + return status ; + } + + apr_pool_create(&sp, p); + apr_pool_tag(sp, "authz_groupfile (groups_for_user)"); + + ap_varbuf_init(p, &vb, VARBUF_INIT_LEN); + + while (!(ap_varbuf_cfg_getline(&vb, f, VARBUF_MAX_LEN))) { + if ((vb.buf[0] == '#') || (!vb.buf[0])) { + continue; + } + ll = vb.buf; + apr_pool_clear(sp); + + group_name = ap_getword(sp, &ll, ':'); + group_len = strlen(group_name); + + while (group_len && apr_isspace(*(group_name + group_len - 1))) { + --group_len; + } + + while (ll[0]) { + w = ap_getword_conf(sp, &ll); + if (!strcmp(w, user)) { + apr_table_setn(grps, apr_pstrmemdup(p, group_name, group_len), + "in"); + break; + } + } + } + ap_cfg_closefile(f); + apr_pool_destroy(sp); + ap_varbuf_free(&vb); + + *out = grps; + return APR_SUCCESS; +} + +static authz_status group_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + authz_groupfile_config_rec *conf = ap_get_module_config(r->per_dir_config, + &authz_groupfile_module); + char *user = r->user; + + const char *err = NULL; + const ap_expr_info_t *expr = parsed_require_args; + const char *require; + + const char *t, *w; + apr_table_t *grpstatus = NULL; + apr_status_t status; + + if (!user) { + return AUTHZ_DENIED_NO_USER; + } + + /* If there is no group file - then we are not + * configured. So decline. + */ + if (!(conf->groupfile)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01664) + "No group file was specified in the configuration"); + return AUTHZ_DENIED; + } + + status = groups_for_user(r->pool, user, conf->groupfile, + &grpstatus); + + if (status != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01665) + "Could not open group file: %s", + conf->groupfile); + return AUTHZ_DENIED; + } + + if (apr_is_empty_table(grpstatus)) { + /* no groups available, so exit immediately */ + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01666) + "Authorization of user %s to access %s failed, reason: " + "user doesn't appear in group file (%s).", + r->user, r->uri, conf->groupfile); + return AUTHZ_DENIED; + } + + require = ap_expr_str_exec(r, expr, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02592) + "authz_groupfile authorize: require group: Can't " + "evaluate require expression: %s", err); + return AUTHZ_DENIED; + } + + t = require; + while ((w = ap_getword_conf(r->pool, &t)) && w[0]) { + if (apr_table_get(grpstatus, w)) { + return AUTHZ_GRANTED; + } + } + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01667) + "Authorization of user %s to access %s failed, reason: " + "user is not part of the 'require'ed group(s).", + r->user, r->uri); + + return AUTHZ_DENIED; +} + +static APR_OPTIONAL_FN_TYPE(authz_owner_get_file_group) *authz_owner_get_file_group; + +static authz_status filegroup_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + authz_groupfile_config_rec *conf = ap_get_module_config(r->per_dir_config, + &authz_groupfile_module); + char *user = r->user; + apr_table_t *grpstatus = NULL; + apr_status_t status; + const char *filegroup = NULL; + + if (!user) { + return AUTHZ_DENIED_NO_USER; + } + + /* If there is no group file - then we are not + * configured. So decline. + */ + if (!(conf->groupfile)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01668) + "No group file was specified in the configuration"); + return AUTHZ_DENIED; + } + + status = groups_for_user(r->pool, user, conf->groupfile, + &grpstatus); + if (status != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01669) + "Could not open group file: %s", + conf->groupfile); + return AUTHZ_DENIED; + } + + if (apr_is_empty_table(grpstatus)) { + /* no groups available, so exit immediately */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01670) + "Authorization of user %s to access %s failed, reason: " + "user doesn't appear in group file (%s).", + r->user, r->uri, conf->groupfile); + return AUTHZ_DENIED; + } + + filegroup = authz_owner_get_file_group(r); + + if (filegroup) { + if (apr_table_get(grpstatus, filegroup)) { + return AUTHZ_GRANTED; + } + } + else { + /* No need to emit a error log entry because the call + to authz_owner_get_file_group already did it + for us. + */ + return AUTHZ_DENIED; + } + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01671) + "Authorization of user %s to access %s failed, reason: " + "user is not part of the 'require'ed file group.", + r->user, r->uri); + + return AUTHZ_DENIED; +} + +static const char *groupfile_parse_config(cmd_parms *cmd, const char *require_line, + const void **parsed_require_line) +{ + const char *expr_err = NULL; + ap_expr_info_t *expr; + + expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT, + &expr_err, NULL); + + if (expr_err) + return apr_pstrcat(cmd->temp_pool, + "Cannot parse expression in require line: ", + expr_err, NULL); + + *parsed_require_line = expr; + + return NULL; +} + +static const authz_provider authz_group_provider = +{ + &group_check_authorization, + &groupfile_parse_config, +}; + +static const authz_provider authz_filegroup_provider = +{ + &filegroup_check_authorization, + NULL, +}; + + +static void authz_groupfile_getfns(void) +{ + authz_owner_get_file_group = APR_RETRIEVE_OPTIONAL_FN(authz_owner_get_file_group); +} + +static void register_hooks(apr_pool_t *p) +{ + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "group", + AUTHZ_PROVIDER_VERSION, + &authz_group_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "file-group", + AUTHZ_PROVIDER_VERSION, + &authz_filegroup_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_hook_optional_fn_retrieve(authz_groupfile_getfns, NULL, NULL, APR_HOOK_MIDDLE); +} + +AP_DECLARE_MODULE(authz_groupfile) = +{ + STANDARD20_MODULE_STUFF, + create_authz_groupfile_dir_config,/* dir config creater */ + NULL, /* dir merger -- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + authz_groupfile_cmds, /* command apr_table_t */ + register_hooks /* register hooks */ +}; diff --git a/modules/aaa/mod_authz_groupfile.dep b/modules/aaa/mod_authz_groupfile.dep new file mode 100644 index 0000000..cb09628 --- /dev/null +++ b/modules/aaa/mod_authz_groupfile.dep @@ -0,0 +1,61 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authz_groupfile.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authz_groupfile.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\include\util_varbuf.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_lib.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + ".\mod_authz_owner.h"\ + diff --git a/modules/aaa/mod_authz_groupfile.dsp b/modules/aaa/mod_authz_groupfile.dsp new file mode 100644 index 0000000..efea169 --- /dev/null +++ b/modules/aaa/mod_authz_groupfile.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_authz_groupfile" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authz_groupfile - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_groupfile.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_groupfile.mak" CFG="mod_authz_groupfile - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authz_groupfile - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authz_groupfile - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authz_groupfile - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_authz_groupfile_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authz_groupfile.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authz_groupfile.so" /d LONG_NAME="authz_groupfile_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authz_groupfile.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_groupfile.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authz_groupfile.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_groupfile.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authz_groupfile.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authz_groupfile - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_authz_groupfile_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authz_groupfile.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authz_groupfile.so" /d LONG_NAME="authz_groupfile_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authz_groupfile.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_groupfile.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authz_groupfile.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_groupfile.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authz_groupfile.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authz_groupfile - Win32 Release" +# Name "mod_authz_groupfile - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_authz_groupfile.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authz_groupfile.mak b/modules/aaa/mod_authz_groupfile.mak new file mode 100644 index 0000000..37d729c --- /dev/null +++ b/modules/aaa/mod_authz_groupfile.mak @@ -0,0 +1,381 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authz_groupfile.dsp +!IF "$(CFG)" == "" +CFG=mod_authz_groupfile - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_authz_groupfile - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_authz_groupfile - Win32 Release" && "$(CFG)" != "mod_authz_groupfile - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_groupfile.mak" CFG="mod_authz_groupfile - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authz_groupfile - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authz_groupfile - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authz_groupfile - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authz_groupfile.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Release" "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authz_groupfile.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" "mod_auth_basic - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authz_groupfile.obj" + -@erase "$(INTDIR)\mod_authz_groupfile.res" + -@erase "$(INTDIR)\mod_authz_groupfile_src.idb" + -@erase "$(INTDIR)\mod_authz_groupfile_src.pdb" + -@erase "$(OUTDIR)\mod_authz_groupfile.exp" + -@erase "$(OUTDIR)\mod_authz_groupfile.lib" + -@erase "$(OUTDIR)\mod_authz_groupfile.pdb" + -@erase "$(OUTDIR)\mod_authz_groupfile.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authz_groupfile_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authz_groupfile.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authz_groupfile.so" /d LONG_NAME="authz_groupfile_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authz_groupfile.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authz_groupfile.pdb" /debug /out:"$(OUTDIR)\mod_authz_groupfile.so" /implib:"$(OUTDIR)\mod_authz_groupfile.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_groupfile.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authz_groupfile.obj" \ + "$(INTDIR)\mod_authz_groupfile.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authz_groupfile.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authz_groupfile.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authz_groupfile.so" + if exist .\Release\mod_authz_groupfile.so.manifest mt.exe -manifest .\Release\mod_authz_groupfile.so.manifest -outputresource:.\Release\mod_authz_groupfile.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authz_groupfile - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authz_groupfile.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Debug" "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authz_groupfile.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" "mod_auth_basic - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authz_groupfile.obj" + -@erase "$(INTDIR)\mod_authz_groupfile.res" + -@erase "$(INTDIR)\mod_authz_groupfile_src.idb" + -@erase "$(INTDIR)\mod_authz_groupfile_src.pdb" + -@erase "$(OUTDIR)\mod_authz_groupfile.exp" + -@erase "$(OUTDIR)\mod_authz_groupfile.lib" + -@erase "$(OUTDIR)\mod_authz_groupfile.pdb" + -@erase "$(OUTDIR)\mod_authz_groupfile.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authz_groupfile_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authz_groupfile.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authz_groupfile.so" /d LONG_NAME="authz_groupfile_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authz_groupfile.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authz_groupfile.pdb" /debug /out:"$(OUTDIR)\mod_authz_groupfile.so" /implib:"$(OUTDIR)\mod_authz_groupfile.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_groupfile.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authz_groupfile.obj" \ + "$(INTDIR)\mod_authz_groupfile.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authz_groupfile.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authz_groupfile.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authz_groupfile.so" + if exist .\Debug\mod_authz_groupfile.so.manifest mt.exe -manifest .\Debug\mod_authz_groupfile.so.manifest -outputresource:.\Debug\mod_authz_groupfile.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authz_groupfile.dep") +!INCLUDE "mod_authz_groupfile.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authz_groupfile.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authz_groupfile - Win32 Release" || "$(CFG)" == "mod_authz_groupfile - Win32 Debug" + +!IF "$(CFG)" == "mod_authz_groupfile - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_groupfile - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_groupfile - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_groupfile - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_groupfile - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_groupfile - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_groupfile - Win32 Release" + +"mod_auth_basic - Win32 Release" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" + cd "." + +"mod_auth_basic - Win32 ReleaseCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" RECURSE=1 CLEAN + cd "." + +!ELSEIF "$(CFG)" == "mod_authz_groupfile - Win32 Debug" + +"mod_auth_basic - Win32 Debug" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" + cd "." + +"mod_auth_basic - Win32 DebugCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" RECURSE=1 CLEAN + cd "." + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authz_groupfile - Win32 Release" + + +"$(INTDIR)\mod_authz_groupfile.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authz_groupfile.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authz_groupfile.so" /d LONG_NAME="authz_groupfile_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authz_groupfile - Win32 Debug" + + +"$(INTDIR)\mod_authz_groupfile.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authz_groupfile.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authz_groupfile.so" /d LONG_NAME="authz_groupfile_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authz_groupfile.c + +"$(INTDIR)\mod_authz_groupfile.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authz_host.c b/modules/aaa/mod_authz_host.c new file mode 100644 index 0000000..b43414f --- /dev/null +++ b/modules/aaa/mod_authz_host.c @@ -0,0 +1,410 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Security options etc. + * + * Module derived from code originally written by Rob McCool + * + */ + +#include "apr_strings.h" +#include "apr_network_io.h" +#include "apr_md5.h" +#include "apr_hash.h" + +#define APR_WANT_STRFUNC +#define APR_WANT_BYTEFUNC +#include "apr_want.h" + +#include "ap_config.h" +#include "ap_provider.h" +#include "httpd.h" +#include "http_core.h" +#include "http_config.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" + +#include "mod_auth.h" + +#if APR_HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +/* + * To save memory if the same subnets are used in hundres of vhosts, we store + * each subnet only once and use this temporary hash to find it again. + */ +static apr_hash_t *parsed_subnets; + +static apr_ipsubnet_t *localhost_v4; +#if APR_HAVE_IPV6 +static apr_ipsubnet_t *localhost_v6; +#endif + +static int in_domain(const char *domain, const char *what) +{ + int dl = strlen(domain); + int wl = strlen(what); + + if ((wl - dl) >= 0) { + if (strcasecmp(domain, &what[wl - dl]) != 0) { + return 0; + } + + /* Make sure we matched an *entire* subdomain --- if the user + * said 'allow from good.com', we don't want people from nogood.com + * to be able to get in. + */ + + if (wl == dl) { + return 1; /* matched whole thing */ + } + else { + return (domain[0] == '.' || what[wl - dl - 1] == '.'); + } + } + else { + return 0; + } +} + +static const char *ip_parse_config(cmd_parms *cmd, + const char *require_line, + const void **parsed_require_line) +{ + const char *t, *w; + int count = 0; + apr_ipsubnet_t **ip; + apr_pool_t *ptemp = cmd->temp_pool; + apr_pool_t *p = cmd->pool; + + /* The 'ip' provider will allow the configuration to specify a list of + ip addresses to check rather than a single address. This is different + from the previous host based syntax. */ + + t = require_line; + while ((w = ap_getword_conf(ptemp, &t)) && w[0]) + count++; + + if (count == 0) + return "'require ip' requires an argument"; + + ip = apr_pcalloc(p, sizeof(apr_ipsubnet_t *) * (count + 1)); + *parsed_require_line = ip; + + t = require_line; + while ((w = ap_getword_conf(ptemp, &t)) && w[0]) { + char *addr = apr_pstrdup(ptemp, w); + char *mask; + apr_status_t rv; + + if (parsed_subnets && + (*ip = apr_hash_get(parsed_subnets, w, APR_HASH_KEY_STRING)) != NULL) + { + /* we already have parsed this subnet */ + ip++; + continue; + } + + if ((mask = ap_strchr(addr, '/'))) + *mask++ = '\0'; + + rv = apr_ipsubnet_create(ip, addr, mask, p); + + if(APR_STATUS_IS_EINVAL(rv)) { + /* looked nothing like an IP address */ + return apr_psprintf(p, "ip address '%s' appears to be invalid", w); + } + else if (rv != APR_SUCCESS) { + return apr_psprintf(p, "ip address '%s' appears to be invalid: %pm", + w, &rv); + } + + if (parsed_subnets) + apr_hash_set(parsed_subnets, w, APR_HASH_KEY_STRING, *ip); + ip++; + } + + return NULL; +} + +static authz_status ip_check_authorization(request_rec *r, + const char *require_line, + const void *parsed_require_line) +{ + /* apr_ipsubnet_test should accept const but doesn't */ + apr_ipsubnet_t **ip = (apr_ipsubnet_t **)parsed_require_line; + + while (*ip) { + if (apr_ipsubnet_test(*ip, r->useragent_addr)) + return AUTHZ_GRANTED; + ip++; + } + + /* authz_core will log the require line and the result at DEBUG */ + return AUTHZ_DENIED; +} + +static authz_status host_check_authorization(request_rec *r, + const char *require_line, + const void *parsed_require_line) +{ + const char *t, *w; + const char *remotehost = NULL; + int remotehost_is_ip; + + remotehost = ap_get_useragent_host(r, REMOTE_DOUBLE_REV, &remotehost_is_ip); + + if ((remotehost == NULL) || remotehost_is_ip) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01753) + "access check of '%s' to %s failed, reason: unable to get the " + "remote host name", require_line, r->uri); + } + else { + const char *err = NULL; + const ap_expr_info_t *expr = parsed_require_line; + const char *require; + + require = ap_expr_str_exec(r, expr, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02593) + "authz_host authorize: require host: Can't " + "evaluate require expression: %s", err); + return AUTHZ_DENIED; + } + + /* The 'host' provider will allow the configuration to specify a list of + host names to check rather than a single name. This is different + from the previous host based syntax. */ + t = require; + + /* '#' is not a valid hostname character and admin could + * specify 'Require host localhost# Add example.com later'. We + * should not grant access to 'example.com' in that case. */ + w = ap_strchr_c(t, '#'); + if (w) { + if (w == t) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10120) + "authz_host authorize: dubious empty " + "'Require host %s' with only comment", t); + return AUTHZ_DENIED; + } + + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10121) + "authz_host authorize: ignoring comment in " + "'Require host %s'", t); + + /* Truncate the string at the #. */ + t = apr_pstrmemdup(r->pool, t, w - t); + } + + while ((w = ap_getword_conf(r->pool, &t)) && w[0]) { + if (in_domain(w, remotehost)) { + return AUTHZ_GRANTED; + } + } + } + + /* authz_core will log the require line and the result at DEBUG */ + return AUTHZ_DENIED; +} + +static authz_status +forward_dns_check_authorization(request_rec *r, + const char *require_line, + const void *parsed_require_line) +{ + const char *err = NULL; + const ap_expr_info_t *expr = parsed_require_line; + const char *require, *t; + char *w; + + /* the require line is an expression, which is evaluated now. */ + require = ap_expr_str_exec(r, expr, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(03354) + "authz_host authorize: require forward-dns: " + "Can't evaluate require expression: %s", err); + return AUTHZ_DENIED; + } + + /* tokenize expected list of names */ + t = require; + while ((w = ap_getword_conf(r->pool, &t)) && w[0]) { + + apr_sockaddr_t *sa; + apr_status_t rv; + char *hash_ptr; + + /* stop on apache configuration file comments */ + if ((hash_ptr = ap_strchr(w, '#'))) { + if (hash_ptr == w) { + break; + } + *hash_ptr = '\0'; + } + + /* does the client ip match one of the names? */ + rv = apr_sockaddr_info_get(&sa, w, APR_UNSPEC, 0, 0, r->pool); + if (rv == APR_SUCCESS) { + + while (sa) { + int match = apr_sockaddr_equal(sa, r->useragent_addr); + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03355) + "access check for %s as '%s': %s", + r->useragent_ip, w, match? "yes": "no"); + if (match) { + return AUTHZ_GRANTED; + } + + sa = sa->next; + } + } + else { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(03356) + "No sockaddr info for \"%s\"", w); + } + + /* stop processing, we are in a comment */ + if (hash_ptr) { + break; + } + } + + return AUTHZ_DENIED; +} + +static authz_status local_check_authorization(request_rec *r, + const char *require_line, + const void *parsed_require_line) +{ + if ( apr_sockaddr_equal(r->connection->local_addr, + r->useragent_addr) + || apr_ipsubnet_test(localhost_v4, r->useragent_addr) +#if APR_HAVE_IPV6 + || apr_ipsubnet_test(localhost_v6, r->useragent_addr) +#endif + ) + { + return AUTHZ_GRANTED; + } + + return AUTHZ_DENIED; +} + +static const char *host_parse_config(cmd_parms *cmd, const char *require_line, + const void **parsed_require_line) +{ + const char *expr_err = NULL; + ap_expr_info_t *expr; + + expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT, + &expr_err, NULL); + + if (expr_err) + return apr_pstrcat(cmd->temp_pool, + "Cannot parse expression in require line: ", + expr_err, NULL); + + *parsed_require_line = expr; + + return NULL; +} + +static const authz_provider authz_ip_provider = +{ + &ip_check_authorization, + &ip_parse_config, +}; + +static const authz_provider authz_host_provider = +{ + &host_check_authorization, + &host_parse_config, +}; + +static const authz_provider authz_forward_dns_provider = +{ + &forward_dns_check_authorization, + &host_parse_config, +}; + +static const authz_provider authz_local_provider = +{ + &local_check_authorization, + NULL, +}; + + +static int authz_host_pre_config(apr_pool_t *p, apr_pool_t *plog, + apr_pool_t *ptemp) +{ + /* we only use this hash in the parse config phase, ptemp is enough */ + parsed_subnets = apr_hash_make(ptemp); + + apr_ipsubnet_create(&localhost_v4, "127.0.0.0", "8", p); + apr_hash_set(parsed_subnets, "127.0.0.0/8", APR_HASH_KEY_STRING, localhost_v4); + +#if APR_HAVE_IPV6 + apr_ipsubnet_create(&localhost_v6, "::1", NULL, p); + apr_hash_set(parsed_subnets, "::1", APR_HASH_KEY_STRING, localhost_v6); +#endif + + return OK; +} + +static int authz_host_post_config(apr_pool_t *p, apr_pool_t *plog, + apr_pool_t *ptemp, server_rec *s) +{ + /* make sure we don't use this during .htaccess parsing */ + parsed_subnets = NULL; + + return OK; +} + +static void register_hooks(apr_pool_t *p) +{ + ap_hook_pre_config(authz_host_pre_config, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_post_config(authz_host_post_config, NULL, NULL, APR_HOOK_MIDDLE); + + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ip", + AUTHZ_PROVIDER_VERSION, + &authz_ip_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "host", + AUTHZ_PROVIDER_VERSION, + &authz_host_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "forward-dns", + AUTHZ_PROVIDER_VERSION, + &authz_forward_dns_provider, + AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "local", + AUTHZ_PROVIDER_VERSION, + &authz_local_provider, AP_AUTH_INTERNAL_PER_CONF); +} + +AP_DECLARE_MODULE(authz_host) = +{ + STANDARD20_MODULE_STUFF, + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + NULL, + register_hooks /* register hooks */ +}; diff --git a/modules/aaa/mod_authz_host.dep b/modules/aaa/mod_authz_host.dep new file mode 100644 index 0000000..fe5ce09 --- /dev/null +++ b/modules/aaa/mod_authz_host.dep @@ -0,0 +1,60 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authz_host.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authz_host.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_md5.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apr_xlate.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_authz_host.dsp b/modules/aaa/mod_authz_host.dsp new file mode 100644 index 0000000..e417687 --- /dev/null +++ b/modules/aaa/mod_authz_host.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_authz_host" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authz_host - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_host.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_host.mak" CFG="mod_authz_host - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authz_host - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authz_host - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authz_host - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_authz_host_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authz_host.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authz_host.so" /d LONG_NAME="authz_host_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authz_host.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_host.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authz_host.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_host.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authz_host.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authz_host - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_authz_host_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authz_host.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authz_host.so" /d LONG_NAME="authz_host_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authz_host.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_host.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authz_host.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_host.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authz_host.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authz_host - Win32 Release" +# Name "mod_authz_host - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_authz_host.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authz_host.mak b/modules/aaa/mod_authz_host.mak new file mode 100644 index 0000000..1ad9e85 --- /dev/null +++ b/modules/aaa/mod_authz_host.mak @@ -0,0 +1,381 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authz_host.dsp +!IF "$(CFG)" == "" +CFG=mod_authz_host - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_authz_host - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_authz_host - Win32 Release" && "$(CFG)" != "mod_authz_host - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_host.mak" CFG="mod_authz_host - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authz_host - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authz_host - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authz_host - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authz_host.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Release" "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authz_host.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" "mod_auth_basic - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authz_host.obj" + -@erase "$(INTDIR)\mod_authz_host.res" + -@erase "$(INTDIR)\mod_authz_host_src.idb" + -@erase "$(INTDIR)\mod_authz_host_src.pdb" + -@erase "$(OUTDIR)\mod_authz_host.exp" + -@erase "$(OUTDIR)\mod_authz_host.lib" + -@erase "$(OUTDIR)\mod_authz_host.pdb" + -@erase "$(OUTDIR)\mod_authz_host.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authz_host_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authz_host.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authz_host.so" /d LONG_NAME="authz_host_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authz_host.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authz_host.pdb" /debug /out:"$(OUTDIR)\mod_authz_host.so" /implib:"$(OUTDIR)\mod_authz_host.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_host.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authz_host.obj" \ + "$(INTDIR)\mod_authz_host.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authz_host.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authz_host.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authz_host.so" + if exist .\Release\mod_authz_host.so.manifest mt.exe -manifest .\Release\mod_authz_host.so.manifest -outputresource:.\Release\mod_authz_host.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authz_host - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authz_host.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Debug" "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authz_host.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" "mod_auth_basic - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authz_host.obj" + -@erase "$(INTDIR)\mod_authz_host.res" + -@erase "$(INTDIR)\mod_authz_host_src.idb" + -@erase "$(INTDIR)\mod_authz_host_src.pdb" + -@erase "$(OUTDIR)\mod_authz_host.exp" + -@erase "$(OUTDIR)\mod_authz_host.lib" + -@erase "$(OUTDIR)\mod_authz_host.pdb" + -@erase "$(OUTDIR)\mod_authz_host.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authz_host_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authz_host.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authz_host.so" /d LONG_NAME="authz_host_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authz_host.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authz_host.pdb" /debug /out:"$(OUTDIR)\mod_authz_host.so" /implib:"$(OUTDIR)\mod_authz_host.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_host.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authz_host.obj" \ + "$(INTDIR)\mod_authz_host.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authz_host.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authz_host.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authz_host.so" + if exist .\Debug\mod_authz_host.so.manifest mt.exe -manifest .\Debug\mod_authz_host.so.manifest -outputresource:.\Debug\mod_authz_host.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authz_host.dep") +!INCLUDE "mod_authz_host.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authz_host.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authz_host - Win32 Release" || "$(CFG)" == "mod_authz_host - Win32 Debug" + +!IF "$(CFG)" == "mod_authz_host - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_host - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_host - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_host - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_host - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_host - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_host - Win32 Release" + +"mod_auth_basic - Win32 Release" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" + cd "." + +"mod_auth_basic - Win32 ReleaseCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" RECURSE=1 CLEAN + cd "." + +!ELSEIF "$(CFG)" == "mod_authz_host - Win32 Debug" + +"mod_auth_basic - Win32 Debug" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" + cd "." + +"mod_auth_basic - Win32 DebugCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" RECURSE=1 CLEAN + cd "." + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authz_host - Win32 Release" + + +"$(INTDIR)\mod_authz_host.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authz_host.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authz_host.so" /d LONG_NAME="authz_host_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authz_host - Win32 Debug" + + +"$(INTDIR)\mod_authz_host.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authz_host.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authz_host.so" /d LONG_NAME="authz_host_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authz_host.c + +"$(INTDIR)\mod_authz_host.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authz_owner.c b/modules/aaa/mod_authz_owner.c new file mode 100644 index 0000000..4fd0b2a --- /dev/null +++ b/modules/aaa/mod_authz_owner.c @@ -0,0 +1,189 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_strings.h" +#include "apr_file_info.h" +#include "apr_user.h" + +#include "ap_config.h" +#include "ap_provider.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" + +#include "mod_auth.h" +#include "mod_authz_owner.h" + +static const command_rec authz_owner_cmds[] = +{ + {NULL} +}; + +module AP_MODULE_DECLARE_DATA authz_owner_module; + +static authz_status fileowner_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + char *reason = NULL; + apr_status_t status = 0; + +#if !APR_HAS_USER + reason = "'Require file-owner' is not supported on this platform."; + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01632) + "Authorization of user %s to access %s failed, reason: %s", + r->user, r->uri, reason ? reason : "unknown"); + return AUTHZ_DENIED; +#else /* APR_HAS_USER */ + char *owner = NULL; + apr_finfo_t finfo; + + if (!r->user) { + return AUTHZ_DENIED_NO_USER; + } + + if (!r->filename) { + reason = "no filename available"; + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01633) + "Authorization of user %s to access %s failed, reason: %s", + r->user, r->uri, reason ? reason : "unknown"); + return AUTHZ_DENIED; + } + + status = apr_stat(&finfo, r->filename, APR_FINFO_USER, r->pool); + if (status != APR_SUCCESS) { + reason = apr_pstrcat(r->pool, "could not stat file ", + r->filename, NULL); + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01634) + "Authorization of user %s to access %s failed, reason: %s", + r->user, r->uri, reason ? reason : "unknown"); + return AUTHZ_DENIED; + } + + if (!(finfo.valid & APR_FINFO_USER)) { + reason = "no file owner information available"; + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01635) + "Authorization of user %s to access %s failed, reason: %s", + r->user, r->uri, reason ? reason : "unknown"); + return AUTHZ_DENIED; + } + + status = apr_uid_name_get(&owner, finfo.user, r->pool); + if (status != APR_SUCCESS || !owner) { + reason = "could not get name of file owner"; + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01636) + "Authorization of user %s to access %s failed, reason: %s", + r->user, r->uri, reason ? reason : "unknown"); + return AUTHZ_DENIED; + } + + if (strcmp(owner, r->user)) { + reason = apr_psprintf(r->pool, "file owner %s does not match.", + owner); + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01637) + "Authorization of user %s to access %s failed, reason: %s", + r->user, r->uri, reason ? reason : "unknown"); + return AUTHZ_DENIED; + } + + /* this user is authorized */ + return AUTHZ_GRANTED; +#endif /* APR_HAS_USER */ +} + +static char *authz_owner_get_file_group(request_rec *r) +{ + /* file-group only figures out the file's group and lets + * other modules do the actual authorization (against a group file/db). + * Thus, these modules have to hook themselves after + * mod_authz_owner and of course recognize 'file-group', too. + */ +#if !APR_HAS_USER + return NULL; +#else /* APR_HAS_USER */ + char *reason = NULL; + char *group = NULL; + apr_finfo_t finfo; + apr_status_t status = 0; + + if (!r->filename) { + reason = "no filename available"; + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01638) + "Authorization of user %s to access %s failed, reason: %s", + r->user, r->uri, reason ? reason : "unknown"); + return NULL; + } + + status = apr_stat(&finfo, r->filename, APR_FINFO_GROUP, r->pool); + if (status != APR_SUCCESS) { + reason = apr_pstrcat(r->pool, "could not stat file ", + r->filename, NULL); + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01639) + "Authorization of user %s to access %s failed, reason: %s", + r->user, r->uri, reason ? reason : "unknown"); + return NULL; + } + + if (!(finfo.valid & APR_FINFO_GROUP)) { + reason = "no file group information available"; + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01640) + "Authorization of user %s to access %s failed, reason: %s", + r->user, r->uri, reason ? reason : "unknown"); + return NULL; + } + + status = apr_gid_name_get(&group, finfo.group, r->pool); + if (status != APR_SUCCESS || !group) { + reason = "could not get name of file group"; + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01641) + "Authorization of user %s to access %s failed, reason: %s", + r->user, r->uri, reason ? reason : "unknown"); + return NULL; + } + + return group; +#endif /* APR_HAS_USER */ +} + +static const authz_provider authz_fileowner_provider = +{ + &fileowner_check_authorization, + NULL, +}; + +static void register_hooks(apr_pool_t *p) +{ + APR_REGISTER_OPTIONAL_FN(authz_owner_get_file_group); + + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "file-owner", + AUTHZ_PROVIDER_VERSION, + &authz_fileowner_provider, + AP_AUTH_INTERNAL_PER_CONF); +} + +AP_DECLARE_MODULE(authz_owner) = +{ + STANDARD20_MODULE_STUFF, + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + authz_owner_cmds, /* command apr_table_t */ + register_hooks /* register hooks */ +}; diff --git a/modules/aaa/mod_authz_owner.dep b/modules/aaa/mod_authz_owner.dep new file mode 100644 index 0000000..42a1056 --- /dev/null +++ b/modules/aaa/mod_authz_owner.dep @@ -0,0 +1,59 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authz_owner.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authz_owner.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + ".\mod_authz_owner.h"\ + diff --git a/modules/aaa/mod_authz_owner.dsp b/modules/aaa/mod_authz_owner.dsp new file mode 100644 index 0000000..e026a28 --- /dev/null +++ b/modules/aaa/mod_authz_owner.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_authz_owner" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authz_owner - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_owner.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_owner.mak" CFG="mod_authz_owner - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authz_owner - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authz_owner - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authz_owner - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_authz_owner_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authz_owner.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authz_owner.so" /d LONG_NAME="authz_owner_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authz_owner.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_owner.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authz_owner.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_owner.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authz_owner.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authz_owner - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_authz_owner_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authz_owner.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authz_owner.so" /d LONG_NAME="authz_owner_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authz_owner.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_owner.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authz_owner.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_owner.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authz_owner.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authz_owner - Win32 Release" +# Name "mod_authz_owner - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_authz_owner.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authz_owner.h b/modules/aaa/mod_authz_owner.h new file mode 100644 index 0000000..799f336 --- /dev/null +++ b/modules/aaa/mod_authz_owner.h @@ -0,0 +1,27 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOD_AUTHZ_OWNER_H +#define MOD_AUTHZ_OWNER_H + +#include "http_request.h" + +/* mod_authz_owner exports an optional function which retrieves the + * group name of the file identified by r->filename, if available, or + * else returns NULL. */ +APR_DECLARE_OPTIONAL_FN(char*, authz_owner_get_file_group, (request_rec *r)); + +#endif /* MOD_AUTHZ_OWNER_H */ diff --git a/modules/aaa/mod_authz_owner.mak b/modules/aaa/mod_authz_owner.mak new file mode 100644 index 0000000..850a1f7 --- /dev/null +++ b/modules/aaa/mod_authz_owner.mak @@ -0,0 +1,381 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authz_owner.dsp +!IF "$(CFG)" == "" +CFG=mod_authz_owner - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_authz_owner - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_authz_owner - Win32 Release" && "$(CFG)" != "mod_authz_owner - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_owner.mak" CFG="mod_authz_owner - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authz_owner - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authz_owner - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authz_owner - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authz_owner.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Release" "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authz_owner.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" "mod_auth_basic - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authz_owner.obj" + -@erase "$(INTDIR)\mod_authz_owner.res" + -@erase "$(INTDIR)\mod_authz_owner_src.idb" + -@erase "$(INTDIR)\mod_authz_owner_src.pdb" + -@erase "$(OUTDIR)\mod_authz_owner.exp" + -@erase "$(OUTDIR)\mod_authz_owner.lib" + -@erase "$(OUTDIR)\mod_authz_owner.pdb" + -@erase "$(OUTDIR)\mod_authz_owner.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authz_owner_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authz_owner.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authz_owner.so" /d LONG_NAME="authz_owner_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authz_owner.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authz_owner.pdb" /debug /out:"$(OUTDIR)\mod_authz_owner.so" /implib:"$(OUTDIR)\mod_authz_owner.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_owner.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authz_owner.obj" \ + "$(INTDIR)\mod_authz_owner.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authz_owner.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authz_owner.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authz_owner.so" + if exist .\Release\mod_authz_owner.so.manifest mt.exe -manifest .\Release\mod_authz_owner.so.manifest -outputresource:.\Release\mod_authz_owner.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authz_owner - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authz_owner.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Debug" "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authz_owner.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" "mod_auth_basic - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authz_owner.obj" + -@erase "$(INTDIR)\mod_authz_owner.res" + -@erase "$(INTDIR)\mod_authz_owner_src.idb" + -@erase "$(INTDIR)\mod_authz_owner_src.pdb" + -@erase "$(OUTDIR)\mod_authz_owner.exp" + -@erase "$(OUTDIR)\mod_authz_owner.lib" + -@erase "$(OUTDIR)\mod_authz_owner.pdb" + -@erase "$(OUTDIR)\mod_authz_owner.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authz_owner_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authz_owner.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authz_owner.so" /d LONG_NAME="authz_owner_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authz_owner.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authz_owner.pdb" /debug /out:"$(OUTDIR)\mod_authz_owner.so" /implib:"$(OUTDIR)\mod_authz_owner.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_owner.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authz_owner.obj" \ + "$(INTDIR)\mod_authz_owner.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authz_owner.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authz_owner.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authz_owner.so" + if exist .\Debug\mod_authz_owner.so.manifest mt.exe -manifest .\Debug\mod_authz_owner.so.manifest -outputresource:.\Debug\mod_authz_owner.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authz_owner.dep") +!INCLUDE "mod_authz_owner.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authz_owner.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authz_owner - Win32 Release" || "$(CFG)" == "mod_authz_owner - Win32 Debug" + +!IF "$(CFG)" == "mod_authz_owner - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_owner - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_owner - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_owner - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_owner - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_owner - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_owner - Win32 Release" + +"mod_auth_basic - Win32 Release" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" + cd "." + +"mod_auth_basic - Win32 ReleaseCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" RECURSE=1 CLEAN + cd "." + +!ELSEIF "$(CFG)" == "mod_authz_owner - Win32 Debug" + +"mod_auth_basic - Win32 Debug" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" + cd "." + +"mod_auth_basic - Win32 DebugCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" RECURSE=1 CLEAN + cd "." + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authz_owner - Win32 Release" + + +"$(INTDIR)\mod_authz_owner.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authz_owner.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authz_owner.so" /d LONG_NAME="authz_owner_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authz_owner - Win32 Debug" + + +"$(INTDIR)\mod_authz_owner.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authz_owner.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authz_owner.so" /d LONG_NAME="authz_owner_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authz_owner.c + +"$(INTDIR)\mod_authz_owner.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/aaa/mod_authz_user.c b/modules/aaa/mod_authz_user.c new file mode 100644 index 0000000..881f77f --- /dev/null +++ b/modules/aaa/mod_authz_user.c @@ -0,0 +1,146 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_strings.h" + +#include "ap_config.h" +#include "ap_provider.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" + +#include "mod_auth.h" + +typedef struct { + int dummy; /* just here to stop compiler warnings for now. */ +} authz_user_config_rec; + +static void *create_authz_user_dir_config(apr_pool_t *p, char *d) +{ + authz_user_config_rec *conf = apr_palloc(p, sizeof(*conf)); + + return conf; +} + +static const command_rec authz_user_cmds[] = +{ + {NULL} +}; + +module AP_MODULE_DECLARE_DATA authz_user_module; + +static authz_status user_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + const char *err = NULL; + const ap_expr_info_t *expr = parsed_require_args; + const char *require; + + const char *t, *w; + + if (!r->user) { + return AUTHZ_DENIED_NO_USER; + } + + require = ap_expr_str_exec(r, expr, &err); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02594) + "authz_user authorize: require user: Can't " + "evaluate require expression: %s", err); + return AUTHZ_DENIED; + } + + t = require; + while ((w = ap_getword_conf(r->pool, &t)) && w[0]) { + if (!strcmp(r->user, w)) { + return AUTHZ_GRANTED; + } + } + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01663) + "access to %s failed, reason: user '%s' does not meet " + "'require'ments for user to be allowed access", + r->uri, r->user); + + return AUTHZ_DENIED; +} + +static authz_status validuser_check_authorization(request_rec *r, + const char *require_line, + const void *parsed_require_line) +{ + if (!r->user) { + return AUTHZ_DENIED_NO_USER; + } + + return AUTHZ_GRANTED; +} + +static const char *user_parse_config(cmd_parms *cmd, const char *require_line, + const void **parsed_require_line) +{ + const char *expr_err = NULL; + ap_expr_info_t *expr; + + expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT, + &expr_err, NULL); + + if (expr_err) + return apr_pstrcat(cmd->temp_pool, + "Cannot parse expression in require line: ", + expr_err, NULL); + + *parsed_require_line = expr; + + return NULL; +} + +static const authz_provider authz_user_provider = +{ + &user_check_authorization, + &user_parse_config, +}; +static const authz_provider authz_validuser_provider = +{ + &validuser_check_authorization, + NULL, +}; + +static void register_hooks(apr_pool_t *p) +{ + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "user", + AUTHZ_PROVIDER_VERSION, + &authz_user_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "valid-user", + AUTHZ_PROVIDER_VERSION, + &authz_validuser_provider, + AP_AUTH_INTERNAL_PER_CONF); +} + +AP_DECLARE_MODULE(authz_user) = +{ + STANDARD20_MODULE_STUFF, + create_authz_user_dir_config, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + authz_user_cmds, /* command apr_table_t */ + register_hooks /* register hooks */ +}; diff --git a/modules/aaa/mod_authz_user.dep b/modules/aaa/mod_authz_user.dep new file mode 100644 index 0000000..648fa02 --- /dev/null +++ b/modules/aaa/mod_authz_user.dep @@ -0,0 +1,58 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_authz_user.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_authz_user.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\mod_auth.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/aaa/mod_authz_user.dsp b/modules/aaa/mod_authz_user.dsp new file mode 100644 index 0000000..91d80a6 --- /dev/null +++ b/modules/aaa/mod_authz_user.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_authz_user" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_authz_user - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_user.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_user.mak" CFG="mod_authz_user - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authz_user - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authz_user - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_authz_user - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_authz_user_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_authz_user.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authz_user.so" /d LONG_NAME="authz_user_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_authz_user.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_user.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_authz_user.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_user.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_authz_user.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_authz_user - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_authz_user_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_authz_user.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authz_user.so" /d LONG_NAME="authz_user_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authz_user.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_user.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_authz_user.so" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_user.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_authz_user.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_authz_user - Win32 Release" +# Name "mod_authz_user - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_authz_user.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/aaa/mod_authz_user.mak b/modules/aaa/mod_authz_user.mak new file mode 100644 index 0000000..0989f6e --- /dev/null +++ b/modules/aaa/mod_authz_user.mak @@ -0,0 +1,381 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_authz_user.dsp +!IF "$(CFG)" == "" +CFG=mod_authz_user - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_authz_user - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_authz_user - Win32 Release" && "$(CFG)" != "mod_authz_user - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_authz_user.mak" CFG="mod_authz_user - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_authz_user - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_authz_user - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_authz_user - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authz_user.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Release" "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_authz_user.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" "mod_auth_basic - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authz_user.obj" + -@erase "$(INTDIR)\mod_authz_user.res" + -@erase "$(INTDIR)\mod_authz_user_src.idb" + -@erase "$(INTDIR)\mod_authz_user_src.pdb" + -@erase "$(OUTDIR)\mod_authz_user.exp" + -@erase "$(OUTDIR)\mod_authz_user.lib" + -@erase "$(OUTDIR)\mod_authz_user.pdb" + -@erase "$(OUTDIR)\mod_authz_user.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authz_user_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authz_user.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_authz_user.so" /d LONG_NAME="authz_user_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authz_user.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authz_user.pdb" /debug /out:"$(OUTDIR)\mod_authz_user.so" /implib:"$(OUTDIR)\mod_authz_user.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_user.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_authz_user.obj" \ + "$(INTDIR)\mod_authz_user.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authz_user.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_authz_user.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authz_user.so" + if exist .\Release\mod_authz_user.so.manifest mt.exe -manifest .\Release\mod_authz_user.so.manifest -outputresource:.\Release\mod_authz_user.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_authz_user - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_authz_user.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "mod_auth_basic - Win32 Debug" "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_authz_user.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" "mod_auth_basic - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_authz_user.obj" + -@erase "$(INTDIR)\mod_authz_user.res" + -@erase "$(INTDIR)\mod_authz_user_src.idb" + -@erase "$(INTDIR)\mod_authz_user_src.pdb" + -@erase "$(OUTDIR)\mod_authz_user.exp" + -@erase "$(OUTDIR)\mod_authz_user.lib" + -@erase "$(OUTDIR)\mod_authz_user.pdb" + -@erase "$(OUTDIR)\mod_authz_user.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_authz_user_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_authz_user.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_authz_user.so" /d LONG_NAME="authz_user_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_authz_user.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_authz_user.pdb" /debug /out:"$(OUTDIR)\mod_authz_user.so" /implib:"$(OUTDIR)\mod_authz_user.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_authz_user.so +LINK32_OBJS= \ + "$(INTDIR)\mod_authz_user.obj" \ + "$(INTDIR)\mod_authz_user.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" \ + "$(OUTDIR)\mod_auth_basic.lib" + +"$(OUTDIR)\mod_authz_user.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_authz_user.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_authz_user.so" + if exist .\Debug\mod_authz_user.so.manifest mt.exe -manifest .\Debug\mod_authz_user.so.manifest -outputresource:.\Debug\mod_authz_user.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_authz_user.dep") +!INCLUDE "mod_authz_user.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_authz_user.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_authz_user - Win32 Release" || "$(CFG)" == "mod_authz_user - Win32 Debug" + +!IF "$(CFG)" == "mod_authz_user - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\aaa" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_user - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\aaa" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_user - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\aaa" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_user - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\aaa" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_user - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\aaa" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ELSEIF "$(CFG)" == "mod_authz_user - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\aaa" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\aaa" + +!ENDIF + +!IF "$(CFG)" == "mod_authz_user - Win32 Release" + +"mod_auth_basic - Win32 Release" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" + cd "." + +"mod_auth_basic - Win32 ReleaseCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Release" RECURSE=1 CLEAN + cd "." + +!ELSEIF "$(CFG)" == "mod_authz_user - Win32 Debug" + +"mod_auth_basic - Win32 Debug" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" + cd "." + +"mod_auth_basic - Win32 DebugCLEAN" : + cd "." + $(MAKE) /$(MAKEFLAGS) /F ".\mod_auth_basic.mak" CFG="mod_auth_basic - Win32 Debug" RECURSE=1 CLEAN + cd "." + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_authz_user - Win32 Release" + + +"$(INTDIR)\mod_authz_user.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authz_user.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_authz_user.so" /d LONG_NAME="authz_user_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_authz_user - Win32 Debug" + + +"$(INTDIR)\mod_authz_user.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_authz_user.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_authz_user.so" /d LONG_NAME="authz_user_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_authz_user.c + +"$(INTDIR)\mod_authz_user.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + |