summaryrefslogtreecommitdiffstats
path: root/usr.sbin/httpd/src
diff options
context:
space:
mode:
authorbeck <beck@openbsd.org>1999-09-29 06:28:49 +0000
committerbeck <beck@openbsd.org>1999-09-29 06:28:49 +0000
commita5311d6855861e61375991d1275235e931299ca4 (patch)
treef44f3e07a9dd26d791b37aaf78429c2019699036 /usr.sbin/httpd/src
parentadd -V option (diff)
downloadwireguard-openbsd-a5311d6855861e61375991d1275235e931299ca4.tar.xz
wireguard-openbsd-a5311d6855861e61375991d1275235e931299ca4.zip
Apache 1.3.9 + Mod_ssl 2.4.2 - now builds with apaci nastiness.
Diffstat (limited to 'usr.sbin/httpd/src')
-rw-r--r--usr.sbin/httpd/src/.gdbinit13
-rw-r--r--usr.sbin/httpd/src/Apache.dsp8
-rw-r--r--usr.sbin/httpd/src/Apache.mak102
-rw-r--r--usr.sbin/httpd/src/ApacheCore.def63
-rw-r--r--usr.sbin/httpd/src/ApacheCore.dsp12
-rw-r--r--usr.sbin/httpd/src/ApacheCore.mak572
-rw-r--r--usr.sbin/httpd/src/ApacheCoreOS2.def366
-rw-r--r--usr.sbin/httpd/src/CHANGES876
-rw-r--r--usr.sbin/httpd/src/CHANGES.SSL679
-rw-r--r--usr.sbin/httpd/src/Configuration128
-rw-r--r--usr.sbin/httpd/src/Configuration.tmpl141
-rw-r--r--usr.sbin/httpd/src/Configure531
-rw-r--r--usr.sbin/httpd/src/Makefile.bsd-wrapper64
-rw-r--r--usr.sbin/httpd/src/Makefile.nt11
-rw-r--r--usr.sbin/httpd/src/Makefile.tmpl25
-rw-r--r--usr.sbin/httpd/src/Makefile_win32.txt11
-rw-r--r--usr.sbin/httpd/src/Makefile_win32_debug.txt11
-rw-r--r--usr.sbin/httpd/src/README.EAPI340
-rw-r--r--usr.sbin/httpd/src/ap/Makefile.tmpl44
-rw-r--r--usr.sbin/httpd/src/ap/ap.dsp16
-rw-r--r--usr.sbin/httpd/src/ap/ap.mak380
-rw-r--r--usr.sbin/httpd/src/ap/ap_base64.c272
-rw-r--r--usr.sbin/httpd/src/ap/ap_checkpass.c111
-rw-r--r--usr.sbin/httpd/src/ap/ap_ctx.c27
-rw-r--r--usr.sbin/httpd/src/ap/ap_execve.c12
-rw-r--r--usr.sbin/httpd/src/ap/ap_getpass.c167
-rw-r--r--usr.sbin/httpd/src/ap/ap_hook.c129
-rw-r--r--usr.sbin/httpd/src/ap/ap_md5c.c (renamed from usr.sbin/httpd/src/main/md5c.c)213
-rw-r--r--usr.sbin/httpd/src/ap/ap_mm.c178
-rw-r--r--usr.sbin/httpd/src/ap/ap_sha1.c383
-rw-r--r--usr.sbin/httpd/src/ap/ap_snprintf.c229
-rw-r--r--usr.sbin/httpd/src/helpers/GuessOS30
-rw-r--r--usr.sbin/httpd/src/helpers/PrintPath5
-rw-r--r--usr.sbin/httpd/src/helpers/TestCompile81
-rw-r--r--usr.sbin/httpd/src/helpers/binbuild.sh154
-rw-r--r--usr.sbin/httpd/src/helpers/buildinfo.sh38
-rw-r--r--usr.sbin/httpd/src/helpers/checkheader.sh9
-rw-r--r--usr.sbin/httpd/src/helpers/dummy.c2
-rw-r--r--usr.sbin/httpd/src/helpers/find-dbm-lib17
-rw-r--r--usr.sbin/httpd/src/helpers/findcpp.sh21
-rw-r--r--usr.sbin/httpd/src/helpers/findprg.sh24
-rw-r--r--usr.sbin/httpd/src/helpers/fmn.sh9
-rw-r--r--usr.sbin/httpd/src/helpers/fp2rp2
-rw-r--r--usr.sbin/httpd/src/helpers/getuid.sh65
-rw-r--r--usr.sbin/httpd/src/helpers/install.sh30
-rw-r--r--usr.sbin/httpd/src/helpers/mkshadow.sh14
-rw-r--r--usr.sbin/httpd/src/helpers/ppl.sh4
-rw-r--r--usr.sbin/httpd/src/helpers/slo.sh28
-rw-r--r--usr.sbin/httpd/src/include/alloc.h49
-rw-r--r--usr.sbin/httpd/src/include/ap.h26
-rw-r--r--usr.sbin/httpd/src/include/ap_compat.h5
-rw-r--r--usr.sbin/httpd/src/include/ap_config.h175
-rw-r--r--usr.sbin/httpd/src/include/ap_ctx.h13
-rw-r--r--usr.sbin/httpd/src/include/ap_ctype.h1
-rw-r--r--usr.sbin/httpd/src/include/ap_hook.h511
-rw-r--r--usr.sbin/httpd/src/include/ap_md5.h19
-rw-r--r--usr.sbin/httpd/src/include/ap_mm.h130
-rw-r--r--usr.sbin/httpd/src/include/ap_mmn.h27
-rw-r--r--usr.sbin/httpd/src/include/ap_sha1.h102
-rw-r--r--usr.sbin/httpd/src/include/buff.h4
-rw-r--r--usr.sbin/httpd/src/include/hsregex.h2
-rw-r--r--usr.sbin/httpd/src/include/http_conf_globals.h2
-rw-r--r--usr.sbin/httpd/src/include/http_config.h14
-rw-r--r--usr.sbin/httpd/src/include/http_core.h30
-rw-r--r--usr.sbin/httpd/src/include/http_protocol.h1
-rw-r--r--usr.sbin/httpd/src/include/http_request.h3
-rw-r--r--usr.sbin/httpd/src/include/httpd.h81
-rw-r--r--usr.sbin/httpd/src/include/scoreboard.h4
-rw-r--r--usr.sbin/httpd/src/include/util_md5.h4
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/CHANGES41
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/Makefile.tmpl26
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/asciitab.h62
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/expat.html73
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/hashtable.c151
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/hashtable.h69
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/iasciitab.h63
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/latin1tab.h62
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/nametab.h150
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/utf8tab.h63
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/xmldef.h70
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/xmlparse.c3256
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/xmlparse.h482
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/xmlrole.c1113
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/xmlrole.h111
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/xmltok.c1527
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/xmltok.h307
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/xmltok_impl.c1746
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/xmltok_impl.h71
-rw-r--r--usr.sbin/httpd/src/lib/expat-lite/xmltok_ns.c96
-rw-r--r--usr.sbin/httpd/src/main/Makefile.tmpl5
-rw-r--r--usr.sbin/httpd/src/main/alloc.c365
-rw-r--r--usr.sbin/httpd/src/main/buff.c36
-rw-r--r--usr.sbin/httpd/src/main/http_config.c55
-rw-r--r--usr.sbin/httpd/src/main/http_core.c453
-rw-r--r--usr.sbin/httpd/src/main/http_log.c52
-rw-r--r--usr.sbin/httpd/src/main/http_main.c1402
-rw-r--r--usr.sbin/httpd/src/main/http_protocol.c527
-rw-r--r--usr.sbin/httpd/src/main/http_request.c52
-rw-r--r--usr.sbin/httpd/src/main/rfc1413.c14
-rw-r--r--usr.sbin/httpd/src/main/util.c475
-rw-r--r--usr.sbin/httpd/src/main/util_date.c2
-rw-r--r--usr.sbin/httpd/src/main/util_md5.c31
-rw-r--r--usr.sbin/httpd/src/main/util_script.c484
-rw-r--r--usr.sbin/httpd/src/main/util_uri.c31
-rw-r--r--usr.sbin/httpd/src/modules/example/mod_example.c2
-rw-r--r--usr.sbin/httpd/src/modules/experimental/Makefile.tmpl9
-rw-r--r--usr.sbin/httpd/src/modules/experimental/mod_auth_digest.c1919
-rw-r--r--usr.sbin/httpd/src/modules/extra/mod_define.c446
-rw-r--r--usr.sbin/httpd/src/modules/proxy/ApacheModuleProxy.dsp8
-rw-r--r--usr.sbin/httpd/src/modules/proxy/ApacheModuleProxy.mak123
-rw-r--r--usr.sbin/httpd/src/modules/proxy/Makefile.OS26
-rw-r--r--usr.sbin/httpd/src/modules/proxy/Makefile.tmpl7
-rw-r--r--usr.sbin/httpd/src/modules/proxy/mod_proxy.c2
-rw-r--r--usr.sbin/httpd/src/modules/proxy/mod_proxy.h2
-rw-r--r--usr.sbin/httpd/src/modules/proxy/proxy_cache.c151
-rw-r--r--usr.sbin/httpd/src/modules/proxy/proxy_connect.c11
-rw-r--r--usr.sbin/httpd/src/modules/proxy/proxy_ftp.c103
-rw-r--r--usr.sbin/httpd/src/modules/proxy/proxy_http.c42
-rw-r--r--usr.sbin/httpd/src/modules/proxy/proxy_util.c94
-rw-r--r--usr.sbin/httpd/src/modules/ssl/Makefile.libdir8
-rw-r--r--usr.sbin/httpd/src/modules/ssl/Makefile.tmpl293
-rw-r--r--usr.sbin/httpd/src/modules/ssl/Makefile.win3226
-rw-r--r--usr.sbin/httpd/src/modules/ssl/README86
-rw-r--r--usr.sbin/httpd/src/modules/ssl/README.dsov.fig62
-rw-r--r--usr.sbin/httpd/src/modules/ssl/README.dsov.ps52
-rw-r--r--usr.sbin/httpd/src/modules/ssl/libssl.module128
-rw-r--r--usr.sbin/httpd/src/modules/ssl/libssl.version2
-rw-r--r--usr.sbin/httpd/src/modules/ssl/mod_ssl.c35
-rw-r--r--usr.sbin/httpd/src/modules/ssl/mod_ssl.h218
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_compat.c81
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_config.c197
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_dh.c255
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_ds.c12
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_ext.c113
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_init.c505
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_io.c285
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_kernel.c1056
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_log.c45
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_mutex.c68
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_pphrase.c385
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_rand.c25
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_scache.c618
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_vars.c72
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_expr.c12
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_expr.h12
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_expr_eval.c12
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_expr_parse.c40
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_expr_parse.y8
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_expr_scan.c2002
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_expr_scan.l8
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_util.c97
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_util_sdbm.c12
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_util_sdbm.h12
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_util_ssl.c384
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_util_ssl.h37
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_util_table.c2868
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_util_table.h189
-rw-r--r--usr.sbin/httpd/src/modules/standard/Makefile.OS2115
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_access.c2
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_alias.c2
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_auth.c11
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_auth_db.c11
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_auth_dbm.c16
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_autoindex.c511
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_cgi.c37
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_dir.c4
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_env.c50
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_imap.c2
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_include.c71
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_info.c3
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_log_config.c154
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_mime.c9
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_mime_magic.c48
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_negotiation.c236
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_rewrite.c251
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_rewrite.h36
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_setenvif.c14
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_so.c7
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_speling.c78
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_status.c85
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_unique_id.c6
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_userdir.c2
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_usertrack.c75
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_vhost_alias.c482
-rw-r--r--usr.sbin/httpd/src/os/bs2000/Makefile.tmpl48
-rw-r--r--usr.sbin/httpd/src/os/bs2000/bs2login.c199
-rw-r--r--usr.sbin/httpd/src/os/bs2000/os.h15
-rw-r--r--usr.sbin/httpd/src/os/os2/Makefile.tmpl24
-rw-r--r--usr.sbin/httpd/src/os/os2/os.c52
-rw-r--r--usr.sbin/httpd/src/os/os2/os.h15
-rw-r--r--usr.sbin/httpd/src/os/os2/util_os2.c69
-rw-r--r--usr.sbin/httpd/src/os/tpf/Makefile.tmpl5
-rw-r--r--usr.sbin/httpd/src/os/tpf/cgetop.c151
-rw-r--r--usr.sbin/httpd/src/os/tpf/os.c297
-rw-r--r--usr.sbin/httpd/src/os/tpf/os.h107
-rw-r--r--usr.sbin/httpd/src/os/unix/os.c28
-rw-r--r--usr.sbin/httpd/src/os/unix/os.h3
-rw-r--r--usr.sbin/httpd/src/os/win32/ApacheModuleRewrite.dsp8
-rw-r--r--usr.sbin/httpd/src/os/win32/ApacheModuleRewrite.mak23
-rw-r--r--usr.sbin/httpd/src/os/win32/apache.icobin0 -> 766 bytes
-rw-r--r--usr.sbin/httpd/src/os/win32/apache.rc84
-rw-r--r--usr.sbin/httpd/src/os/win32/installer/apache.iwz454
-rw-r--r--usr.sbin/httpd/src/os/win32/installer/installdll/install.c199
-rw-r--r--usr.sbin/httpd/src/os/win32/installer/installdll/install.dsp8
-rw-r--r--usr.sbin/httpd/src/os/win32/installer/installdll/install.mak175
-rw-r--r--usr.sbin/httpd/src/os/win32/installer/installdll/test/resource.h13
-rw-r--r--usr.sbin/httpd/src/os/win32/installer/installdll/test/test.c125
-rw-r--r--usr.sbin/httpd/src/os/win32/installer/installdll/test/test.mak11
-rw-r--r--usr.sbin/httpd/src/os/win32/installer/installdll/test/test.rc38
-rw-r--r--usr.sbin/httpd/src/os/win32/os.h6
-rw-r--r--usr.sbin/httpd/src/os/win32/registry.c156
-rw-r--r--usr.sbin/httpd/src/os/win32/registry.h2
-rw-r--r--usr.sbin/httpd/src/os/win32/resource.h17
-rw-r--r--usr.sbin/httpd/src/os/win32/service.c251
-rw-r--r--usr.sbin/httpd/src/os/win32/service.h10
-rw-r--r--usr.sbin/httpd/src/os/win32/util_win32.c11
-rw-r--r--usr.sbin/httpd/src/regex/debug.c1
-rw-r--r--usr.sbin/httpd/src/regex/main.c4
-rw-r--r--usr.sbin/httpd/src/regex/regex.34
-rw-r--r--usr.sbin/httpd/src/regex/regex.72
-rw-r--r--usr.sbin/httpd/src/regex/split.c2
-rw-r--r--usr.sbin/httpd/src/support/Makefile.tmpl12
-rw-r--r--usr.sbin/httpd/src/support/README62
-rw-r--r--usr.sbin/httpd/src/support/SHA1/README.sha134
-rw-r--r--usr.sbin/httpd/src/support/SHA1/convert-sha1.pl36
-rw-r--r--usr.sbin/httpd/src/support/SHA1/htpasswd-sha1.pl22
-rw-r--r--usr.sbin/httpd/src/support/SHA1/ldif-sha1.example19
-rw-r--r--usr.sbin/httpd/src/support/ab.8 (renamed from usr.sbin/httpd/src/support/ab.1)124
-rw-r--r--usr.sbin/httpd/src/support/ab.c1068
-rw-r--r--usr.sbin/httpd/src/support/apachectl2
-rw-r--r--usr.sbin/httpd/src/support/apachectl.8 (renamed from usr.sbin/httpd/src/support/apachectl.1)38
-rw-r--r--usr.sbin/httpd/src/support/apxs.880
-rw-r--r--usr.sbin/httpd/src/support/apxs.pl105
-rw-r--r--usr.sbin/httpd/src/support/ca-fix.c609
-rw-r--r--usr.sbin/httpd/src/support/dbmmanage.161
-rw-r--r--usr.sbin/httpd/src/support/htdigest.122
-rw-r--r--usr.sbin/httpd/src/support/htdigest.c98
-rw-r--r--usr.sbin/httpd/src/support/htdigest.dsp103
-rw-r--r--usr.sbin/httpd/src/support/htdigest.mak297
-rw-r--r--usr.sbin/httpd/src/support/htpasswd.1139
-rw-r--r--usr.sbin/httpd/src/support/htpasswd.c631
-rw-r--r--usr.sbin/httpd/src/support/htpasswd.dsp119
-rw-r--r--usr.sbin/httpd/src/support/htpasswd.mak550
-rw-r--r--usr.sbin/httpd/src/support/httpd.843
-rw-r--r--usr.sbin/httpd/src/support/httpd.exp102
-rw-r--r--usr.sbin/httpd/src/support/log_server_status9
-rw-r--r--usr.sbin/httpd/src/support/logresolve.810
-rw-r--r--usr.sbin/httpd/src/support/mkcert.sh542
-rw-r--r--usr.sbin/httpd/src/support/rotatelogs.82
-rw-r--r--usr.sbin/httpd/src/support/suexec.84
-rw-r--r--usr.sbin/httpd/src/support/suexec.c37
251 files changed, 37965 insertions, 6568 deletions
diff --git a/usr.sbin/httpd/src/.gdbinit b/usr.sbin/httpd/src/.gdbinit
index b0aa1e7794f..564d9c3a255 100644
--- a/usr.sbin/httpd/src/.gdbinit
+++ b/usr.sbin/httpd/src/.gdbinit
@@ -13,3 +13,16 @@ end
document dump_table
Print the key/value pairs in a table.
end
+
+define dump_string_array
+ set $a = (char **)((array_header *)$arg0)->elts
+ set $n = (int)((array_header *)$arg0)->nelts
+ set $i = 0
+ while $i < $n
+ printf "[%u] '%s'\n", $i, $a[$i]
+ set $i = $i + 1
+ end
+end
+document dump_string_array
+ Print all of the elements in an array of strings.
+end
diff --git a/usr.sbin/httpd/src/Apache.dsp b/usr.sbin/httpd/src/Apache.dsp
index 25766afeb59..bbb644ded95 100644
--- a/usr.sbin/httpd/src/Apache.dsp
+++ b/usr.sbin/httpd/src/Apache.dsp
@@ -96,6 +96,14 @@ SOURCE=.\os\win32\main_win32.c
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\os\win32\apache.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\win32\apache.rc
+# End Source File
# End Group
# End Target
# End Project
diff --git a/usr.sbin/httpd/src/Apache.mak b/usr.sbin/httpd/src/Apache.mak
index 738e11bdb06..b44f43e0721 100644
--- a/usr.sbin/httpd/src/Apache.mak
+++ b/usr.sbin/httpd/src/Apache.mak
@@ -25,9 +25,6 @@ NULL=
NULL=nul
!ENDIF
-CPP=cl.exe
-RSC=rc.exe
-
!IF "$(CFG)" == "Apache - Win32 Release"
OUTDIR=.\ApacheR
@@ -47,6 +44,7 @@ ALL : "$(OUTDIR)\Apache.exe"
!ENDIF
CLEAN :
+ -@erase "$(INTDIR)\apache.res"
-@erase "$(INTDIR)\main_win32.obj"
-@erase "$(INTDIR)\vc50.idb"
-@erase "$(OUTDIR)\Apache.exe"
@@ -54,10 +52,44 @@ CLEAN :
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+CPP=cl.exe
CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
/Fp"$(INTDIR)\Apache.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
CPP_OBJS=.\ApacheR/
CPP_SBRS=.
+
+.c{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\apache.res" /d "NDEBUG"
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\Apache.bsc"
BSC32_SBRS= \
@@ -68,6 +100,7 @@ LINK32_FLAGS=CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\
/incremental:no /pdb:"$(OUTDIR)\Apache.pdb" /machine:I386\
/out:"$(OUTDIR)\Apache.exe"
LINK32_OBJS= \
+ "$(INTDIR)\apache.res" \
"$(INTDIR)\main_win32.obj"
"$(OUTDIR)\Apache.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
@@ -94,6 +127,7 @@ ALL : "$(OUTDIR)\Apache.exe"
!ENDIF
CLEAN :
+ -@erase "$(INTDIR)\apache.res"
-@erase "$(INTDIR)\main_win32.obj"
-@erase "$(INTDIR)\vc50.idb"
-@erase "$(INTDIR)\vc50.pdb"
@@ -104,28 +138,11 @@ CLEAN :
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+CPP=cl.exe
CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
/Fp"$(INTDIR)\Apache.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
CPP_OBJS=.\ApacheD/
CPP_SBRS=.
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\Apache.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\
- winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console\
- /incremental:yes /pdb:"$(OUTDIR)\Apache.pdb" /debug /machine:I386\
- /out:"$(OUTDIR)\Apache.exe"
-LINK32_OBJS= \
- "$(INTDIR)\main_win32.obj"
-
-"$(OUTDIR)\Apache.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
.c{$(CPP_OBJS)}.obj::
$(CPP) @<<
@@ -157,6 +174,28 @@ LINK32_OBJS= \
$(CPP_PROJ) $<
<<
+RSC=rc.exe
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\apache.res" /d "_DEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\Apache.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\
+ winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console\
+ /incremental:yes /pdb:"$(OUTDIR)\Apache.pdb" /debug /machine:I386\
+ /out:"$(OUTDIR)\Apache.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\apache.res" \
+ "$(INTDIR)\main_win32.obj"
+
+"$(OUTDIR)\Apache.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
!IF "$(CFG)" == "Apache - Win32 Release" || "$(CFG)" == "Apache - Win32 Debug"
SOURCE=.\os\win32\main_win32.c
@@ -165,6 +204,27 @@ SOURCE=.\os\win32\main_win32.c
$(CPP) $(CPP_PROJ) $(SOURCE)
+SOURCE=.\os\win32\apache.rc
+DEP_RSC_APACH=\
+ ".\os\win32\apache.ico"\
+
+
+!IF "$(CFG)" == "Apache - Win32 Release"
+
+
+"$(INTDIR)\apache.res" : $(SOURCE) $(DEP_RSC_APACH) "$(INTDIR)"
+ $(RSC) /l 0x809 /fo"$(INTDIR)\apache.res" /i "os\win32" /d "NDEBUG" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "Apache - Win32 Debug"
+
+
+"$(INTDIR)\apache.res" : $(SOURCE) $(DEP_RSC_APACH) "$(INTDIR)"
+ $(RSC) /l 0x809 /fo"$(INTDIR)\apache.res" /i "os\win32" /d "_DEBUG" $(SOURCE)
+
+
+!ENDIF
+
!ENDIF
diff --git a/usr.sbin/httpd/src/ApacheCore.def b/usr.sbin/httpd/src/ApacheCore.def
index ce7044e12f7..e82c26d2b61 100644
--- a/usr.sbin/httpd/src/ApacheCore.def
+++ b/usr.sbin/httpd/src/ApacheCore.def
@@ -320,21 +320,56 @@ EXPORTS
ap_method_number_of @313
ap_exists_config_define @314
ap_single_module_configure @315
- ap_single_module_init @316
ap_make_etag @317
ap_array_pstrcat @318
ap_os_is_filename_valid @319
- ap_add_config_define @320
- ap_global_ctx @321
- ap_ctx_new @322
- ap_ctx_get @323
- ap_ctx_set @324
- ap_hook_init @325
- ap_hook_kill @326
- ap_hook_configure @327
- ap_hook_register_I @328
- ap_hook_unregister_I @329
- ap_hook_status @330
- ap_hook_use @331
- ap_hook_call @332
+ ap_find_list_item @320
+ ap_MD5Encode @321
+ ap_validate_password @322
+ ap_size_list_item @323
+ ap_get_list_item @324
+ ap_scoreboard_fname @325
+ ap_pid_fname @326
+ ap_excess_requests_per_child @327
+ ap_threads_per_child @328
+ ap_max_requests_per_child @329
+ ap_daemons_to_start @330
+ ap_daemons_min_free @331
+ ap_daemons_max_free @332
+ ap_daemons_limit @333
+ ap_user_name @334
+ ap_user_id @335
+ ap_group_id @336
+ ap_standalone @337
+ ap_server_confname @338
+ ap_sub_req_method_uri @339
+ ap_regerror @341
+ ap_regexec @342
+ ap_field_noparam @343
+ ap_pbase64decode @344
+ ap_pbase64encode @345
+ ap_base64encode @346
+ ap_base64encode_binary @347
+ ap_base64encode_len @348
+ ap_base64decode @349
+ ap_base64decode_binary @350
+ ap_base64decode_len @351
+ ap_SHA1Init @352
+ ap_SHA1Update_binary @353
+ ap_SHA1Update @354
+ ap_SHA1Final @355
+ ap_sha1_base64 @356
+ ap_add_config_define @357
+ ap_global_ctx @358
+ ap_ctx_new @359
+ ap_ctx_get @360
+ ap_ctx_set @361
+ ap_hook_init @362
+ ap_hook_kill @363
+ ap_hook_configure @364
+ ap_hook_register_I @365
+ ap_hook_unregister_I @366
+ ap_hook_status @367
+ ap_hook_use @368
+ ap_hook_call @369
diff --git a/usr.sbin/httpd/src/ApacheCore.dsp b/usr.sbin/httpd/src/ApacheCore.dsp
index 21e5880f56e..511e5feefe1 100644
--- a/usr.sbin/httpd/src/ApacheCore.dsp
+++ b/usr.sbin/httpd/src/ApacheCore.dsp
@@ -44,7 +44,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I ".\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I ".\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
@@ -54,7 +54,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
-# ADD LINK32 os\win32\ApacheOSR\ApacheOS.lib regex\release\regex.lib ap\Release\ap.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 os\win32\ApacheOSR\ApacheOS.lib regex\release\regex.lib ap\Release\ap.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:windows /dll /machine:I386
!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
@@ -70,7 +70,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I ".\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I ".\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
@@ -80,7 +80,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
-# ADD LINK32 os\win32\ApacheOSD\ApacheOS.lib regex\debug\regex.lib ap\Debug\ap.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 os\win32\ApacheOSD\ApacheOS.lib regex\debug\regex.lib ap\Debug\ap.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:windows /dll /debug /machine:I386
# SUBTRACT LINK32 /map
!ENDIF
@@ -142,10 +142,6 @@ SOURCE=.\main\http_vhost.c
# End Source File
# Begin Source File
-SOURCE=.\main\md5c.c
-# End Source File
-# Begin Source File
-
SOURCE=.\modules\standard\mod_access.c
# End Source File
# Begin Source File
diff --git a/usr.sbin/httpd/src/ApacheCore.mak b/usr.sbin/httpd/src/ApacheCore.mak
index e253234629d..8b012c51223 100644
--- a/usr.sbin/httpd/src/ApacheCore.mak
+++ b/usr.sbin/httpd/src/ApacheCore.mak
@@ -28,6 +28,10 @@ NULL=
NULL=nul
!ENDIF
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
!IF "$(CFG)" == "ApacheCore - Win32 Release"
OUTDIR=.\CoreR
@@ -58,7 +62,6 @@ CLEAN :
-@erase "$(INTDIR)\http_protocol.obj"
-@erase "$(INTDIR)\http_request.obj"
-@erase "$(INTDIR)\http_vhost.obj"
- -@erase "$(INTDIR)\md5c.obj"
-@erase "$(INTDIR)\mod_access.obj"
-@erase "$(INTDIR)\mod_actions.obj"
-@erase "$(INTDIR)\mod_alias.obj"
@@ -90,8 +93,6 @@ CLEAN :
-@erase "$(INTDIR)\util_uri.obj"
-@erase "$(INTDIR)\util_win32.obj"
-@erase "$(INTDIR)\vc50.idb"
- -@erase "$(INTDIR)\ApacheCore.pch"
- -@erase "$(OUTDIR)\ApacheCore.pch"
-@erase "$(OUTDIR)\ApacheCore.dll"
-@erase "$(OUTDIR)\ApacheCore.exp"
-@erase "$(OUTDIR)\ApacheCore.lib"
@@ -99,46 +100,12 @@ CLEAN :
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /GX /O2 /I ".\include" /D "WIN32" /D "NDEBUG" /D\
- "_WINDOWS" /Fp"$(INTDIR)\ApacheCore.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\
- /FD /c
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I ".\include" /D "NDEBUG" /D "WIN32" /D\
+ "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /Fp"$(INTDIR)\ApacheCore.pch" /YX\
+ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
CPP_OBJS=.\CoreR/
CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheCore.bsc"
BSC32_SBRS= \
@@ -146,7 +113,7 @@ BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=os\win32\ApacheOSR\ApacheOS.lib regex\release\regex.lib\
ap\Release\ap.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
- advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll\
+ advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:windows /dll\
/incremental:no /pdb:"$(OUTDIR)\ApacheCore.pdb" /machine:I386\
/def:".\ApacheCore.def" /out:"$(OUTDIR)\ApacheCore.dll"\
/implib:"$(OUTDIR)\ApacheCore.lib"
@@ -164,7 +131,6 @@ LINK32_OBJS= \
"$(INTDIR)\http_protocol.obj" \
"$(INTDIR)\http_request.obj" \
"$(INTDIR)\http_vhost.obj" \
- "$(INTDIR)\md5c.obj" \
"$(INTDIR)\mod_access.obj" \
"$(INTDIR)\mod_actions.obj" \
"$(INTDIR)\mod_alias.obj" \
@@ -242,8 +208,6 @@ CLEAN :
-@erase "$(INTDIR)\http_request.sbr"
-@erase "$(INTDIR)\http_vhost.obj"
-@erase "$(INTDIR)\http_vhost.sbr"
- -@erase "$(INTDIR)\md5c.obj"
- -@erase "$(INTDIR)\md5c.sbr"
-@erase "$(INTDIR)\mod_access.obj"
-@erase "$(INTDIR)\mod_access.sbr"
-@erase "$(INTDIR)\mod_actions.obj"
@@ -306,8 +270,6 @@ CLEAN :
-@erase "$(INTDIR)\util_win32.sbr"
-@erase "$(INTDIR)\vc50.idb"
-@erase "$(INTDIR)\vc50.pdb"
- -@erase "$(INTDIR)\ApacheCore.pch"
- -@erase "$(OUTDIR)\ApacheCore.pch"
-@erase "$(OUTDIR)\ApacheCore.bsc"
-@erase "$(OUTDIR)\ApacheCore.dll"
-@erase "$(OUTDIR)\ApacheCore.exp"
@@ -318,46 +280,12 @@ CLEAN :
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I ".\include" /D "WIN32" /D "_DEBUG"\
- /D "_WINDOWS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\ApacheCore.pch" /YX\
- /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I ".\include" /D "_DEBUG" /D "WIN32"\
+ /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /FR"$(INTDIR)\\"\
+ /Fp"$(INTDIR)\ApacheCore.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
CPP_OBJS=.\CoreD/
CPP_SBRS=.\CoreD/
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheCore.bsc"
BSC32_SBRS= \
@@ -372,7 +300,6 @@ BSC32_SBRS= \
"$(INTDIR)\http_protocol.sbr" \
"$(INTDIR)\http_request.sbr" \
"$(INTDIR)\http_vhost.sbr" \
- "$(INTDIR)\md5c.sbr" \
"$(INTDIR)\mod_access.sbr" \
"$(INTDIR)\mod_actions.sbr" \
"$(INTDIR)\mod_alias.sbr" \
@@ -412,7 +339,7 @@ BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=os\win32\ApacheOSD\ApacheOS.lib regex\debug\regex.lib\
ap\Debug\ap.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
- advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll\
+ advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:windows /dll\
/incremental:yes /pdb:"$(OUTDIR)\ApacheCore.pdb" /debug /machine:I386\
/def:".\ApacheCore.def" /out:"$(OUTDIR)\ApacheCore.dll"\
/implib:"$(OUTDIR)\ApacheCore.lib"
@@ -430,7 +357,6 @@ LINK32_OBJS= \
"$(INTDIR)\http_protocol.obj" \
"$(INTDIR)\http_request.obj" \
"$(INTDIR)\http_vhost.obj" \
- "$(INTDIR)\md5c.obj" \
"$(INTDIR)\mod_access.obj" \
"$(INTDIR)\mod_actions.obj" \
"$(INTDIR)\mod_alias.obj" \
@@ -469,6 +395,36 @@ LINK32_OBJS= \
!ENDIF
+.c{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
!IF "$(CFG)" == "ApacheCore - Win32 Release" || "$(CFG)" ==\
"ApacheCore - Win32 Debug"
@@ -481,6 +437,7 @@ DEP_CPP_ALLOC=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_log.h"\
@@ -502,6 +459,7 @@ DEP_CPP_ALLOC=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_log.h"\
@@ -510,14 +468,6 @@ DEP_CPP_ALLOC=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_ALLOC=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\alloc.obj" "$(INTDIR)\alloc.sbr" : $(SOURCE) $(DEP_CPP_ALLOC)\
@@ -536,6 +486,7 @@ DEP_CPP_BUFF_=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_log.h"\
@@ -557,6 +508,7 @@ DEP_CPP_BUFF_=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_log.h"\
@@ -565,14 +517,6 @@ DEP_CPP_BUFF_=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_BUFF_=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\buff.obj" "$(INTDIR)\buff.sbr" : $(SOURCE) $(DEP_CPP_BUFF_)\
@@ -591,6 +535,7 @@ DEP_CPP_BUILD=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\httpd.h"\
@@ -609,20 +554,13 @@ DEP_CPP_BUILD=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\httpd.h"\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_BUILD=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\buildmark.obj" "$(INTDIR)\buildmark.sbr" : $(SOURCE)\
@@ -658,6 +596,7 @@ DEP_CPP_HTTP_=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\explain.h"\
".\include\hsregex.h"\
@@ -684,6 +623,7 @@ DEP_CPP_HTTP_=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\explain.h"\
".\include\hsregex.h"\
@@ -697,14 +637,6 @@ DEP_CPP_HTTP_=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_HTTP_=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\http_config.obj" "$(INTDIR)\http_config.sbr" : $(SOURCE)\
@@ -724,6 +656,7 @@ DEP_CPP_HTTP_C=\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
".\include\ap_md5.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\fnmatch.h"\
".\include\hsregex.h"\
@@ -756,6 +689,7 @@ DEP_CPP_HTTP_C=\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
".\include\ap_md5.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\fnmatch.h"\
".\include\hsregex.h"\
@@ -774,14 +708,6 @@ DEP_CPP_HTTP_C=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_HTTP_C=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\http_core.obj" "$(INTDIR)\http_core.sbr" : $(SOURCE)\
@@ -800,8 +726,10 @@ DEP_CPP_HTTP_L=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
".\include\http_config.h"\
".\include\http_core.h"\
".\include\http_log.h"\
@@ -823,8 +751,10 @@ DEP_CPP_HTTP_L=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
".\include\http_config.h"\
".\include\http_core.h"\
".\include\http_log.h"\
@@ -833,14 +763,6 @@ DEP_CPP_HTTP_L=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_HTTP_L=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\http_log.obj" "$(INTDIR)\http_log.sbr" : $(SOURCE) $(DEP_CPP_HTTP_L)\
@@ -859,6 +781,7 @@ DEP_CPP_HTTP_M=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\explain.h"\
".\include\hsregex.h"\
@@ -893,6 +816,7 @@ DEP_CPP_HTTP_M=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\explain.h"\
".\include\hsregex.h"\
@@ -914,14 +838,6 @@ DEP_CPP_HTTP_M=\
".\os\win32\readdir.h"\
".\os\win32\registry.h"\
".\os\win32\service.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_HTTP_M=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\http_main.obj" "$(INTDIR)\http_main.sbr" : $(SOURCE)\
@@ -940,6 +856,7 @@ DEP_CPP_HTTP_P=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_conf_globals.h"\
@@ -968,6 +885,7 @@ DEP_CPP_HTTP_P=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_conf_globals.h"\
@@ -983,14 +901,6 @@ DEP_CPP_HTTP_P=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_HTTP_P=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\http_protocol.obj" "$(INTDIR)\http_protocol.sbr" : $(SOURCE)\
@@ -1009,9 +919,11 @@ DEP_CPP_HTTP_R=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\fnmatch.h"\
".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
".\include\http_config.h"\
".\include\http_core.h"\
".\include\http_log.h"\
@@ -1036,9 +948,11 @@ DEP_CPP_HTTP_R=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\fnmatch.h"\
".\include\hsregex.h"\
+ ".\include\http_conf_globals.h"\
".\include\http_config.h"\
".\include\http_core.h"\
".\include\http_log.h"\
@@ -1050,14 +964,6 @@ DEP_CPP_HTTP_R=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_HTTP_R=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\http_request.obj" "$(INTDIR)\http_request.sbr" : $(SOURCE)\
@@ -1076,6 +982,7 @@ DEP_CPP_HTTP_V=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_conf_globals.h"\
@@ -1100,6 +1007,7 @@ DEP_CPP_HTTP_V=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_conf_globals.h"\
@@ -1111,14 +1019,6 @@ DEP_CPP_HTTP_V=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_HTTP_V=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\http_vhost.obj" "$(INTDIR)\http_vhost.sbr" : $(SOURCE)\
@@ -1128,46 +1028,6 @@ NODEP_CPP_HTTP_V=\
!ENDIF
-SOURCE=.\main\md5c.c
-
-!IF "$(CFG)" == "ApacheCore - Win32 Release"
-
-DEP_CPP_MD5C_=\
- ".\include\ap_config.h"\
- ".\include\ap_ctype.h"\
- ".\include\ap_md5.h"\
- ".\include\hsregex.h"\
- ".\os\win32\os.h"\
-
-
-"$(INTDIR)\md5c.obj" : $(SOURCE) $(DEP_CPP_MD5C_) "$(INTDIR)"
- $(CPP) $(CPP_PROJ) $(SOURCE)
-
-
-!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
-
-DEP_CPP_MD5C_=\
- ".\include\ap_config.h"\
- ".\include\ap_ctype.h"\
- ".\include\ap_md5.h"\
- ".\include\hsregex.h"\
- ".\os\win32\os.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MD5C_=\
- ".\include\ap_config_auto.h"\
- ".\include\os.h"\
- ".\main\ebcdic.h"\
-
-
-"$(INTDIR)\md5c.obj" "$(INTDIR)\md5c.sbr" : $(SOURCE) $(DEP_CPP_MD5C_)\
- "$(INTDIR)"
- $(CPP) $(CPP_PROJ) $(SOURCE)
-
-
-!ENDIF
-
SOURCE=.\modules\standard\mod_access.c
!IF "$(CFG)" == "ApacheCore - Win32 Release"
@@ -1177,6 +1037,7 @@ DEP_CPP_MOD_A=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1200,6 +1061,7 @@ DEP_CPP_MOD_A=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1210,14 +1072,6 @@ DEP_CPP_MOD_A=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_A=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_access.obj" "$(INTDIR)\mod_access.sbr" : $(SOURCE)\
@@ -1236,6 +1090,7 @@ DEP_CPP_MOD_AC=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1262,6 +1117,7 @@ DEP_CPP_MOD_AC=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1275,14 +1131,6 @@ DEP_CPP_MOD_AC=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_AC=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_actions.obj" "$(INTDIR)\mod_actions.sbr" : $(SOURCE)\
@@ -1301,6 +1149,7 @@ DEP_CPP_MOD_AL=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1321,6 +1170,7 @@ DEP_CPP_MOD_AL=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1328,14 +1178,6 @@ DEP_CPP_MOD_AL=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_AL=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_alias.obj" "$(INTDIR)\mod_alias.sbr" : $(SOURCE)\
@@ -1354,6 +1196,7 @@ DEP_CPP_MOD_AS=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1379,6 +1222,7 @@ DEP_CPP_MOD_AS=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1391,14 +1235,6 @@ DEP_CPP_MOD_AS=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_AS=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_asis.obj" "$(INTDIR)\mod_asis.sbr" : $(SOURCE) $(DEP_CPP_MOD_AS)\
@@ -1417,6 +1253,8 @@ DEP_CPP_MOD_AU=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_md5.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1440,6 +1278,8 @@ DEP_CPP_MOD_AU=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_md5.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1450,14 +1290,6 @@ DEP_CPP_MOD_AU=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_AU=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_auth.obj" "$(INTDIR)\mod_auth.sbr" : $(SOURCE) $(DEP_CPP_MOD_AU)\
@@ -1476,7 +1308,9 @@ DEP_CPP_MOD_AUT=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
+ ".\include\fnmatch.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
".\include\http_core.h"\
@@ -1502,7 +1336,9 @@ DEP_CPP_MOD_AUT=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
+ ".\include\fnmatch.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
".\include\http_core.h"\
@@ -1515,14 +1351,6 @@ DEP_CPP_MOD_AUT=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_AUT=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_autoindex.obj" "$(INTDIR)\mod_autoindex.sbr" : $(SOURCE)\
@@ -1541,6 +1369,7 @@ DEP_CPP_MOD_C=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_conf_globals.h"\
@@ -1568,6 +1397,7 @@ DEP_CPP_MOD_C=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_conf_globals.h"\
@@ -1582,14 +1412,6 @@ DEP_CPP_MOD_C=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_C=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_cgi.obj" "$(INTDIR)\mod_cgi.sbr" : $(SOURCE) $(DEP_CPP_MOD_C)\
@@ -1608,6 +1430,7 @@ DEP_CPP_MOD_D=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1634,6 +1457,7 @@ DEP_CPP_MOD_D=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1647,14 +1471,6 @@ DEP_CPP_MOD_D=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_D=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_dir.obj" "$(INTDIR)\mod_dir.sbr" : $(SOURCE) $(DEP_CPP_MOD_D)\
@@ -1673,6 +1489,7 @@ DEP_CPP_MOD_E=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1693,6 +1510,7 @@ DEP_CPP_MOD_E=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1700,14 +1518,6 @@ DEP_CPP_MOD_E=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_E=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_env.obj" "$(INTDIR)\mod_env.sbr" : $(SOURCE) $(DEP_CPP_MOD_E)\
@@ -1726,6 +1536,7 @@ DEP_CPP_MOD_I=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1752,6 +1563,7 @@ DEP_CPP_MOD_I=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1765,14 +1577,6 @@ DEP_CPP_MOD_I=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_I=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_imap.obj" "$(INTDIR)\mod_imap.sbr" : $(SOURCE) $(DEP_CPP_MOD_I)\
@@ -1791,6 +1595,7 @@ DEP_CPP_MOD_IN=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1817,6 +1622,7 @@ DEP_CPP_MOD_IN=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1830,16 +1636,6 @@ DEP_CPP_MOD_IN=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_IN=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
- ".\modules\standard\config.h"\
- ".\modules\standard\modules\perl\mod_perl.h"\
"$(INTDIR)\mod_include.obj" "$(INTDIR)\mod_include.sbr" : $(SOURCE)\
@@ -1858,6 +1654,7 @@ DEP_CPP_MOD_IS=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1883,6 +1680,7 @@ DEP_CPP_MOD_IS=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1895,13 +1693,6 @@ DEP_CPP_MOD_IS=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_IS=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_isapi.obj" "$(INTDIR)\mod_isapi.sbr" : $(SOURCE)\
@@ -1920,6 +1711,7 @@ DEP_CPP_MOD_L=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1942,6 +1734,7 @@ DEP_CPP_MOD_L=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1951,14 +1744,6 @@ DEP_CPP_MOD_L=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_L=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_log_config.obj" "$(INTDIR)\mod_log_config.sbr" : $(SOURCE)\
@@ -1977,6 +1762,7 @@ DEP_CPP_MOD_M=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -1998,6 +1784,7 @@ DEP_CPP_MOD_M=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -2006,14 +1793,6 @@ DEP_CPP_MOD_M=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_M=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_mime.obj" "$(INTDIR)\mod_mime.sbr" : $(SOURCE) $(DEP_CPP_MOD_M)\
@@ -2032,11 +1811,13 @@ DEP_CPP_MOD_N=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.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\util_script.h"\
@@ -2056,25 +1837,19 @@ DEP_CPP_MOD_N=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.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\util_script.h"\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_N=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_negotiation.obj" "$(INTDIR)\mod_negotiation.sbr" : $(SOURCE)\
@@ -2093,6 +1868,7 @@ DEP_CPP_MOD_S=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -2115,6 +1891,7 @@ DEP_CPP_MOD_S=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -2124,14 +1901,6 @@ DEP_CPP_MOD_S=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_S=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_setenvif.obj" "$(INTDIR)\mod_setenvif.sbr" : $(SOURCE)\
@@ -2150,6 +1919,7 @@ DEP_CPP_MOD_SO=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -2171,6 +1941,7 @@ DEP_CPP_MOD_SO=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -2179,14 +1950,6 @@ DEP_CPP_MOD_SO=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_SO=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_so.obj" "$(INTDIR)\mod_so.sbr" : $(SOURCE) $(DEP_CPP_MOD_SO)\
@@ -2205,6 +1968,7 @@ DEP_CPP_MOD_U=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -2225,6 +1989,7 @@ DEP_CPP_MOD_U=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -2232,14 +1997,6 @@ DEP_CPP_MOD_U=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MOD_U=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\mod_userdir.obj" "$(INTDIR)\mod_userdir.sbr" : $(SOURCE)\
@@ -2258,6 +2015,7 @@ DEP_CPP_MODUL=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -2278,6 +2036,7 @@ DEP_CPP_MODUL=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_config.h"\
@@ -2285,13 +2044,6 @@ DEP_CPP_MODUL=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MODUL=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\sfio.h"\
"$(INTDIR)\modules.obj" "$(INTDIR)\modules.sbr" : $(SOURCE) $(DEP_CPP_MODUL)\
@@ -2308,6 +2060,7 @@ SOURCE=.\os\win32\multithread.c
DEP_CPP_MULTI=\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\hsregex.h"\
".\include\multithread.h"\
".\os\win32\os.h"\
@@ -2322,14 +2075,10 @@ DEP_CPP_MULTI=\
DEP_CPP_MULTI=\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\hsregex.h"\
".\include\multithread.h"\
".\os\win32\os.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_MULTI=\
- ".\include\ap_config_auto.h"\
"$(INTDIR)\multithread.obj" "$(INTDIR)\multithread.sbr" : $(SOURCE)\
@@ -2370,6 +2119,7 @@ DEP_CPP_REGIS=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_log.h"\
@@ -2390,6 +2140,7 @@ DEP_CPP_REGIS=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_log.h"\
@@ -2397,13 +2148,6 @@ DEP_CPP_REGIS=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_REGIS=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\sfio.h"\
"$(INTDIR)\registry.obj" "$(INTDIR)\registry.sbr" : $(SOURCE) $(DEP_CPP_REGIS)\
@@ -2422,6 +2166,7 @@ DEP_CPP_RFC14=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_log.h"\
@@ -2444,6 +2189,7 @@ DEP_CPP_RFC14=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_log.h"\
@@ -2453,14 +2199,6 @@ DEP_CPP_RFC14=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_RFC14=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\rfc1413.obj" "$(INTDIR)\rfc1413.sbr" : $(SOURCE) $(DEP_CPP_RFC14)\
@@ -2479,6 +2217,7 @@ DEP_CPP_SERVI=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_conf_globals.h"\
@@ -2504,6 +2243,7 @@ DEP_CPP_SERVI=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_conf_globals.h"\
@@ -2516,13 +2256,6 @@ DEP_CPP_SERVI=\
".\os\win32\readdir.h"\
".\os\win32\registry.h"\
".\os\win32\service.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_SERVI=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\sfio.h"\
"$(INTDIR)\service.obj" "$(INTDIR)\service.sbr" : $(SOURCE) $(DEP_CPP_SERVI)\
@@ -2541,6 +2274,7 @@ DEP_CPP_UTIL_=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_conf_globals.h"\
@@ -2563,6 +2297,7 @@ DEP_CPP_UTIL_=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_conf_globals.h"\
@@ -2572,14 +2307,6 @@ DEP_CPP_UTIL_=\
".\main\test_char.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_UTIL_=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\util.obj" "$(INTDIR)\util.sbr" : $(SOURCE) $(DEP_CPP_UTIL_)\
@@ -2590,36 +2317,24 @@ NODEP_CPP_UTIL_=\
!ENDIF
SOURCE=.\main\util_date.c
-
-!IF "$(CFG)" == "ApacheCore - Win32 Release"
-
DEP_CPP_UTIL_D=\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\hsregex.h"\
".\include\util_date.h"\
".\os\win32\os.h"\
+!IF "$(CFG)" == "ApacheCore - Win32 Release"
+
+
"$(INTDIR)\util_date.obj" : $(SOURCE) $(DEP_CPP_UTIL_D) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug"
-DEP_CPP_UTIL_D=\
- ".\include\ap_config.h"\
- ".\include\ap_ctype.h"\
- ".\include\hsregex.h"\
- ".\include\util_date.h"\
- ".\os\win32\os.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_UTIL_D=\
- ".\include\ap_config_auto.h"\
- ".\include\os.h"\
-
"$(INTDIR)\util_date.obj" "$(INTDIR)\util_date.sbr" : $(SOURCE)\
$(DEP_CPP_UTIL_D) "$(INTDIR)"
@@ -2638,6 +2353,7 @@ DEP_CPP_UTIL_M=\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
".\include\ap_md5.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\httpd.h"\
@@ -2659,6 +2375,7 @@ DEP_CPP_UTIL_M=\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
".\include\ap_md5.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\httpd.h"\
@@ -2666,14 +2383,6 @@ DEP_CPP_UTIL_M=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_UTIL_M=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\util_md5.obj" "$(INTDIR)\util_md5.sbr" : $(SOURCE) $(DEP_CPP_UTIL_M)\
@@ -2692,6 +2401,7 @@ DEP_CPP_UTIL_S=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_conf_globals.h"\
@@ -2720,6 +2430,7 @@ DEP_CPP_UTIL_S=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_conf_globals.h"\
@@ -2735,14 +2446,6 @@ DEP_CPP_UTIL_S=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_UTIL_S=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\util_script.obj" "$(INTDIR)\util_script.sbr" : $(SOURCE)\
@@ -2761,6 +2464,7 @@ DEP_CPP_UTIL_U=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_conf_globals.h"\
@@ -2783,6 +2487,7 @@ DEP_CPP_UTIL_U=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_conf_globals.h"\
@@ -2792,14 +2497,6 @@ DEP_CPP_UTIL_U=\
".\main\uri_delims.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_UTIL_U=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\os.h"\
- ".\include\sfio.h"\
"$(INTDIR)\util_uri.obj" "$(INTDIR)\util_uri.sbr" : $(SOURCE) $(DEP_CPP_UTIL_U)\
@@ -2818,6 +2515,7 @@ DEP_CPP_UTIL_W=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_log.h"\
@@ -2838,6 +2536,7 @@ DEP_CPP_UTIL_W=\
".\include\ap.h"\
".\include\ap_config.h"\
".\include\ap_ctype.h"\
+ ".\include\ap_mmn.h"\
".\include\buff.h"\
".\include\hsregex.h"\
".\include\http_log.h"\
@@ -2845,13 +2544,6 @@ DEP_CPP_UTIL_W=\
".\include\util_uri.h"\
".\os\win32\os.h"\
".\os\win32\readdir.h"\
- {$(INCLUDE)}"sys\stat.h"\
- {$(INCLUDE)}"sys\types.h"\
-
-NODEP_CPP_UTIL_W=\
- ".\include\ap_config_auto.h"\
- ".\include\ebcdic.h"\
- ".\include\sfio.h"\
"$(INTDIR)\util_win32.obj" "$(INTDIR)\util_win32.sbr" : $(SOURCE)\
diff --git a/usr.sbin/httpd/src/ApacheCoreOS2.def b/usr.sbin/httpd/src/ApacheCoreOS2.def
new file mode 100644
index 00000000000..5476d091dc9
--- /dev/null
+++ b/usr.sbin/httpd/src/ApacheCoreOS2.def
@@ -0,0 +1,366 @@
+; ApacheCoreOS2.def :
+
+LIBRARY libhttpd INITINSTANCE
+DESCRIPTION 'Apache Web Server'
+
+EXPORTS
+ ; Add new API calls to the end of this list.
+ ap_MD5Final @1
+ ap_MD5Init @2
+ ap_MD5Update @3
+; ap_acquire_mutex @4
+ ap_add_cgi_vars @5
+ ap_add_common_vars @6
+ ap_add_loaded_module @7
+ ap_add_module @8
+ ap_add_named_module @9
+ ap_add_per_dir_conf @10
+ ap_add_per_url_conf @11
+ ap_add_version_component @12
+ ap_allow_options @13
+ ap_allow_overrides @14
+ ap_append_arrays @15
+ ap_array_cat @16
+ ap_auth_name @17
+ ap_auth_type @18
+ ap_basic_http_header @19
+ ap_bclose @20
+ ap_bcreate @21
+ ap_bfilbuf @22
+ ap_bfileno @23
+ ap_bflsbuf @24
+ ap_bflush @25
+ ap_bgetopt @26
+ ap_bgets @27
+ ap_bhalfduplex @28
+ ap_block_alarms @29
+ ap_blookc @30
+ ap_bnonblock @31
+ ap_bonerror @32
+ ap_bpushfd @33
+; ap_bpushh @34
+ ap_bputs @35
+ ap_bread @36
+ ap_bsetflag @37
+ ap_bsetopt @38
+ ap_bskiplf @39
+ ap_bspawn_child @40
+ ap_bwrite @41
+ ap_bytes_in_free_blocks @42
+ ap_bytes_in_pool @43
+ ap_call_exec @44
+ ap_can_exec @45
+ ap_cfg_closefile @46
+ ap_cfg_getc @47
+ ap_cfg_getline @48
+ ap_chdir_file @49
+; ap_check_alarm @50
+ ap_check_cmd_context @51
+ ap_checkmask @52
+ ap_cleanup_for_exec @53
+ ap_clear_module_list @54
+ ap_clear_pool @55
+ ap_clear_table @56
+ ap_close_piped_log @57
+ ap_construct_server @58
+ ap_construct_url @59
+ ap_content_type_tolower @60
+ ap_copy_array @61
+ ap_copy_array_hdr @62
+ ap_copy_table @63
+ ap_count_dirs @64
+ ap_cpystrn @65
+ ap_create_environment @66
+; ap_create_mutex @67
+ ap_create_per_dir_config @68
+ ap_custom_response @69
+ ap_default_port_for_request @70
+ ap_default_port_for_scheme @71
+ ap_default_type @72
+; ap_destroy_mutex @73
+ ap_destroy_pool @74
+ ap_destroy_sub_req @75
+ ap_die @76
+ ap_discard_request_body @77
+ ap_document_root @78
+ ap_each_byterange @79
+ ap_error_log2stderr @80
+ ap_escape_html @81
+ ap_escape_path_segment @82
+ ap_escape_quotes @83
+ ap_escape_shell_cmd @84
+ ap_exists_scoreboard_image @85
+ ap_finalize_request_protocol @86
+ ap_find_command @87
+ ap_find_command_in_modules @88
+ ap_find_last_token @89
+ ap_find_linked_module @90
+ ap_find_module_name @91
+ ap_find_path_info @92
+ ap_find_token @93
+ ap_get_basic_auth_pw @94
+ ap_get_client_block @95
+ ap_get_gmtoff @96
+ ap_get_limit_req_body @97
+ ap_get_remote_host @98
+ ap_get_remote_logname @99
+ ap_get_server_built @100
+ ap_get_server_name @101
+ ap_get_server_port @102
+ ap_get_server_version @103
+ ap_get_time @104
+ ap_get_token @105
+ ap_getparents @106
+ ap_getword @107
+ ap_getword_conf @108
+ ap_getword_conf_nc @109
+ ap_getword_nc @110
+ ap_getword_nulls @111
+ ap_getword_nulls_nc @112
+ ap_getword_white @113
+ ap_getword_white_nc @114
+ ap_gm_timestr_822 @115
+ ap_gname2id @116
+ ap_handle_command @117
+ ap_hard_timeout @118
+ ap_ht_time @119
+ ap_ind @120
+ ap_index_of_response @121
+ ap_init_virtual_host @122
+ ap_internal_redirect @123
+ ap_internal_redirect_handler @124
+ ap_is_directory @125
+ ap_is_fnmatch @126
+ ap_is_initial_req @127
+ ap_is_matchexp @128
+ ap_is_url @129
+ ap_kill_cleanup @130
+ ap_kill_cleanups_for_fd @131
+ ap_kill_cleanups_for_socket @132
+ ap_kill_timeout @133
+ ap_log_assert @134
+ ap_log_error_old @135
+ ap_log_reason @136
+ ap_log_unixerr @137
+ ap_make_array @138
+ ap_make_dirstr @139
+ ap_make_dirstr_parent @140
+ ap_make_dirstr_prefix @141
+ ap_make_full_path @142
+ ap_make_sub_pool @143
+ ap_make_table @144
+ ap_matches_request_vhost @145
+ ap_md5 @146
+ ap_md5_binary @147
+ ap_md5contextTo64 @148
+ ap_md5digest @149
+ ap_meets_conditions @150
+ ap_no2slash @151
+ ap_note_auth_failure @152
+ ap_note_basic_auth_failure @153
+ ap_note_cleanups_for_fd @154
+ ap_note_cleanups_for_file @155
+; ap_note_cleanups_for_h @156
+ ap_note_cleanups_for_socket @157
+ ap_note_digest_auth_failure @158
+ ap_note_subprocess @159
+; ap_open_mutex @160
+ ap_open_piped_log @161
+ ap_os_canonical_filename @162
+ ap_os_escape_path @163
+ ap_overlap_tables @164
+ ap_overlay_tables @165
+ ap_palloc @166
+ ap_parseHTTPdate @167
+ ap_parse_hostinfo_components @168
+ ap_parse_uri @169
+ ap_parse_uri_components @170
+ ap_pcalloc @171
+ ap_pcfg_open_custom @172
+ ap_pcfg_openfile @173
+ ap_pclosedir @174
+ ap_pclosef @175
+; ap_pcloseh @176
+ ap_pclosesocket @177
+ ap_pduphostent @178
+ ap_pfclose @179
+ ap_pfdopen @180
+ ap_pfopen @181
+ ap_pgethostbyname @182
+ ap_popendir @183
+ ap_popenf @184
+ ap_pregcomp @185
+ ap_pregfree @186
+ ap_pregsub @187
+ ap_psignature @188
+ ap_psocket @189
+ ap_pstrdup @190
+ ap_pstrndup @191
+ ap_push_array @192
+ ap_pvsprintf @193
+ ap_rationalize_mtime @194
+ ap_register_cleanup @195
+; ap_release_mutex @196
+ ap_remove_loaded_module @197
+ ap_remove_module @198
+ ap_requires @199
+ ap_reset_timeout @200
+ ap_rflush @201
+ ap_rind @202
+ ap_rputc @203
+ ap_rputs @204
+ ap_run_cleanup @205
+ ap_run_sub_req @206
+ ap_rwrite @207
+ ap_satisfies @208
+ ap_scan_script_header_err @209
+ ap_scan_script_header_err_buff @210
+ ap_scan_script_header_err_core @211
+ ap_send_fb @212
+ ap_send_fb_length @213
+ ap_send_fd @214
+ ap_send_fd_length @215
+ ap_send_http_header @216
+ ap_send_http_trace @217
+ ap_send_mmap @218
+ ap_send_size @219
+ ap_server_root_relative @220
+ ap_set_byterange @221
+ ap_set_content_length @222
+ ap_set_etag @223
+ ap_set_keepalive @224
+ ap_set_last_modified @225
+ ap_setup_client_block @226
+ ap_should_client_block @227
+ ap_soft_timeout @228
+ ap_some_auth_required @229
+ ap_spawn_child @230
+ ap_srm_command_loop @231
+ ap_str_tolower @232
+ ap_strcasecmp_match @233
+ ap_strcmp_match @234
+ ap_sub_req_lookup_file @235
+ ap_sub_req_lookup_uri @236
+ ap_sync_scoreboard_image @237
+ ap_table_add @238
+ ap_table_addn @239
+ ap_table_get @240
+ ap_table_merge @241
+ ap_table_mergen @242
+ ap_table_set @243
+ ap_table_setn @244
+ ap_table_unset @245
+ ap_tm2sec @246
+ ap_uname2id @247
+ ap_unblock_alarms @248
+ ap_unescape_url @249
+ ap_unparse_uri_components @250
+ ap_update_mtime @251
+ ap_uudecode @252
+ ap_uuencode @253
+ ap_vbprintf @254
+ ap_vformatter @255
+ ap_vsnprintf @256
+; closedir @257
+; opendir @258
+; os_spawnv @259
+; os_spawnve @260
+; os_stat @261
+; readdir @262
+ regcomp @263
+ regexec @264
+ regfree @265
+; access_module @266
+; alias_module @267
+ ap_bprintf @268
+ ap_bvputs @269
+ ap_day_snames @270
+ ap_extended_status @271
+ ap_limit_section @272
+ ap_loaded_modules @273
+ ap_log_error @274
+ ap_log_printf @275
+ ap_log_rerror @276
+ ap_month_snames @277
+ ap_null_cleanup @278
+ ap_psprintf @279
+ ap_pstrcat @280
+ ap_restart_time @281
+ ap_rprintf @282
+ ap_rvputs @283
+ ap_scoreboard_image @284
+ ap_send_header_field @285
+ ap_server_argv0 @286
+ ap_server_root @287
+ ap_set_file_slot @288
+ ap_set_flag_slot @289
+ ap_set_string_slot @290
+ ap_set_string_slot_lower @291
+ ap_snprintf @292
+ ap_suexec_enabled @293
+ ap_table_do @294
+ ap_main @295
+; asis_module @296
+; auth_module @297
+; autoindex_module @298
+; cgi_module @299
+; config_log_module @300
+ core_module @301
+; dir_module @302
+; env_module @303
+; imap_module @304
+; includes_module @305
+; mime_module @306
+; negotiation_module @307
+; os_spawnle @308
+; setenvif_module @309
+ so_module @310
+ top_module @311
+ ap_fnmatch @312
+ ap_method_number_of @313
+ ap_exists_config_define @314
+ ap_single_module_configure @315
+ ap_make_etag @317
+ ap_array_pstrcat @318
+; ap_os_is_filename_valid @319
+ ap_find_list_item @320
+ ap_MD5Encode @321
+ ap_validate_password @322
+ ap_size_list_item @323
+ ap_get_list_item @324
+ ap_scoreboard_fname @325
+ ap_pid_fname @326
+ ap_excess_requests_per_child @327
+ ap_threads_per_child @328
+ ap_max_requests_per_child @329
+ ap_daemons_to_start @330
+ ap_daemons_min_free @331
+ ap_daemons_max_free @332
+ ap_daemons_limit @333
+ ap_user_name @334
+ ap_user_id @335
+ ap_group_id @336
+ ap_standalone @337
+ ap_server_confname @338
+ ap_sub_req_method_uri @339
+ strcasecmp @340
+ strncasecmp @341
+ ap_my_generation @342
+ ap_dummy_mutex @343
+ ap_signal @344
+ ap_regerror @345
+ ap_regexec @346
+ ap_field_noparam @347
+ ap_pbase64decode @348
+ ap_pbase64encode @349
+ ap_base64encode @350
+ ap_base64encode_binary @351
+ ap_base64encode_len @352
+ ap_base64decode @353
+ ap_base64decode_binary @354
+ ap_base64decode_len @355
+ ap_SHA1Init @356
+ ap_SHA1Update_binary @357
+ ap_SHA1Update @358
+ ap_SHA1Final @359
+ ap_sha1_base64 @360
diff --git a/usr.sbin/httpd/src/CHANGES b/usr.sbin/httpd/src/CHANGES
index 41833f59eac..1c95e220c5a 100644
--- a/usr.sbin/httpd/src/CHANGES
+++ b/usr.sbin/httpd/src/CHANGES
@@ -1,3 +1,877 @@
+Changes with Apache 1.3.9
+
+ *) Remove bogus error message when a redirect doesn't set Location.
+ Instead, use an empty string to avoid coredump if the error message
+ was supposed to include a location. [Roy Fielding]
+
+ *) Don't allow configure to include mod_auth_digest unless it is
+ explicitly requested, even if the user asked for all modules.
+ [Roy Fielding]
+
+ *) Translate module names to dll names for OS/2 so that they are no more
+ than 8 characters long and have an extension of "dll" instead of "so".
+ [Brian Havard]
+
+ *) Print out pointer to Rule DEV_RANDOM when truerand lib not found.
+ Fix test-compile check to check for randbyte instead of trand32.
+ Use ap_base64encode_binary/decode instead of copy in mod_auth_digest.c
+ and tweak to make Amaya happier. [Ronald Tschalär]
+
+ *) Ensure that the installed expat include files are world readable,
+ just like the other header files. [Martin Kraemer]
+
+ *) Fixed generated AddModule adjustments in APACI's `configure' script
+ in order to allow (new) modules like mod_vhost_alias to be handled
+ correctly (which was touched by the adjustments for mod_alias).
+ [Ralf S. Engelschall]
+
+ *) For binary builds, add -R flag to apachectl to work around the lack of
+ an absolute path to the ./libexec directory where the libhttp.ep file
+ is needed for SHARED_CORE architectures. [Randy Terbush]
+
+ *) WIN32: Create the CGI script process as DETACHED. This may solve the
+ problem observed by some Win95/98 users where they get CGI script
+ output sent to the console. [Bill Stoddard]
+
+ *) Fix (re)naming in the uuencode/decode section. The ap/ap_
+ routines are now called ap_base64* and are 'plain' (i.e., no
+ pool access or anything clever). Inside util.c the routines acting
+ like pstrdup are called ap_pbase64encode() and ap_pbase64decode().
+ The oddly named ap_uuencode(), ap_uudecode() are kept around for
+ now but deprecated. [dirkx]
+
+ *) Clean up the base64 and SHA1 additions and make sure they are
+ represented in the ApacheCore.def, ApacheCoreOS2.def, and httpd.exp
+ files. [Roy Fielding]
+
+ *) WIN32: Migrate to InstallShield 5.5 and provide a bit more error
+ checking. Allow compiling on VS 6.0. [Randy Terbush]
+
+ *) Fixed assumption of absolute paths in binbuild.sh. [Tony Finch]
+
+ *) Use TestCompile to search for the truerand library (rather than blindly
+ assuming its existence). If it is not found, complain (but do not
+ exit - yet). [Martin Kraemer]
+
+ *) We forgot to add the new exported function names to
+ src/support/httpd.exp. [Bill Stoddard, Randy Terbush]
+
+ *) Add description of -T command-line option to usage().
+ [Ralf S. Engelschall]
+
+ *) For "some" platforms (notably, EBCDIC based ones), libos needs to be
+ searched only AFTER libap has been searched, because libap needs
+ some symbols from libos. [Martin Kraemer]
+
+ *) Fix conflict with original mod_digest related to the symbol of the
+ module dispatch list (which has to be unique for DSO and follow the
+ usual conventions for the installation procedure).
+ [Ralf S. Engelschall]
+
+ *) Add a dbm-library check for the "usual places" (-ldbm, -lndbm, -ldb)
+ for other platforms as well. [Martin Kraemer]
+
+ *) Make ap_sha1.c compile for EBCDIC platforms: replace remaining LONG
+ types by AP_LONG and replace reference to renamed variable 'ubuf'
+ by 'buffer'. [Martin Kraemer]
+
+Changes with Apache 1.3.8 [not released]
+
+ *) Flush the output buffer immediately after sending an error or redirect
+ response, since the result may be needed by the client to abort a
+ long data transfer or restart a series of pipelined requests.
+ [Tom Vaughan <tvaughan@aventail.com>, Roy Fielding]
+
+ *) PORT: Improved compilation and DSO support on Sequent DYNIX/ptx.
+ [Ian Turner <iant@sequent.com>] PR#4735
+
+ *) Local struct mmap in http_core.c conflicted with system structure
+ name on DYNIX -- changed to mmap_rec. [Roy Fielding] PR#4735
+
+ *) Added updated mod_digest as modules/experimental/mod_auth_digest.
+ [Ronald Tschalär <ronald@innovation.ch>]
+
+ *) Fix a memory leak where the module counts were getting messed
+ up across restarts. [David Harris <dharris@drh.net>]
+
+ *) CIDR addresses such as a.b.c.d/24 where d != 0 weren't handled
+ properly in mod_access.
+ ["Paul J. Reder" <rederpj@raleigh.ibm.com>] PR#4770
+
+ *) RewriteLock/RewriteMap didn't work properly with virtual hosts.
+ [Dmitry Khrustalev <dima@bog.msu.su>] PR#3874
+
+ *) PORT: Support for compaq/tandem/com.
+ [Michael Ottati <michael.ottati@compaq.com>, dirkx]
+
+ *) Added SHA1 password encryption support to easy migration from
+ Netscape servers. See support/SHA1 for more information.
+ Caused the separation of ap_md5.c into md5, sha1 and a general
+ ap_checkpass.c with just a validate_passwd routine. Added a
+ couple of flags to support/htpasswd. Some reuse of the to64()
+ function; hence renamed to ap_to64().
+ [Dirk-Willem van Gulik, Clinton Wong <clintdw@netcom.com>]
+
+ *) Change for EBCDIC platforms (TPF and BS2000) to correctly deal
+ with ASCII/EBCDIC conversions in "ident" query.
+ [David McCreedy <McCreedy@us.ibm.com>]
+
+ *) Get rid of redefinition warning on MAC_OS_X_SERVER platform.
+ Change "Power Macintosh" to Power* so if uname prints "Power Book"
+ we're still happy on Rhapsody platforms. [Wilfredo Sanchez]
+
+ *) Fix SIGSEGV on some systems because the Vary fix below included
+ a call to table_do with a variable argument list that was not
+ NULL terminated. Replaced with better implementation. [Roy Fielding]
+
+Changes with Apache 1.3.7 [not released]
+
+ *) The "Vary" response header field is now sanitised right before
+ the header is sent back to the client. Multiple "Vary" fields
+ are combined, and duplicate tokens (e.g., "Vary: host, host" or
+ "Vary: host, negotiate, host, accept-language") are reduced to
+ single instances. This is a better solution than the force-no-vary
+ one (which is still valid for clients that can't cope with Vary
+ at all). PR#3118 [Dean Gaudet, Roy Fielding, Ken Coar]
+
+ *) Portability changes for BeOS. [David Reid abb37@dial.pipex.com]
+
+ *) Link DSO's with "gcc -shared" instead of "ld -Bshareable" at
+ least on Linux and FreeBSD for now.
+ [Rasmus Lerdorf]
+
+ *) Win32: More apache -k restart work. Restarts are now honored
+ immediately and connections in the listen queue are -not- lost.
+ This is made possible by the use of the WSADuplicateSocket()
+ call. The listeners are opened in the parent, duplicated, then
+ the duplicates are passed to the child. The original listen sockets
+ are not closed by the parent across a restart, thus the listen queue
+ is preserved.
+ [Bill Stoddard <stoddard@raleigh.ibm.com>]
+
+ *) Fix handling of case when a client has sent "Expect: 100-continue"
+ and we are going to respond with an error, but get stuck waiting to
+ discard the body in the pointless hope of preserving the connection.
+ [Roy Fielding, Joe Orton <jeo101@york.ac.uk>] PR#4499, PR#3806
+
+ *) Fix 'configure' to work correctly with SysV-based versions of
+ 'tr' (consistent with Configure's use as well). [Jim Jagielski]
+
+ *) apxs: Add "-S var=val" option which allows for override of CFG_*
+ built-in values. Add "-e" option which works like -i but doesn't
+ install the DSO; useful for editing httpd.conf with apxs. Fix
+ editing code so that multiple invocations of apxs -a will not
+ create duplicate LoadModule/AddModule entries; apxs can now be
+ used to re- enable/disable a module. [Wilfredo Sanchez]
+
+ *) Win32: Update the server to use Winsock 2. Specifically, link with
+ ws2_32.lib rather than wsock32.lib. This gives us access to
+ WSADuplcateSocket() in addition to some other enhanced comm APIs.
+ Win 95 users may need to update their TCP/IP stack to pick up
+ Winsock 2. (See http://www.microsoft.com/windows95/downloads/)
+ [Bill Stoddard stoddard@raleigh.ibm.com]
+
+ *) Win32: Redirect CGI script stderr (script debug info) into the
+ error.log when CGI scripts fail. This makes Apache on Win32
+ behave more like Unix.
+ [Bill Stoddard stoddard@raleigh.ibm.com]
+
+ *) Fixed `httpd' usage display: -D was missing.
+ [Ralf S. Engelschall] PR#4614
+
+ *) Fix `make r' test procedure in src/regex/: ap_isprint was not found.
+ [Ralf S. Engelschall] PR#4561, PR#4562
+
+ *) OS/2: Fix problem with accept lock semaphores where server would die with
+ "OS2SEM: Error 105 getting accept lock. Exiting!"
+ [Brian Havard] PR#4505
+
+ *) Add DSO support for DGUX 4.x using gcc. Tested on x86 platforms.
+ [Randy Terbush <randy@covalent.net>]
+
+ *) Add the new mass-vhost module (mod_vhost_alias.c) developed and
+ used by Demon Internet, Ltd. [Tony Finch <fanf@demon.net>]
+
+ *) Better GCC detection for DSO flags under Solaris 2 where the `cc'
+ command potentially _is_ GCC. [Ralf S. Engelschall]
+
+ *) Fix apxs build issues on AIX
+ [Rasmus Lerdorf <rasmus@raleigh.ibm.com>]
+
+ *) DocumentRoot Checking: Under previous versions, when Apache
+ first started up, it used to do a stat of each DocumentRoot to
+ see if it existed and was a directory. If not, then an error
+ message was printed. THIS HAS BEEN DISABLED. If DocumentRoot
+ does not exist, you will get error messages in error_log. If
+ the '-t' command line option is used (to check the configuration)
+ the check of DocumentRoot IS performed. An additional command
+ line option, '-T', has been added if you want to avoid the
+ DocumentRoot check even when checking the configuration.
+ [Jim Jagielski]
+
+ *) Win32: The query switch "apache -S" didn't exit after showing the
+ vhost settings. That was inconsistent with the other query functions.
+ [Bill Stoddard - Fixed by Martin on Unix in 1.3.4]
+
+ *) Win32: Changed behaviour of apache -k restart.
+ Previously, the server would drain all connections in the stack's
+ listen queue before honoring the restart. On a busy server, this
+ could take hours. Now, a restart is honored almost immediately.
+ All connections in Apache's queues are handled but connections in
+ the stack's listen queue are discarded. Restart triggered by
+ MaxRequestPerChild is unchanged.
+ [Bill Stoddard <stoddard@raleigh.ibm.com>]
+
+ *) Win32: Eliminated unnecessary call to wait_for_multiple_objects in
+ the accept loop. Good for a 5% performance boost. Cleaned up
+ parent/child process management code.
+ [Bill Stoddard <stoddard@raleigh.ibm.com>]
+
+ *) Added ceiling on file size for memory mapped files.
+ [John Giannandrea <jg@meer.net>] PR#4122
+
+ *) Fix ndbm.h include problems with brain-dead glibc >= 2.1 which
+ has ndbm.h in a non-standard db1/ subdir. PR#4431, PR#4528
+ [Henri Gomez <gomez@slib.fr>, Ralf S. Engelschall]
+
+ *) Determine AP_BYTE_ORDER for ap_config_auto.h and already
+ use this at least for Expat. [Ralf S. Engelschall]
+
+ *) Allow .module files to specify libraries with Lib:.
+ [Ben Laurie]
+
+ *) Allow SetEnvIf[NoCase] to test environment variables as well
+ as header fields and request attributes. [Ken Coar]
+
+ *) Fix mod_autoindex's handling of ScanHTMLTitles when file
+ content-types are "text/html;parameters". PR#4524 [Ken Coar]
+
+ *) Remove "mxb" support from mod_negotiation -- it was a draft feature
+ never accepted into any standard, and it opens up certain DoS
+ attacks. [Koen Holtman <Koen.Holtman@cern.ch>]
+
+ *) TestCompile updated. We can now run programs and output the
+ results during the Configure process. [ Jim Jagielski]
+
+ *) The source is now quad (long long) aware as needed. Specifically,
+ the Configure process determines the correct size of off_t and
+ *void. When the OS/platform/compiler supports quads, ap_snprintf()
+ provides for the 'q' format qualifier (if quads are not available,
+ 'q' is silently "demoted" to long). [Jim Jagielski]
+
+ *) When the username or password fed to htpasswd is too long, include the
+ size limit in the error message. Also report illegal characters
+ (currently only ':') in the username. Add the size restrictions
+ to the man page. [Ken Coar]
+
+ *) Fixed the configure --without-support option so it doesn't result in
+ an infinite loop. [Marc Slemko]
+
+ *) Piped error logs could cause a segfault if an error occured
+ during configuration after a restart.
+ [Aidan Cully <aidan@panix.com>] PR#4456
+
+ *) If a "Location" field was stored in r->err_headers_out rather
+ than r->headers_out, redirect processing wouldn't find it and
+ the server would core dump on ap_escape_html(NULL). Check both
+ tables and raise HTTP_INTERNAL_SERVER_ERROR with a log message
+ if Location isn't set. [Doug MacEachern, Ken Coar]
+
+ *) Add RULE_EXPAT, the src/lib/ directory structure, and a modified copy
+ of the Expat 1.0.2 distribution. [Greg Stein]
+
+ *) Replace regexec() calls with calls to a new API stub function
+ ap_regexec(). This solves problems with DSO modules which use the regex
+ library. [Jens-Uwe Mager <jum@helios.de>, Ralf S. Engelschall]
+
+ *) Add 'Request_Protocol' special keyword to mod_setenvif so that
+ environment variables can be set according to the protocol version
+ (e.g., HTTP/0.9 or HTTP/1.1) of the request. [Ken Coar]
+
+ *) Add DSO support for OpenStep (Mach 4.2) platform.
+ [Ralf S. Engelschall, Rex Dieter <rdieter@math.unl.edu>] PR#3997
+
+ *) Fix sed regex for generating ap_config_auto.h in src/Configure.
+ [Jan Gallo <gallo@pvt.sk>] PR#3690, PR#4373
+
+ *) Switch to /bin/sh5 in APACI on Ultrix and friends to avoid problems with
+ their brain-dead /bin/sh. [Ralf S. Engelschall] PR#4372
+
+ *) Better DSO flags recognition on NetBSD platforms using ELF.
+ [Todd Vierling <tv@pobox.com>] PR#4310
+
+ *) Always log months in english format for %t in mod_log_config.
+ [Petr Lampa <lampa@fee.vutbr.cz>] PR#4366, 679
+
+ *) Support for server-parsed and multiview-determined ReadmeName and
+ HeaderName files in mod_autoindex. Removed the restriction on
+ "/"s in ReadmeName and HeaderName directives since the *sub_req*
+ routines will deal with the access issues. (It's now possible to
+ have {site|group|project|customer|...} wide readmes and headers.)
+ [Raymond S Brand <rsbx@rsbx.net>, Ken Coar] PR#1574, 3026, 3529,
+ 3569, 4256
+
+ *) When stat() fails, don't assume anything about the contents of
+ the struct stat. [Ed Korthof <ed@bitmechanic.com>]
+
+ *) It's OK for a semop to return EINTR, just loop around and try
+ again. [Dean Gaudet]
+
+ *) Fix configuration engine re-entrant hangups, which solve a
+ handful of problems seen with mod_perl <Perl> configuration sections
+ [Salvador Ortiz Garcia <sog@msg.com.mx>]
+
+ *) Mac OS and Mac OS X Server now use the appropriate custom layout
+ by default when building with APACI; allow for platform-specific
+ variable defaults in configure. [Wilfredo Sanchez]
+
+ *) Do setgid() before initgroups() in http_main; some platforms
+ zap the grouplist when setgid() is called. This was fixed in
+ suexec earlier, but the main httpd code missed the change.
+ [Rob Saccoccio <robs@InfiniteTechnology.com>] PR#2579
+
+ *) Add recognition of .tgz as a gzipped tarchive.
+ [Bertrand de Singly <bertrand.de-singly@polytechnique.fr>] PR#2364
+
+ *) mod_include's fsize/flastmod should allow only relative paths, just
+ like "include file". [Jaroslav Benkovsky <benkovsk@pha.pvt.cz>]
+
+ *) OS/2: Add support for building loadable modules using DLLs.
+ [Brian Havard]
+
+ *) Add iconsdir, htdocsdir, and cgidir to config.layout.
+ [Wilfredo Sanchez]
+
+ *) Fix minor but annoying bug with the test for Configuration.tmpl
+ being newer than Configuration so that it is less likely to fail
+ when using APACI and shadow sources. [Wilfredo Sanchez]
+
+ *) PORT: Add initial support for Mac OS (versions 10.0 and
+ greater). Use Mac OS X Server layout for now. Clean up dyld code
+ in unix/os.c, and don't install the dyld error handlers, which
+ are no longer needed in Mac OS. [Wilfredo Sanchez]
+
+ *) Rename Rhapsody layout to "Mac OS X Server". Change install
+ locations to appropriate ones for user-built (as opposed to
+ system) installs. [Wilfredo Sanchez]
+
+ *) Modify mod_autoindex's handling of AddDescription so that the
+ behaviour matches the documentation. [Ken Coar] PR#1898, 3072.
+
+ *) Add functionality to the install-bindist.sh script created by
+ binbuild.sh to use tar when copying distribution files to the
+ serverroot. This allows upgrading an existing installation
+ without nesting the new distribution in the old.
+
+ install-bindist.sh now detects the local perl5 path to install
+ apxs and dbmmanage with proper path to perl interpreter.
+
+ Add an install-binsupport target which copies the source files
+ for apxs and dbmmanage to bindist to allow these scripts to
+ be properly installed relative to the destination serverroot.
+ [Randy Terbush, Covalent Technologies, randy@covalent.net]
+
+ *) Fix intermittent SEGV in ap_proxy_cache_error() in
+ src/modules/proxy_util.c where a NULL filepointer and
+ temporary filename were closed and unlinked.
+ [Graham Leggett <minfrin@sharp.fm>,
+ Tim Costello <tjcostel@socs.uts.edu.au>] PR#3178
+
+ *) Fix inconsistent error messages reported by mod_proxy.
+ [Graham Leggett <minfrin@sharp.fm>]
+
+ *) OS/2: Fix terminating CGIs that aren't compiled by EMX GCC when a
+ connection is aborted. [Brian Havard]
+
+ *) Force the LANG envariable to the known state of "C" so that we
+ have assurance about how string manipulators (e.g., tr) will
+ function. [Ken Coar] PR#1630
+
+ *) Add a directive to allow customising of the tracking cookie name.
+ [Ken Coar] PR#2921, 4303
+
+ *) Add "force-no-vary" envariable to allow servers to work around
+ clients that choke on "Vary" fields in the response header.
+ [Ken Coar, Dmitry Khrustalev <dima@zippy.machaon.ru>] PR#4118
+
+ *) Fixed a bug in mod_dir that causes a child process will infinitely
+ recurse when it attemps to handle a request for a directory wnd the
+ value of the DirectoryIndex directive is a single dot. Also likely
+ to happen for anyother values of DirectoryIndex that will map back
+ to the same directory. The handler now only considers regular files
+ as being index candidates. No PR#s found.
+ [Raymond S Brand <rsbx@rsbx.net>]
+
+ *) Ease configuration debugging by making TestCompile fall back to
+ using "make" if the $MAKE variable is unset [Martin Kraemer]
+
+ *) Fixed the ServerSignature directive to work as documented.
+ [Raymond S Brand <rsbx@rsbx.net>] PR#4248
+
+ *) Add "opt" (SysV-style) layout to config.layout. [Raymond S Brand
+ <rsbx@rsbx.net>]
+
+ *) Add APACI --without-execstrip option which can be used to disable the
+ stripping of executables on installation. This is very important for DSO
+ and debugging situations. [Ralf S. Engelschall]
+
+ *) Add support for OS/2 (case insenstive filesystem, .exe suffix, etc)
+ to APACI files and related scripts.
+ [Yitzchak Scott-Thoennes <sthoenna@efn.org>, Ralf S. Engelschall] PR#4269
+
+ *) Add support for standalone mode in TPF
+ [Joe Moenich <moenich@us.ibm.com>]
+
+ *) Fix number of bytes copied by read_connection() in src/support/ab.c
+ [Jim Cox <jc@superlink.net>] PR#4271
+
+ *) Fix special RewriteCond "-s" pattern matching.
+ [Bob Finch <bob@nas.com>]
+
+ *) Fix value quoting in src/Configure script for ap_config_auto.h
+ [Paul Sutton <paul@awe.com>]
+
+ *) Make sure RewriteLock can be used only in the global context, (i.e.
+ outside of any <VirtualHost> sections) because it's a global facility of
+ the rewrite engine. [Ralf S. Engelschall]
+
+ *) Fix the ownership delegation for proxy directory under `make install'.
+ [Ralf S. Engelschall]
+
+ *) APACI would not correctly build suexec. [Maria Verina
+ <mariav@icgeb.trieste.it>] PR#4260
+
+ *) mod_mime_magic passed only the first 4k of a file to
+ uncompress/gzip, but those tools sometimes do not produce
+ any output unless a sufficient portion of the compressed
+ file is input. Change to pass the entire file -- but
+ only read 4k of output.
+ [Marcin Cieslak <saper@system.pl>] PR#4097
+
+ *) "IndexOptions None" generated extra spaces at the end of each
+ line. [inkling@firstnethou.com] PR#3770
+
+ *) The "100 Continue" response wasn't being sent after internal
+ redirects. [Jose KAHAN <kahan@w3.org>] PR#3910, 3806, 3575
+
+ *) When padding the name with spaces for display, mod_autoindex would
+ count &, <, and > in their escaped width, messing up the display.
+ [Dean Gaudet] PR#4075, 3758
+
+ *) PORT: fixed a compilation problem on NEXT.
+ [Jacques Distler <distler@golem.ph.utexas.edu>] PR#4130
+
+ *) r->request_time wasn't being set properly in certain error conditions.
+ [Dean Gaudet] PR#4156
+
+ *) PORT: deal with UTS compiler error in http_protocol.c
+ [Dave Dykstra <dwd@bell-labs.com>] PR#4189
+
+ *) Add ap_vrprintf() function. [John Tobey <jtobey@banta-im.com>] PR#4246
+
+ *) Fix the mod_mime hash table to work properly with locales other
+ than C. [Dean Gaudet] PR#3427
+
+ *) Fix a memory leak which is exacerbated by certain configurations.
+ [Dean Gaudet] PR#4225
+
+ *) Prevent clobbering saved IFS values in APACI. [Jim Jagielski]
+
+ *) Fix buffer overflows in ap_uuencode and ap_uudecode pointed out
+ by "Peter 'Luna' Altberg <peter@altberg.nu>" and PR#3422
+ [Peter 'Luna' Altberg <peter@altberg.nu>, Ronald Tschalär]
+
+ *) Make {Set,Unset,Pass}Env per-directory instead of per-server.
+ [Ben Laurie]
+
+ *) Correct an apparent typo: on the Windows and MPE platforms, the
+ htpasswd utility was limiting passwords to only 8 characters.
+ [Ken Coar]
+
+ *) EBCDIC platforms: David submitted patches for two bugs in the
+ MD5 digest port for EBCDIC machines:
+ a) the htdigest utility overwrote the old contents of the digest file
+ b) the Content-MD5 header value (ContentDigest directive) was wrong
+ when the returned file was not converted from EBCDIC, but was a
+ binary (e.g., image file) in the first place.
+ [David McCreedy <mccreedy@us.ibm.com>]
+
+ *) support/htpasswd now permits the password to be specified on the
+ command line with the '-b' switch. This is useful when passwords
+ need to be maintained by scripts -- particularly in the Win32
+ environment. [Ken Coar]
+
+ *) Win32: Win32 multiple services patch. Added capability to install and
+ run multiple copies of apache as individual services.
+
+ Example 1:
+ apache -n apache1 -i -f c:/httpd.conf
+ Installs apache as service 'apache1' and associates c:/httpd.conf
+ with that service.
+ net start apache1
+ Starts apache1 service.
+ net stop apache1
+ Stops apache1 service
+
+ Example 2:
+ apache -n apache2 -i
+ Installs apache as service 'apache2'. httpd.conf is located under
+ the default server root (/apache/conf/httpd.conf).
+ net start apache2
+ Starts apache2 service.
+
+ Example 3:
+ apache -n apache3 -i -d c:/program files/apache
+ Install apache as service 'apache3' and sets server root to
+ c:/program files/apache.
+
+ Example 4:
+ apache -n apache2 -k restart
+ Restart apache2 service
+
+ [Keith Wannamaker, Ken Parzygnat, Bill Stoddard]
+
+ *) Correct the signed/unsigned character handling for the MD5 routines;
+ mismatches were causing compilation problems with gcc -pedantic and
+ in the TPF cross-compilation. [Ken Coar]
+
+ *) OS/2: Rework CGI handling to use spawn*() instead of fork/exec, achieving
+ a roughly 5 fold speed up. [Brian Havard]
+
+ *) proxy ftp: instead of using the hardwired string "text/plain" as
+ a fallback type for files served by the ftp proxy, use the
+ ap_default_type() function to determine the configured type.
+ This allows for special configurations like
+ <Directory proxy:ftp://some.host>
+ DefaultType gargle/blurb
+ </Directory>
+ Additionally, add the Content-Encoding: header to FTP proxy replies
+ when the encoding is defined (by the AddEncoding directive).
+ Because it was missing, it was almost impossible to browse compressed
+ files using the FTP proxy (works now perfectly in Communicator).
+ The ftp proxy now also returns the Date: and Server: header lines (if not
+ much else... This code is "somewhat" broken) like normal requests do.
+ [Martin Kraemer]
+
+ *) Be more smart in APACI's configure script when determining the UID/GID
+ for User/Group directives and use the determined UID/GID to initialize
+ the permissions on the proxycachedir.
+ [Dirk-Willem van Gulik, Ralf S. Engelschall]
+
+ *) Changed the forking-prior-to-cleanup in the proxy module to first
+ check wether it actually needs to collect garbage. This reduces
+ the number of fork()s from one/request to just the odd one an hour.
+ [Dirk-Willem van Gulik]
+
+ *) Added proxy, auth and header support to src/support/ab.c. Added a
+ README file to src/support/
+ [Dirk-Willem van Gulik]
+
+ *) Don't hard-code the path to AWK in --shadow bootstrapping Makefile.
+ [Ralf S. Engelschall] PR#4050
+
+ *) Add support for DSO module compilation on BSD/OS 3.x.
+ [Randy Terbush, Covalent Technologies]
+
+ *) Fix sed-substitutions in `make install': path elements like `httpd/conf'
+ (for instance from an APACI configure --sysconfdir=/etc/httpd/conf
+ option) were substituted with $(TARGET).conf, etc. Same for other strings
+ with dots where the dot wasn't matched as plain text.
+ [Ralf S. Engelschall]
+
+ *) PORT: Add support for FreeBSD 4.x [Ralf S. Engelschall]
+
+ *) Fix verbose output of APACI configure (option -v)
+ [Martin Kraemer, Ralf S. Engelschall]
+
+Changes with Apache 1.3.6
+
+ *) Removed new PassAllEnv code due to DSO problems. [Lars Eilebrecht]
+
+Changes with Apache 1.3.5 [not released]
+
+ *) M_INVALID needed a value within the scope of METHODS so that unknown
+ methods can be access controlled. [Roy Fielding] PR#3821
+
+ *) Added PassAllEnv; makes server's entire environment available
+ to CGIs and SSIs executed within directive's scope. [Ken Coar]
+
+ *) ap_uuencode() always added two trailing '='s and encoding of
+ 8 bit characters on a machine with signed char may produced
+ incorrect results. Additionally ap_uuencode() should now
+ work correctly on EBCDIC platforms.
+ [Ronald Tschalär <ronald@innovation.ch>] PR#3411
+
+ *) WIN32: Binary installer now runs the configuration DLL before
+ the reboot prompt (which is only given if MSVCRT.DLL system
+ DLL is new or updated). This should avoid the configuration
+ directory being empty after installation. [Paul Sutton]
+ PR#3767, 3800, 3827, 3850, 3900, 3953, 3988
+
+ *) WIN32: Binary installer now creates Start menu options to start
+ and stop Apache as a console application and to uninstall
+ the Apache service on NT. [Paul Sutton] PR#3741
+
+ *) WIN32: Apache.exe now contains an icon. [Paul Sutton]
+
+ *) PORT: Switch back to using fcntl() locking on Linux -- instabilities
+ have been reported with flock() locking (probably related to kernel
+ version). [Dean Gaudet] PR#2723, 3531
+
+ *) Using APACI, the main config file (usually httpd.conf) was
+ not being adjusted as $(TARGET).conf. [Wilfredo Sanchez
+ <wsanchez@apple.com>]
+
+ *) PORT: AIX does not require the SHARED_CODE "hack"
+ [Ryan Bloom <rbb@raleigh.ibm.com>]
+
+ *) Set-Cookie headers were being doubled up for some CGIs by the O(n^2)
+ avoidance code added in 1.3.3.
+ [Dean Gaudet, Jeff Lewis <lewis@stanford.edu>] PR#3872
+
+ *) ap_isxdigit was somehow neglected when adding the ap_isfoo() macros
+ for 8-bit safeness. [Dean Gaudet]
+
+ *) PORT: Use -fPIC instead of -fpic on Solaris and SunOS for compiling DSOs
+ because SPARCs have a small machine-specific maximum size for the Global
+ Offset Table which is often exceeded when compiling one of the larger
+ third-party modules with Apache. [Peter Urban <Peter.Urban@epfl.ch>] PR#3977
+
+ *) Move the directive `ExtendedStatus' in httpd.conf-dist-win _after_ the
+ DSO/DLL section because it's a directive from mod_status and isn't
+ available before the DLL of mod_status is loaded.
+ [Martin POESCHL <mpoeschl@gmx.net>] PR#3936
+
+ *) SECURITY: Fix a bug in the calculation of the buffer size for the line
+ continuation facility in Apache's configuration files which could
+ lead to a buffer overflow situation.
+ [Thomas Devanneaux <Thomas.Devanneaux@enst.fr>] PR#3617
+
+ *) Make documentation and error messages of APACI's --activate-module=FILE
+ option more clear. [Jan Wolter <janc@wwnet.net>] PR#3995
+
+ *) Fix the gcc version check (for enabling the `inline' facility) to
+ really support all future gcc versions >= 2.7 until we know more.
+ [John Tobey <jtobey@banta-im.com>] PR#3983
+
+ *) Let APACI's configure script correctly complain for unknown --enable-XXX
+ and --disable-XXX options. [Ralf S. Engelschall] PR#3958
+
+ *) Link the shared core bootstrap program (``Rule SHARED_CORE=yes'') also
+ against libap.a and use its ap_snprintf() instead of sprintf() to avoid
+ possible buffer overflows. [Ralf S. Engelschall]
+
+ *) Remove no longer used non-API function ap_single_module_init().
+ [Ralf S. Engelschall]
+
+ *) Add Apple's Mac OS X Server Layout "Rhapsody" to config.layout.
+ [Wilfredo Sanchez]
+
+ *) Add cgidir, htdocsdir, iconsdir variables to Makefile.tmpl in order
+ to make platform installations easier. [Wilfredo Sanchez]
+
+ *) In configure, do not append the target name to the directory path if
+ the path already contains "apache". [Ralf S. Engelschall]
+
+ *) SIGPIPE is now ignored by the server core. The request write routines
+ (ap_rputc, ap_rputs, ap_rvputs, ap_rwrite, ap_rprintf, ap_rflush) now
+ correctly check for output errors and mark the connection as aborted.
+ Replaced many direct (unchecked) calls to ap_b* routines with the
+ analogous ap_r* calls. [Roy Fielding]
+
+ *) Enhanced mod_rewrite's mapfile handling: The in-core cache for text and
+ DBM format mapfiles now uses a 4-way hash table with LRU functionality.
+ Furthermore map lookups for non-existent keys are now cached as well.
+ Additionally "txt" maps are now parsed with simple string functions
+ instead of using ap_pregcomp(). As a side effect a bug that prevented
+ the usage of keys containing the "," character was fixed.
+ The changes drastically improve the performance when large rewrite maps
+ are in use.
+ [Michael van Elst <mlelstv@serpens.swb.de>, Lars Eilebrecht] PR#3160
+
+ *) Added ap_sub_req_method_uri() for doing a subrequest with a method
+ other than GET, and const'd the definition of method in request_rec.
+ [Greg Stein]
+
+ *) Use proper pid_t type for saving PIDs in alloc.c. [John Bley]
+
+ *) Replaced use of WIN32 define with HAVE_DRIVE_LETTERS to indicate
+ when the OS allows a DOS drive letter within pathnames. [Brian Havard]
+
+ *) Add %V to mod_log_config, this logs the hostname according to the
+ UseCanonicalName setting (this is the pre-1.3.4 behaviour of
+ %v). Useful for mass vhosting. [Tony Finch <dot@dotat.at>]
+
+ *) Add support for \n and \t to mod_log_config, can be used to produce
+ more reliable logs with multiline entries. [Tony Finch <dot@dotat.at>]
+
+ *) Fixed a few compiler nits. [John Bley <jbb6@acpub.duke.edu>]
+
+ *) Added informative error messages for failed munmap() and fseek() calls
+ in http_core.c. [John Bley, Roy Fielding]
+
+ *) Added some informative error messages for some failed malloc()
+ calls. [John Bley <jbb6@acpub.duke.edu>, Jim Jagielski]
+
+ *) OS/2 ap_os_canonical_filename()'s behaviour is improved: ap_assert()
+ is removed. This allows <Directory proxy:*> directives to work and
+ prevents invalid requests from killing the process.
+ [Brian Havard <brianh@kheldar.apana.org.au>]
+
+ *) Reorganised FAQ document.
+ [Joshua Slive <slive@finance.commerce.ubc.ca>] PR#2497
+
+ *) src/support/: The ApacheBench benchmark program was overhauled by
+ David N. Welton: you can now have it generate an HTML TABLE, presumably
+ for integration into other HTML sources. David updated the ab man page
+ as well and added some missing descriptions. Thanks!
+ [David N. Welton <davidw@prosa.it>]
+
+ *) Win32: The filename validity checker now allows filenames containing
+ characters in the range 0x80 to 0xff (for example accented characters).
+ [Paul Sutton] PR#3890
+
+ *) Added conditional logging based upon environment variables to
+ mod_log_config. mod_log_referer and mod_log_agent
+ are now deprecated. [Ken Coar]
+
+ *) Allow apache acting as a proxy server to relay the real
+ reason of a failure to a client rather than the "internal
+ server error" it does currently. The general exposure mechanism
+ can be triggered by any module by setting the "verbose-error-to"
+ note to "*"; this allows more than just proxy errors to be exposed.
+ [Cliff Skolnick, Roy Fielding, Martin Kraemer] Related to PR#3455, 4086
+
+ *) Moved man pages for ab and apachectrl to section 8.
+ [Wilfredo Sanchez, Roy Fielding]
+
+ *) Added -S option to install.sh so that options can be passed to
+ strip on some platforms. [Ralf S. Engelschall, Wilfredo Sanchez]
+
+ *) Tweak modules Makefile generated by Configure so that it handles
+ the test case of no modules being selected. [chaz@reliant.com]
+
+ *) Added a <LimitExcept method ...> sectioning directive that allows
+ the user to assign authentication control to any HTTP method that
+ is *not* given in the argument list; i.e., the logical negation
+ of the <Limit> directive. This is particularly useful for controlling
+ access on methods unknown to the Apache core, but perhaps known by
+ some module or CGI script. [Roy Fielding, Tony Finch]
+
+ *) Prevent apachectl from complaining if the PIDFILE exists but
+ does not contain a process id, as might occur if the server is
+ being rapidly restarted. [Wilfredo Sanchez]
+
+ *) Win32: Add global symbols missing from ApacheCore.def. [Carl Olsen]
+
+ *) Entity tag comparisons for If-Match and If-None-Match were not being
+ performed correctly -- weak tags might cause false positives. Also,
+ strong comparison wasn't properly enforced in all cases.
+ [Roy Fielding, Ken Coar, Dean Gaudet] PR#2065, 3657
+
+ *) OS/2: Supply OS/2 error code instead of errno on semaphore errors.
+ [Brian Havard]
+
+ *) Work around a bug in Lynx regarding its sending "Negotiate: trans"
+ even though it doesn't understand TCN. [Koen Holtman, Roy Fielding]
+
+ *) Added ap_size_list_item(), ap_get_list_item(), and ap_find_list_item()
+ to util.c for parsing an HTTP header field value to extract the next
+ list item, taking into account the possible presence of nested comments,
+ quoted-pairs, and quoted-strings. ap_get_list_item() also removes
+ insignificant whitespace and lowercases non-quoted tokens.
+ [Roy Fielding] PR#2065
+
+ *) proxy: The various calls to ap_proxyerror() can return HTTP/1.1 status
+ code different from 500. This allows the proxy to, e.g., return
+ "403 Forbidden" for ProxyBlock'ed URL's. [Martin Kraemer] Related to PR#3455
+
+ *) Fix ordering of language variants for the case where the traditional
+ negotiation algorithm is being used with multiple language variants
+ and no Accept-Language. [James Treacy <treacy@debian.org>] PR#3299, 3688
+
+ *) Do not round the TCN quality calculation to 5 decimal places,
+ unlike RFC 2296, because the calculation might need 12 decimal places
+ to get the right result. [Roy Fielding]
+
+ *) Remove unused code to disable transparent negotiation when
+ negotiating on encoding only, as we now handle encoding too
+ (though this is nonstandard for TCN), remove charset=ISO-8859-1
+ fiddle from the fiddle-averse RVSA comparison, and fix bugs in
+ some debugging statements within mod_negotiation. [Koen Holtman]
+
+ *) Fixed a rare memory corruption possibility in mod_dir if the index
+ file is negotiable and no acceptable variant can be found.
+ [Dean Gaudet, Roy Fielding, Martin Kraemer]
+
+ *) Win32: Add new config directive, ScriptInterpreterSource, to enable
+ searching the Win32 registry for script interpreters.
+ [Bill Stoddard]
+
+ *) Win32: The compiled-in default filename for the error log is now
+ error.log, which matches the default in the distributed httpd.conf.
+ [Paul Sutton]
+
+ *) Win32: Any error messages from -i or -u command line options are now
+ displayed on the console output rather than sent to the error log.
+ Also the "Running Apache..." message is not output unless Apache is
+ going to serve requests. [Paul Sutton]
+
+ *) Rework the MD5 authentication scheme to use FreeBSD's algorithm,
+ and use a private significator ('$apr1$') to mark passwords as
+ being smashed with our own algorithm. Also abstract the password
+ checking into a new ap_validate_password() routine. [Ken Coar]
+
+ *) Win32: The filename validity checker now allows "COM" but refuses
+ access to "COM1" through "COM4". This allows filenames such
+ as "com.name" to be served. [Paul Sutton] PR#3769.
+
+ *) BS2000: Adapt to the new ufork() system call interface which will
+ make subtasking easier on the OSD/POSIX mainframe environment.
+ [Martin Kraemer]
+
+ *) Add a compatibility define for escape_uri() -> ap_escape_uri() to
+ ap_compat.h. [David White <david@persimmon.com>] PR#3725
+
+ *) Make NDBM file suffix determination for mod_rewrite more accurate, i.e.
+ use `.db' instead of `.pag' not only for FreeBSD, but also when
+ the NDBM library looks like Berkeley-DB based.
+ [Ralf S. Engelschall] PR#3773
+
+ *) Add ability to handle DES or MD5 authentication passwords.
+ [Ryan Bloom <rbb@Raleigh.IBM.Com>]
+
+ *) Fix O(n^2) memory consumption in mod_speling. [Dean Gaudet]
+
+ *) SECURITY: Avoid some buffer overflow problems when escaping
+ quoted strings. (This overflow was on the heap and we believe
+ impossible to exploit.) [Rick Perry <perry@ece.vill.edu>]
+
+ *) Let src/Configure be aware of CFLAGS options starting with plus
+ signs as it's the case for the HP/UX compiler.
+ [Doug Yatcilla <yatcilda@umdnj.edu>] PR#3681
+
+ *) Remove the hard-wire of TAR=tar (we now check for gtar and gnutar first)
+ and check to see if the tar we wind up with supports '-h'.
+ [Jim Jagielski] PR#3671
+
+ *) A consistent and conservative style for all shell scripts has been
+ implemented. Basically, all shell string tests use the traditional
+ hack of 'if [ "x$var" != "x" ]' or 'if [ "x$var" = "xstring" ]'
+ to protect against bare null variable strings (ie: wrapping both
+ sides with double quotes and prepending 'x'). 'x' was chosen
+ because it's more universal and hopefully easier for old shell
+ prgrammers, as well as being easier to search for in 'vi' (/x\$) :)
+ [Jim Jagielski]
+
+ *) The status module now prints out both the main server generation as
+ well as the generation of each process. Also, the vhost info is
+ printed with '?notable'. [Jim Jagielski]
+
+ *) Move src/main/md5c.c to src/ap/ap_md5c.c; it's httpd-neutral
+ and this makes its functions available to things in src/support.
+ [Ken Coar]
+
Changes with Apache 1.3.4
*) Renamed macros status_drops_connection to ap_status_drops_connection
@@ -1967,7 +2841,7 @@ Changes with Apache 1.3b6
*) PORT: IRIX needs the -n32 flag iff using the 'cc' compiler
[Jim Jagielski] PR#1901
- *) BUG: Configure was using TCC and CC inconsistantly. Make sure
+ *) BUG: Configure was using TCC and CC inconsistently. Make sure
Configure knows which CC we are using. [Jim Jagielski]
*) "Options +Includes" wasn't correctly merged if "+IncludesNoExec"
diff --git a/usr.sbin/httpd/src/CHANGES.SSL b/usr.sbin/httpd/src/CHANGES.SSL
index 16304281a32..00b298731c5 100644
--- a/usr.sbin/httpd/src/CHANGES.SSL
+++ b/usr.sbin/httpd/src/CHANGES.SSL
@@ -1,8 +1,8 @@
_ _
- _ __ ___ ___ __| | ___ ___| |
- | '_ ` _ \ / _ \ / _` | / __/ __| |
- | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
- |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+ _ __ ___ ___ __| | ___ ___| | mod_ssl
+ | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+ | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+ |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
|_____|
_____________________________________________________________________________
@@ -13,7 +13,462 @@
This file summarizes *all* types of changes to the mod_ssl package, i.e.
changes between each betalevel and patchlevel, i.e. changes between
2.x.y->2.x.(y+1) and 2.x.y->2.(x+1).0. Take this list as a reference for
- concrete and detailed information about every single change.
+ concrete and detailed information about every single change. There are
+ _INTENTIONALLY_ no contributor names attached to the entries. Instead all
+ contributors are listed in the CREDITS file.
+
+ ____ _ _
+ |___ \ | || |
+ __) || || |_
+ / __/ |__ _|
+ __ |_____(_) |_| ___________________________________________
+
+ Changes with mod_ssl 2.4.2 (30-Aug-1999 to 06-Sep-1999)
+
+ *) Added hint about -fPIC vs. -fpic to INSTALL document.
+
+ *) Changed /sw/bin/perl to the more common /usr/bin/perl
+ in pkg.contrib/loadcacert.cgi.
+
+ *) Fixed two (harmless) compile-time warnings related to
+ `unsigned char *' vs. `char *'.
+
+ *) Added hint about required browser restarts on re-installations.
+
+ *) Added quotes to DocumentRoot in conf/httpd.conf-dist
+ to avoid problems with binbuild.sh.
+
+ *) Fixed --with-apxs: configure.stub.sh has to be `sourced' as
+ `./configure.stub.sh' instead of just `configure.stub.sh' or some
+ Bourne Shells cannot find it.
+
+ Changes with mod_ssl 2.4.1 (18-Aug-1999 to 30-Aug-1999)
+
+ *) Added logging hint "too restrictive SSLCipherSuite or using DSA server
+ certificate?" for "no shared cipher" errors.
+
+ *) Added an explicit ap_blush() call to the connection close hook to
+ make sure that pending outgoing data is flushed _before_ the SSL
+ layer is closed. This is important to make sure that the pending
+ data is still transferred through the SSL layer. Else an I/O
+ error can occur inside the browser because the pending data is
+ transferred as plain data (at a time where the browser will no
+ longer expect the data, i.e. after the SSL close notify message
+ was already received by it).
+
+ *) Added new FAQ entries.
+
+ *) Show `-D EAPI_MM' on `httpd -V', too.
+
+ *) Pass also $(MFLAGS) to src/support/mkcert.sh for consistency.
+
+ *) Fixed mod_define.html: `docroot' was doubled.
+
+ *) Made sure mkcert.sh handles the algorithm variable more robust in order
+ to make sure that people do not accidently choose the DSA variant.
+
+ *) mod_ssl now complains already at startup if one tries to use ``SSLMutex
+ file:...'' on Win32 (where the semaphore mutex _has_ to be used).
+
+ *) Removed obsolete pkg.ssldoc/ssl_cover_title.gif
+
+ Changes with mod_ssl 2.4.0 (03-Aug-1999 to 18-Aug-1999)
+
+ *) Upgraded from Apache 1.3.6 to Apache 1.3.9
+ (Apache versions 1.3.7 and 1.3.8 were not released).
+
+ *) Fixed a nasty bug in mod_define.c: the global define variable pool was
+ never destroyed and this way could lead to segfaults on server restarts.
+
+ *) Pass number of bytes from ``SSLRandomSeed exec:/path/to/prog(bytes)'' as
+ first argument to /path/to/prog in order to allow the program to know
+ how much bytes of entropy it should provide on stdout.
+
+ ____ _____
+ |___ \ |___ /
+ __) | |_ \
+ / __/ _ ___) |
+ __ |_____(_)____/ __________________________________________
+
+ Changes with mod_ssl 2.3.11 (28-Jul-1999 to 03-Aug-1999)
+
+ *) Changed pass phrase dialog: Now you're allowed to enter even 1 char pass
+ phrases, i.e. you're no longer required to enter more than 4 characters.
+ That's important for encrypted private keys not generated via OpenSSL.
+
+ *) Added configuration check: Now mod_ssl checks on startup whether the
+ CommonName (CN) of a certificate matches the ServerName of the virtual
+ host. If not, a warning is given, because it will lead to at least
+ popping up dialog boxes in NS and IE.
+
+ *) Added configuration check: Now mod_ssl checks whether more than one
+ SSL-aware virtual host uses the same IP:port and complains with a
+ warning, because for SSL name-based virtual hosts cannot be used.
+
+ *) Overhauled mod_define: it now uses a global define value table and
+ this way not works correctly also in <VirtualHost> sections and other
+ contexts.
+
+ *) Added a few more FAQ entries.
+
+ *) Cleaned up ssl_init_Module() function: it now no longer
+ destroys the server_rec argument as a side-effect.
+
+ *) Fixed top-level Makefile.tmpl: ssl.crl wasn't created; README.CRL
+ wasn't installed; incorporated an important escaping bugfix from Apache
+ 1.3.7-dev.
+
+ *) Added fallback definitions for TRUE/FALSE to ap_mm.h
+
+ *) Fixed I/O pre-sucking for HTTPS proxy situations where
+ no mod_ssl context is attached to SSL structures.
+
+ *) Fixed Mutex acquiring under Win32: the result value
+ was computed incorrectly and leaded to warning log entries.
+
+ *) Catch SIGPIPE in truerand.c (a contrib program in pkg.contrib/) to allow
+ it behave correctly under `SSLRandomSeed exec:bin/truerand N'.
+
+ Changes with mod_ssl 2.3.10 (26-Jul-1999 to 28-Jul-1999)
+
+ *) Changed the handling of the `per-URL SSL re-configuration in conjunction
+ with POST method based HTTP requests' problem: Per default mod_ssl now
+ returns a METHOD_NOT_ALLOWED HTTP error when one tries to POST to a URL
+ which has SSL parameters re-configured, because mod_ssl per default
+ cannot handle this situation (for technical reasons). This way the I/O
+ errors which occured in the past are now at least replaced by a correct
+ error message.
+
+ But when you build with --enable-rule=SSL_EXPERIMENTAL you get
+ experimental support for this situation and you then _CAN_ use POST even
+ in conjunction with per-URL SSL re-configurations.
+
+ But nevertheless one have to keep in mind that the POST body is still
+ transferred under the global SSL parameters and that the renegotiation
+ (typically to a stronger cipher, etc.) happens only before the response
+ is sent (and not before the POST data is read!). The rule of thumb is:
+ per-URL SSL parameters _CANNOT_ be applied to _ANY_ part of the
+ _REQUEST_, they are only guarrantied to be applied to the _RESPONSE_.
+
+ In practice there are situations (for instance when the client resumes
+ the request already with previously renegotiated parameters, etc.) where
+ the situation _CAN_ be better. But you cannot _EXPECT_ it to be better
+ and mod_ssl _CANNOT GUARRANTY_ it to be better, of course.
+
+ *) Added support for latest OpenSSL 0.9.4-dev snapshot version.
+
+ *) Fixed initialization and cleanup relazed problems with SSLMutex: The
+ mutex is now closed before the chown and the mutex is removed only in
+ the parent on module shutdown.
+
+ *) Removed HTTPD_ROOT from EAPI_MM_CORE_PATH definition in httpd.h
+ because it is redundant and can cause problems.
+
+ Changes with mod_ssl 2.3.9 (25-Jul-1999 to 26-Jul-1999)
+
+ *) Compile ap_make_shared_sub_pool() only under -DEAPI
+ and added it to httpd.exp.
+
+ *) Fixed alloc.c again: the ap_mm_destroy has to be used only for
+ defined(EAPI) && defined(EAPI_MM) and not just for defined(EAPI).
+
+ Changes with mod_ssl 2.3.8 (25-Jul-1999 to 25-Jul-1999)
+
+ *) Fixed a nasty problem with early pool cleanups during
+ startup when shared memory session caches are configured.
+
+ Changes with mod_ssl 2.3.7 (14-Jul-1999 to 25-Jul-1999)
+
+ *) Optimization for logfile handling: We now short-circuit the
+ filedescriptors for inherited logfiles in order to save filedescriptors.
+ This is important for mass virtual hosting situations where we really
+ have to reduce the resource consumption.
+
+ *) Enhanced the DBM-based SSL Session Cache:
+
+ o the cache DBM files are removed on shutdowns and restarts now
+ to prevent the occurance of DBM inconsistencies over long runs.
+
+ o the DBM store operation now stores only data which has
+ sizeof(key)+sizeof(data) < 1024 to make sure some broken vendor DBM
+ libraries do not segfault on large entries. Only with the built-in
+ SDBM library up to 8KB are stored.
+
+ o the expiry procedure was rewritten to prevent problems with
+ less smart DBM libraries: Instead of iterating and deleting in
+ parallel (which causes some DBM libraries to become totally crazy) a
+ two pass approach is used. In the first pass the DBM library is
+ scanned and expired elements are remembered only. In the second pass
+ the rememebered elements are actually deleted.
+
+ *) Fixed SSL mutex handling: the mutex file was not removed on shutdown.
+
+ *) Fixed global shared memory pool handling in alloc.c: The shared memory
+ related temporary files of MM were not removed because ap_mm_destroy()
+ was missing on exit.
+
+ *) A few adjustments anf fixes to the FAQ and added hint to OpenSA
+ to INSTALL.Win32.
+
+ *) Fixed ``SSLRandomSeed exec:..'' for OS/2 and Win32.
+
+ *) Fixed shared memory pool handling in alloc.c:
+ Two realloc() calls were not shared memory aware.
+
+ Changes with mod_ssl 2.3.6 (22-Jun-1999 to 14-Jul-1999)
+
+ *) Enhanced ap_mm_create() failure messages in alloc.c
+
+ *) Fixed a core dump for the rare situation where mod_ssl was build
+ statically into Apache but not enabled (AddModule).
+
+ *) Perform more tries to chown() used DBM files.
+
+ *) Fixed memory leaks on restarts related to shared memory session cache:
+ the MM object wasn't removed at all.
+
+ *) Allow SSL_DBM_FILE_SUFFIX_DIR and SSL_DBM_FILE_SUFFIX_PAG
+ to be overridden via CFLAGS.
+
+ *) Fixed grammar and typos in ssl_reference.wml
+
+ *) Done a blind update of the INSTALL.Win32 document.
+
+ *) Added five new FAQ entries.
+
+ *) Fixed EAPI MM related permission problems.
+
+ *) On startup the configured cipher suite is now also
+ displayed under log level "trace".
+
+ *) Let the Win32 configure.bat complain when --with-apache or
+ --with-ssl is missing.
+
+ *) Added new `SSLCertificateChainFile /path/to/file' directive. This can
+ point to a file containing the concatenation of PEM encoded CA
+ certificates which explicitly form the server certificate chain. This is
+ intended for instance for the Global-ID situation where one _has_ to
+ send the intermediate CA of Verisign with the GID while one wants to
+ avoid that under client authentication all clients issued by this CA are
+ accepted (which would happen when one references the CA cert via
+ SSLCACertificatePath or SSLCACertificateFile instead of
+ SSLCertificateChainFile).
+
+ *) Changed the "Interrupted by system" `error' to `info' level in
+ case errno is not > 0.
+
+ Changes with mod_ssl 2.3.5 (18-Jun-1999 to 22-Jun-1999)
+
+ *) Rewritten the DBM and SHM expiration functions in ssl_engine_scache.c to
+ avoid problematic situation where one deletes an entry before the
+ iteration counter was incremented. This was perhaps also another reasons
+ for the session cache related core dumps.
+
+ *) Fixed a nasty bug in ssl_util_table.c: A static (heap-based) calloc()
+ call was forgotten to be converted to a dynamic (shared memory based)
+ table->calloc() call. This leaded to various core dumps once the session
+ cache's hash table was filled as had to be resized (which occured
+ only after some time of operation, of course).
+
+ *) Now mod_ssl displays an info logfile entry when the server certificate
+ is a SCG one and warning logfile entries when the server certificate has
+ BasicConstraints CA:TRUE or pathlen>0.
+
+ *) Fixed FakeBasicAuth handling: ssl::client::dn wasn't
+ set correctly and wasn't set at all in renegotiation context.
+
+ *) Fixed HowTo example with +FakeBasicAuth: AuthName was
+ missing and typos
+
+ Changes with mod_ssl 2.3.4 (09-Jun-1999 to 18-Jun-1999)
+
+ *) The Fake Basic Auth stuff now is logging it's operation.
+
+ *) Fixed pkg.contrib/cca.sh script: CA:TRUE was incorrect
+ for a client certificate, of course.
+
+ *) Added session cache status display to the pages generated by mod_status.
+ When "ExtendedStatus on" is used mod_ssl appends session cache
+ information (supported for both DBM and SHM).
+
+ *) Fixed ``SSLVerifyClient optional_no_ca'' for per-directory context.
+
+ *) Added ``SSLOptions +OptRenegotiate'':
+ This enables optimized SSL connection renegotiation handling when SSL
+ directives are used in per-directory context. Per default a strict
+ handling is enabled where every per-directory reconfiguration of SSL
+ parameters cause a full SSL renegotiation handshake. When this option
+ is used mod_ssl tries to avoid unnecessary handshakes by doing more
+ granular (but still safe) parameter checks. This should reduce
+ the renegotiation overhead a little bit.
+
+ *) Also print SSL errors on SSL_ERROR_SYSCALL situation.
+
+ *) Make sure EAPI_MM=SYSTEM doesn't add -I/usr/include to CFLAGS (which
+ occurrs for instance under Debian where MM is installed in system
+ locations).
+
+ *) The SSL session context is now also set on session renegotiations.
+
+ Changes with mod_ssl 2.3.3 (08-Jun-1999 to 09-Jun-1999)
+
+ *) Various type fixes for Session Cache code.
+
+ *) A few fixes to make the Win32 world happy again.
+
+ *) Fixed glibc 2.1 ndbm.h inclusion problems.
+
+ *) Make sure that in "SSLSessionCache shm:/path/to/file(NNN)"
+ the size NNN cannot be specified greater than the maximum
+ possible shared memory segment (which is platform
+ dependent, of course).
+
+ Changes with mod_ssl 2.3.2 (28-May-1999 to 08-Jun-1999)
+
+ *) Removed obsolete mca.sh script and updated cca.sh script to current
+ OpenSSL state.
+
+ *) Now "SSLSessionCache none" really disables _all_ caching,
+ i.e. including the internal OpenSSL cache.
+
+ *) Added Shared Memory based SSL Session Cache: A new "SSLSessionCache
+ shm:/path/to/file(bytes)" variant of the SSL session cache was added.
+ This uses a high-performance hash table inside a shared memory segment
+ to provide the fastest inter-process session cache which is possible.
+ For this Apache+EAPI has to be built with EAPI_MM (linked against the MM
+ library, the shared memory abstraction).
+
+ *) Fixed the EAPI_MM related patches to Apache's src/Configure:
+ The variables were overridden instead of extended.
+
+ *) Added hint to FAQ to make sure people enter the FQDN for CommonName when
+ generating a server certificate. Added hint to EGD to reference chapter.
+
+ *) Some more Win32 fixes.
+
+ *) Fixed a session cache problem on shutdowns.
+
+ *) Fixed mod_ssl's ``configure --with-mm=DIR''
+
+ Changes with mod_ssl 2.3.1 (25-Apr-1999 to 28-May-1999)
+
+ *) Fixed two memory leaks in ssl_util_ssl.c related to BIOs.
+
+ *) Fixed EAPI sources in src/ap/: They failed to compile
+ when -DEAPI wasn't used which isn't nice.
+
+ *) Fixed Win32 stuff: src/ap/ap.mak missed entries for ap_mm.[ch],
+ src/modules/ssl/Makefile.win32 missed entry for ssl_engine_dh.c,
+ configure.bat wasn't aware of the new include/openssl/ layout.
+
+ Changes with mod_ssl 2.3.0 (12-Apr-1999 to 25-May-1999)
+
+ *) Upgraded to final OpenSSL 0.9.3 API and made this
+ version the lowest possible OpenSSL version for mod_ssl.
+
+ *) Fixed ap_mm.c stubs.
+
+ *) Updated dependencies in src/modules/ssl/Makefile.tmpl
+
+ *) Fixed INSTALL document for OpenSSL 0.9.3:
+ -DNO_IDEA => no-idea and -DRSAref & friends => rsaref.
+
+ *) ** Second major step for DH/DSA support **:
+ The mod_ssl module itself is now aware of multiple certificate/keys when
+ they are of a different type (one RSA, the other DSA). All internal
+ cert/key related handling which was hard-coded for RSA was replaced by
+ generic code which supports both RSA and DSA. This way now all SSL
+ ciphers, including the real Diffie-Hellman ciphers like
+ EDH-DSS-DES-CBC3-SHA are supported by mod_ssl.
+
+ *) Upgraded Thawte's sxnet stuff in pkg.contrib/
+
+ *) Added new variable SSL_SESSION_ID which contains the hex-encoded SSL
+ session id. This variable is also exported to the SSI/CGI environment
+ and can be used as a session-unique key.
+
+ *) Added more error checking for SSL_XXX variable lookups.
+
+ *) ** First major step for DH/DSA support **:
+ 1) snakeoil.{crt,key} was renamed to snakeoil-rsa.{crt,key} and a
+ snakeoil-dsa.{crt,key} was created. 2) src/support/ca-fix.c was kicked
+ out (it's obsolete with OpenSSL 0.9.3) and 3) src/support/mkcert.sh was
+ changed to use the new `openssl x509 -extfile ..' instead of ca-fix and
+ to support the generation of DSA certs/keys via `openssl gendsa'.
+ Finally 4) the top-level Makefiles were adjusted to support an
+ ALGO={RSA,DSA} parameter for selecting the algorithm in batch and a
+ VIEW=1 parameter for viewing the generated cert/key in plain text
+ format.
+
+ *) Removed more source code relicts of SSLeay by replacing
+ them with the official OpenSSL variants.
+
+ *) Added ap_{mm,MM}* function list to src/support/httpd.exp
+
+ *) Update ap_mm.{c,h} for MM 1.0.3, i.e. add stubs for new
+ ap_{MM,mm,mm_core}_permission() function.
+
+ *) Replaced all references to EAY's old email address with the new one.
+
+ *) Fixed source tree creation: ap_mm.[ch] wasn't installed.
+
+ *) Removed -l option from yacc call in src/modules/ssl/Makefile.tmpl and
+ touch the pre-generated scanner/parser files so the generation isn't
+ done for end users.
+
+ *) Give more reasonable error message on pass phrase dialog by
+ distinguishing between "Pass phrase incorrect" and "Private key not
+ found" situations.
+
+ *) Fixed configure and configure.bat scripts: ssl.crl wasn't created
+ and server.csr wasn't installed under Win32.
+
+ *) Added a new ``SSLOptions +StrictRequire'' This _forces_ forbidden
+ access when SSLRequireSSL or SSLRequire successfully decided that access
+ should be forbidden. Usually the default is that at least a used
+ ``Satisfy any'' can cancel such access denies (when other access
+ restrictions were passed), because that's how the Apache Satisfy
+ mechanism should work. But for strict access restriction you can use
+ SSLRequireSSL and/or SSLRequire in combination with an ``SSLOptions
+ +StrictRequire''. Then an additional ``Satisfy Any'' has no chance once
+ mod_ssl has decided to deny access.
+
+ *) Removed all direct Apache-SSL related comparsions from the mod_ssl FAQ
+ chapter of the user manual to finally avoid any more blames by Ben
+ Laurie.
+
+ *) Upgraded to the forthcoming OpenSSL 0.9.3 API. Because of too much API
+ changes (constifications, STACK_OF, etc.) we cannot provide support for
+ older versions any longer without making the mod_ssl source code ugly.
+ OTOH for mkcert.sh we already want >= 0.9.3, so drop support for all
+ older versions now.
+
+ *) Switched all addresses and references to new modssl.org domain.
+
+ *) Updated the User Manual for version 2.3
+
+ *) Various stylistic source code cleanups.
+
+ *) EBCDIC-related fix for variable lookup functions.
+
+ *) Added generic Shared Memory support to Extended API (EAPI) via the new
+ MM library (available externally). First two new ap_mm.c/ap_mm.h source
+ files provide new functions ap_mm_xxx() which are either stubs (when no
+ shared memory support is available via the MM library) or call the
+ mm_xxx() counterparts of the MM library. Second, shared memory pools
+ are patched into alloc.c/alloc.h which uses the ap_mm_xxx() functions in
+ the background.
+
+ *) Added support for X.509 CA Certificate Revocation Lists (CRL). For this
+ the two new directives SSLCARevocationPath and SSLCARevocationFile
+ (similar to SSLCACertificate{Path,File}) are provided where one can
+ store CRL files. The preconfigured default directory for CRLs is
+ PREFIX/conf/ssl.crl. The SSLCARevocationPath is a directory where the
+ CRLs are looked up via hash symlinks. For this a ssl.crl/Makefile is
+ provided similar to ssl.crt/Makefile.
+
+ *) Kicked out all remaining SSLeay references and dependencies. The
+ minimum SSL library version which is now required is OpenSSL 0.9.2b.
____ ____
|___ \ |___ \
@@ -21,6 +476,216 @@
/ __/ _ / __/
__ |_____(_)_____| _________________________________________
+ Changes with mod_ssl 2.2.8 (29-Mar-1999 to 12-Apr-1999)
+
+ *) Use SSL_smart_shutdown() also for SSL proxy stuff.
+
+ *) Fixed some compat variable mappings and updated ssl_compat.wml
+ document to reflect the current compat state.
+
+ *) Added ssl_log_applies() function in advance for forthcoming feature
+ commits.
+
+ *) Added NEWS file to distribution which summarizes the major changes and
+ this way gives a faster overview for the impatient users.
+
+ *) Added a new pkg.contrib/cca.sh script which I used for client auth
+ testing with the latest OpenSSL versions. Additionally adjust old
+ mca.sh script for OpenSSL.
+
+ *) Added the missing ssl_template.inc file to the distribution
+
+ *) Various source code cleanups to make forthcoming patches more clean.
+
+ Changes with mod_ssl 2.2.7 (24-Mar-1999 to 29-Mar-1999)
+
+ *) Fixed the ``HTTPS request received for child'' log entries: Now no
+ longer multiple copies of a message occur, because mod_ssl logs them
+ only on initial requests (and no longer on sub-requests and internal
+ redirects).
+
+ *) Fixed a few more memory leaks which occured on server restarts.
+
+ *) Added entry to the FAQ for the MSIE work-around with
+ ``SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown''.
+
+ *) Added support for two SetEnvIf variables: ssl-unclean-shutdown and
+ ssl-accurate-shutdown. These can be used to for instance force different
+ shutdown approaches for particular browsers. An ``SetEnvIf User-Agent
+ ".*MSIE.*" ssl-unclean-shutdown'' now forces the old mod_ssl 2.1
+ behaviour where no close notify messages are sent at all before
+ connection close. An ``SetEnvIf User-Agent ".*Lynx.*"
+ ssl-accurate-shutdown'' forces an accurate shutdown when the client is
+ Lynx+OpenSSL where mod_ssl both sends it's close notify alert and waits
+ for the close notify alert of the client.
+
+ *) Updated source file dependecies in src/modules/ssl/Makefile.tmpl.
+
+ Changes with mod_ssl 2.2.6 (18-Mar-1999 to 24-Mar-1999)
+
+ *) Now mod_ssl logs the current Apache, mod_ssl and OpenSSL versions at
+ startup which makes it easier to distinguish which software combination
+ is actually running by just looking into the log.
+
+ *) Added support for new 56/1024 bit export ciphersuites (idea overtaken
+ from Apache-SSL 1.32) and sign-only-certificate situations where
+ stronger (1024 instead of 512 bit) temporary keys are reasonable to use.
+
+ *) Upgrade to new upstream version Apache 1.3.6 on vendor branch.
+ [Version 1.3.5 was not released because of last minute problems]
+
+ *) *** SECURITY *** SECURITY *** SECURITY ***
+ In the OpenSSL project we discovered that a terrible security hole
+ exists for _all_ SSLeay/OpenSSL server applications that use virtual
+ hosting. Here sessions could be resumed in the wrong context thus
+ bypassing client certificate protection! This hole is now fixed in
+ OpenSSL 0.9.2b by an ad-hoc solution were SSL sessions cannot be resumed
+ unless the server application tags it with a unique context id per
+ virtual host. mod_ssl now also performs this tagging to prevent this
+ exploit.
+
+ *) Added the nifty EAPI-based mod_define module to the source tree. This
+ modules provides variable definitions for arbitrary directive lines,
+ i.e. you can expand ${xxx} on any(!) directive line. This module is
+ disabled per default in src/Configuration.tmpl (need an
+ --enable-module=define) and it lives in the new pkg.addon area.
+
+ *) Added Stronghold's table look and feel to mod_status' display page.
+ This patch is harmless and enabled per default and lives in the new
+ pkg.addon area.
+
+ *) Opened another distribution package subdir: pkg.addon/.
+ Here addons will be stored which are not directly/physically related to
+ mod_ssl and EAPI, but indirectly.
+
+ *) Cleaned up the generation of the signature table in ap_hook.c
+ and updated the hook list with the still missing vendor hooks.
+
+ *) Renamed recently added vendor hooks to from ssl::vendor::xxx to
+ ap::mod_ssl::vendor::xxx to be consistent with remaining EAPI hook
+ names.
+
+ *) Upgrade to new upstream version Apache 1.3.5 on vendor branch
+
+ *) Fixed a segfault in the HTTPS support for mod_proxy which
+ occured when the proxy couldn't connect to the remote host.
+
+ *) Be 100% conservative and clean and use SSL_clean() after SSL_new().
+
+ Changes with mod_ssl 2.2.5 (04-Mar-1999 to 18-Mar-1999)
+
+ *) Fixed the situation were we discovered processes consuming
+ 100% CPU time. This occured under various not exactly known
+ circumstances, but it seems it was always when the client plays bad with
+ the socket connection and OpenSSL cannot recognize it. Then the state
+ machine of SSL_shutdown() seems to loop endless. It's now fixed by not
+ limiting the iterations.
+
+ *) Fixed a typo in the SSL_CERTIFICATE_FILE define, although this
+ variable is still not used.
+
+ *) Fixed the POST-problem where kept-alive HTTPS connections hang or
+ resulted in an I/O error inside the browser because the ``SSL close
+ notify'' alert couldn't be sent correctly because of Apache's internal
+ ``lingering close'' handling. EAPI was changed to now correctly call the
+ close_connection module hook also on timeout and linger closes. This
+ EAPI change means you cannot upgrade your libssl.so with --with-apxs to
+ this version. A complete Apache rebuild with the updated EAPI code is
+ necessary.
+
+ *) The SSLCertificateFile and SSLCertificateKeyFile directives now can read
+ PEM (=DER+Base64+headers), DER+Base64 (without headers) and plain DER
+ format certificate and private key files. This is mostly provided for
+ convinience reasons.
+
+ *) Add FAQ entry: How to convert PEM into DER.
+
+ Changes with mod_ssl 2.2.4 (21-Feb-1999 to 04-Mar-1999)
+
+ *) Add important note to INSTALL/INSTALL.Win32 that all
+ documentation references already use the term OpenSSL, the file and
+ program names `openssl', etc. although most of the users are still using
+ SSLeay and don't have any `openssl' command, etc.
+
+ *) Fixed two export warnings for ssl_expr_parse.c under Win32.
+
+ *) In correspondence with the SSLeay to OpenSSL transition
+ we changed the --with-ssleay=DIR option to --with-ssl=DIR (but the old
+ variant is still recognized for backward compatibility, of course). For
+ consistency we also renamed --with-rsaref=DIR to --with-rsa=DIR.
+
+ *) Ported src/support/ca-fix tool to OpenSSL 0.9.2, although after final
+ switching to OpenSSL 0.9.2 as the minimum required toolkit version we
+ will no longer need this tool. But until then let us be friendly and
+ support the OpenSSL snapshots ;-)
+
+ *) Added the first cut of Vendor extension support. This stuff is
+ currently _NOT_ compiled in per default. It has to be enabled with the
+ new APACI --enable-rule=SSL_VENDOR option. The idea is this: the mod_ssl
+ sources contain EAPI vendor hooks (`ssl::vendor::xxxx') and internal
+ EAPI context variables which can be used to change or extend mod_ssl by
+ a vendor without patching the source code. Grep for `ssl::vendor::'
+ inside src/modules/ssl/ for more details. Additionally vendors can now
+ add their own source code as files named ssl_vendor.c, ssl_vendor_XXX.c,
+ etc. The libssl.module script automatically picks these up under
+ configuration time and mod_ssl under run-time calls the functions `void
+ ssl_vendor_register(void)' and `void ssl_vendor_unregister(void)' inside
+ these objects to bootstrap them. Read the src/modules/ssl/README file
+ for more details.
+
+ *) Fixed two old Stronghold directive compatibility mappings, added missing
+ Stronghold directive mappings and added a bunch of additional Stronghold
+ variable mappings.
+
+ *) Big and official switch from the name `Apache Interface to SSLeay' to
+ `Apache Interface to OpenSSL', from any SSLeay-references to
+ OpenSSL-references, etc. There is still support for SSLeay, of course.
+ But this renaming cleanup has to be done, because in the near future
+ support for SSLeay has to be completely dropped due to non-optional
+ support for new features like DSA/DH, etc (which is only possible with
+ OpenSSL).
+
+ *) Made the error messages of `configure' even more idiot-proof :-(
+
+ *) Fixed the connection closing phase: First, mod_ssl no longer hooks into
+ this phase by using ap_register_cleanup() (with the connection pool)
+ because the cleanup functions are called by Apache's API a lot too late
+ (actually _after_ the socket was already closed!). Instead a new EAPI
+ hook `close_connection' was added to register a hook which is run
+ directly _before_ the socket is closed. Second, the SSL ``Close
+ Notify'' alert is now always sent (even when older IE browsers display
+ the message in the window), because not sending the alert is a violation
+ of the SSL/TLS standard.
+ !! ATTENTION: THIS HAD TO CHANGE EAPI, SO YOU HAVE TO RECOMPILE APACHE !!
+
+ *) Enhance the output of alert messages under `SSLLogLevel trace'.
+
+ *) Make mod_ssl aware of the forthcoming OpenSSL 0.9.2 version
+ where some callback function signatures will be changed
+ and a few new TLSv1 export ciphers are added.
+
+ *) Fixed restarts which were broken due to recent changes to the cert/key
+ handling (DER/internal conversions). Now mod_ssl again surives server
+ restarts without problems.
+
+ *) Replaced `%0 %*' with `%0 %1 %2 %3 %4 %5 %6 %7 %8 %9' in configure.bat
+ because Windows 98 is even more braindead than anyone can image.
+
+ *) Added AP_HOOK_DECLTMP return code semantic to EAPI's hook mechanism
+ which is needed in the forthcoming vendor hooks to avoid local temporary
+ variables.
+
+ *) Fixed the `SSLLogLevel debug' output where confusing `Ops, no memory
+ buffer?' messages occured in the past. The BIO callback function now
+ only outputs messages for the actual read/write calls.
+
+ *) Fixed a warning the `gcc -O -Wall ...' compiler flag combination causes.
+
+ *) Fixed confusing terms in the final messages in mkcert.sh
+ which display a short description of files under `make certificate'.
+
+ *) Fixed compilation for SunOS where no RAND_MAX exists.
+
Changes with mod_ssl 2.2.3 (05-Feb-1999 to 21-Feb-1999)
*) Cleaned up the namespace of mod_ssl structures:
@@ -1023,7 +1688,7 @@
$ make certificate TYPE=dummy (dummy self-signed Snake Oil cert)
$ make certificate TYPE=test (test cert signed by Snake Oil CA)
$ make certificate TYPE=custom (custom cert signed by own CA)
- $ make certificate TYPE=official (existing official cert)
+ $ make certificate TYPE=existing (existing official cert)
CRT=/path/to/your.crt
[KEY=/path/to/your.key]
The default is TYPE=test which is equivalent to the old `make
@@ -1738,7 +2403,7 @@
$ make certificate TYPE=dummy (dummy self-signed Snake Oil cert)
$ make certificate TYPE=test (test cert signed by Snake Oil CA)
$ make certificate TYPE=custom (custom cert signed by own CA)
- $ make certificate TYPE=official (existing official cert)
+ $ make certificate TYPE=existing (existing official cert)
CRT=/path/to/your.crt
[KEY=/path/to/your.key]
The default is TYPE=test which is equivalent to the old `make
diff --git a/usr.sbin/httpd/src/Configuration b/usr.sbin/httpd/src/Configuration
index a10f798aa6e..68cc2dfaf91 100644
--- a/usr.sbin/httpd/src/Configuration
+++ b/usr.sbin/httpd/src/Configuration
@@ -26,47 +26,6 @@
# not enabled). The AddModule directive can be used to enable such a
# module. By default no such modules are defined.
-################################################################
-# SSL support:
-#
-# o Set SSL_BASE to either the directory of your SSLeay
-# source tree or the installation tree. Alternatively you can
-# also use the value 'SYSTEM' which then indicates that SSLeay
-# is installed under various system locations.
-#
-# o If you're a US-citizen you have to compile SSLeay with the
-# RSAref library (which replaces the RSA code of SSLeay)
-# because of patent legalities with the RSA algorithm used for
-# the SSL protocol. For this situation you already have to
-# compile SSLeay with the -DRSAref define and now you have to
-# force Apache to link against the RSAglue library (from
-# SSLeay) and the rsaref library (from RSA). So, set RSA_BASE
-# to the directory of your RSAref source tree or to 'SYSTEM'
-# (indicating that librsaref.a is installed under a system
-# location)
-#
-# o Disable SSL_COMPAT rule to build mod_ssl without backward
-# compatibility code for Apache-SSL 1.x, mod_ssl 2.0.x Sioux
-# 1.x and Stronghold 2.x.
-#
-# o The SSL_SDBM rule controls whether the built-in SDBM library should be
-# used instead of a custom defined or vendor supplied DBM library. Use the
-# value 'default' for automatic determination or use 'yes' to force the use
-# of SDBM in case the vendor DBM library is buggy or restricts the data
-# sizes too dramatically.
-#
-# o The SSL_EXPERIMENTAL rule can be used to enable still experimental code
-# inside mod_ssl. These are usually new features which need some more
-# testing before they can be considered stable. So, enabled this on your own
-# risk and only when you like to see Apache+mod_ssl dump core ;-)
-#
-
-#SSL_BASE=/usr/local/ssl
-#RSA_BASE=/usr/local/rsa
-SSL_BASE=SYSTEM
-Rule SSL_COMPAT=yes
-Rule SSL_SDBM=default
-Rule SSL_EXPERIMENTAL=no
################################################################
# Makefile configuration
@@ -165,12 +124,12 @@ Rule SHARED_CHAIN=default
# functions. The format is: Rule RULE=value
#
# At present, only the following RULES are known: WANTHSREGEX, SOCKS4,
-# SOCKS5, IRIXNIS, IRIXN32 and PARANOID.
+# SOCKS5, IRIXNIS, IRIXN32, PARANOID, and DEV_RANDOM.
#
-# For all Rules, if set to "yes", then Configure knows we want that
-# capability and does what is required to add it in. If set to "default"
-# then Configure makes a "best guess"; if set to anything else, or not
-# present, then nothing is done.
+# For all Rules except DEV_RANDOM, if set to "yes", then Configure knows
+# we want that capability and does what is required to add it in. If set
+# to "default" then Configure makes a "best guess"; if set to anything
+# else, or not present, then nothing is done.
#
# SOCKS4:
# If SOCKS4 is set to 'yes', be sure that you add the socks library
@@ -201,12 +160,11 @@ Rule SHARED_CHAIN=default
# is performing this function. If PARANOID is set to yes, it will
# actually print-out the code that the modules execute
#
-# EAPI:
-# Enable the Extended API which provides more module hooks, a generic
-# low-level hook mechanism and a generic context mechanism. Please notice
-# that enabling this rule forces you to recompile (with -DEAPI) all existing
-# modules which are already built and installed as DSOs. Because under EAPI
-# the module configuration structure has a different size.
+# EXPAT:
+# Include James Clark's Expat package into Apache, for use by the
+# modules. The "default" is to include it if the lib/expat-lite/
+# directory is present. This rule will always be interpreted as "no"
+# if the directory is not present.
#
Rule SOCKS4=no
@@ -214,7 +172,20 @@ Rule SOCKS5=no
Rule IRIXNIS=no
Rule IRIXN32=yes
Rule PARANOID=no
-Rule EAPI=no
+Rule EXPAT=default
+
+# DEV_RANDOM:
+# Note: this rule is only used when compiling mod_auth_digest.
+# mod_auth_digest requires a cryptographically strong random seed for its
+# random number generator. It knows two ways of getting this: 1) from
+# a file or device (such as "/dev/random"), or 2) from the truerand
+# library. If this rule is set to 'default' then Configure will choose
+# to use /dev/random if it exists, else /dev/urandom if it exists,
+# else the truerand library. To override this behaviour set DEV_RANDOM
+# either to 'truerand' (to use the library) or to a device or file
+# (e.g. '/dev/urandom'). If the truerand library is selected, Configure
+# will assume "-L/usr/local/lib -lrand".
+Rule DEV_RANDOM=default
# The following rules should be set automatically by Configure. However, if
# they are not set by Configure (because we don't know the correct value for
@@ -256,6 +227,13 @@ Rule WANTHSREGEX=default
# AddModule modules/experimental/mod_mmap_static.o
+## mod_vhost_alias provides support for mass virtual hosting
+## by dynamically changing the document root and CGI directory
+## based on the host header or local IP address of the request.
+## See "../htdocs/manual/vhosts/mass.html".
+
+# AddModule modules/standard/mod_vhost_alias.o
+
##
## Config manipulation modules
##
@@ -344,13 +322,6 @@ AddModule modules/standard/mod_actions.o
AddModule modules/standard/mod_userdir.o
-## The proxy module enables the server to act as a proxy for outside
-## http and ftp services. It's not as complete as it could be yet.
-## NOTE: You do not want this module UNLESS you are running a proxy;
-## it is not needed for normal (origin server) operation.
-
-# AddModule modules/proxy/libproxy.a
-
## The Alias module provides simple URL translation and redirection.
AddModule modules/standard/mod_alias.o
@@ -377,14 +348,39 @@ AddModule modules/standard/mod_auth.o
## "gdbm" package if not and possibly adjust EXTRA_LIBS. (This may be
## done by Configure at a later date)
-AddModule modules/standard/mod_auth_dbm.o
-AddModule modules/standard/mod_auth_db.o
+# AddModule modules/standard/mod_auth_dbm.o
+# AddModule modules/standard/mod_auth_db.o
## "digest" implements HTTP Digest Authentication rather than the less
-## secure Basic Auth used by the other modules.
+## secure Basic Auth used by the other modules. This is the old version.
# AddModule modules/standard/mod_digest.o
+## "auth_digest" implements HTTP/1.1 Digest Authentication (RFC 2617)
+## rather than the less secure Basic Auth used by the other modules.
+## This is an updated version of mod_digest, but it is not as well tested
+## and is therefore marked experimental. Use either the one above, or
+## this one below, but not both digest modules.
+## Note: if you add this module in then you might also need the
+## truerand library (available for example from
+## ftp://research.att.com/dist/mab/librand.shar) - see the Rule
+## DEV_RANDOM above for more info.
+##
+## Must be added above (run later than) the proxy module because the
+## WWW-Authenticate and Proxy-Authenticate headers are parsed in the
+## post-read-request phase and it needs to know if this is a proxy request.
+
+# AddModule modules/experimental/mod_auth_digest.o
+
+## Optional Proxy
+##
+## The proxy module enables the server to act as a proxy for outside
+## http and ftp services. It's not as complete as it could be yet.
+## NOTE: You do not want this module UNLESS you are running a proxy;
+## it is not needed for normal (origin server) operation.
+
+# AddModule modules/proxy/libproxy.a
+
## Optional response header manipulation modules.
##
## cern_meta mimics the behavior of the CERN web server with regards to
@@ -440,9 +436,3 @@ AddModule modules/standard/mod_auth_db.o
AddModule modules/standard/mod_setenvif.o
-## mod_ssl incorporates SSL into Apache.
-## It must stay last here to be first in execution to
-## fake basic authorization.
-
-AddModule modules/ssl/libssl.a
-
diff --git a/usr.sbin/httpd/src/Configuration.tmpl b/usr.sbin/httpd/src/Configuration.tmpl
index 351303ec0e8..35fdc590708 100644
--- a/usr.sbin/httpd/src/Configuration.tmpl
+++ b/usr.sbin/httpd/src/Configuration.tmpl
@@ -29,25 +29,21 @@
################################################################
# SSL support:
#
-# o Set SSL_BASE to either the directory of your SSLeay
-# source tree or the installation tree. Alternatively you can
-# also use the value 'SYSTEM' which then indicates that SSLeay
-# is installed under various system locations.
-#
-# o If you're a US-citizen you have to compile SSLeay with the
-# RSAref library (which replaces the RSA code of SSLeay)
-# because of patent legalities with the RSA algorithm used for
-# the SSL protocol. For this situation you already have to
-# compile SSLeay with the -DRSAref define and now you have to
-# force Apache to link against the RSAglue library (from
-# SSLeay) and the rsaref library (from RSA). So, set RSA_BASE
-# to the directory of your RSAref source tree or to 'SYSTEM'
-# (indicating that librsaref.a is installed under a system
-# location)
-#
-# o Disable SSL_COMPAT rule to build mod_ssl without backward
-# compatibility code for Apache-SSL 1.x, mod_ssl 2.0.x Sioux
-# 1.x and Stronghold 2.x.
+# o Set SSL_BASE to either the directory of your OpenSSL source tree or the
+# installation tree. Alternatively you can also use the value 'SYSTEM' which
+# then indicates that OpenSSL is installed under various system locations.
+#
+# o If you're a US-citizen you have to compile OpenSSL with the RSAref library
+# (which replaces the RSA code of OpenSSL) because of patent legalities with
+# the RSA algorithm used for the SSL protocol. For this situation you
+# already have to compile OpenSSL with the -DRSAref define and now you have
+# to force Apache to link against the RSAglue library (from OpenSSL) and the
+# rsaref library (from RSA). So, set RSA_BASE to the directory of your
+# RSAref source tree or to 'SYSTEM' (indicating that librsaref.a is
+# installed under a system location)
+#
+# o Disable SSL_COMPAT rule to build mod_ssl without backward compatibility
+# code for Apache-SSL 1.x, mod_ssl 2.0.x, Sioux 1.x and Stronghold 2.x.
#
# o The SSL_SDBM rule controls whether the built-in SDBM library should be
# used instead of a custom defined or vendor supplied DBM library. Use the
@@ -59,13 +55,18 @@
# inside mod_ssl. These are usually new features which need some more
# testing before they can be considered stable. So, enabled this on your own
# risk and only when you like to see Apache+mod_ssl dump core ;-)
-#
+#
+# o The SSL_VENDOR rule can be used to enable code inside mod_ssl which can be
+# used by product vendors to extend mod_ssl via EAPI hooks without patching
+# the source. Additionally ssl_vendor*.c source files are automatically
+# picked up by the compilation process.
#SSL_BASE=/usr/local/ssl
#RSA_BASE=/usr/local/rsa
Rule SSL_COMPAT=yes
Rule SSL_SDBM=default
Rule SSL_EXPERIMENTAL=no
+Rule SSL_VENDOR=no
################################################################
# Makefile configuration
@@ -108,6 +109,24 @@ EXTRA_DEPS=
#TARGET=
################################################################
+# Extended API (EAPI) support:
+#
+# EAPI:
+# The EAPI rule enables more module hooks, a generic low-level hook
+# mechanism, a generic context mechanism and shared memory based pools.
+#
+# EAPI_MM:
+# Set the EAPI_MM variable to either the directory of a MM Shared Memory
+# Library source tree or the installation tree of MM. Alternatively you can
+# also use the value 'SYSTEM' which then indicates that MM is installed
+# under various system locations. When the MM library files cannot be found
+# the EAPI still can be built, but without shared memory pool support, of
+# course.
+
+Rule EAPI=no
+#EAPI_MM=SYSTEM
+
+################################################################
# Dynamic Shared Object (DSO) support
#
# There is experimental support for compiling the Apache core and
@@ -164,12 +183,12 @@ Rule SHARED_CHAIN=default
# functions. The format is: Rule RULE=value
#
# At present, only the following RULES are known: WANTHSREGEX, SOCKS4,
-# SOCKS5, IRIXNIS, IRIXN32 and PARANOID.
+# SOCKS5, IRIXNIS, IRIXN32, PARANOID, and DEV_RANDOM.
#
-# For all Rules, if set to "yes", then Configure knows we want that
-# capability and does what is required to add it in. If set to "default"
-# then Configure makes a "best guess"; if set to anything else, or not
-# present, then nothing is done.
+# For all Rules except DEV_RANDOM, if set to "yes", then Configure knows
+# we want that capability and does what is required to add it in. If set
+# to "default" then Configure makes a "best guess"; if set to anything
+# else, or not present, then nothing is done.
#
# SOCKS4:
# If SOCKS4 is set to 'yes', be sure that you add the socks library
@@ -200,12 +219,11 @@ Rule SHARED_CHAIN=default
# is performing this function. If PARANOID is set to yes, it will
# actually print-out the code that the modules execute
#
-# EAPI:
-# Enable the Extended API which provides more module hooks, a generic
-# low-level hook mechanism and a generic context mechanism. Please notice
-# that enabling this rule forces you to recompile (with -DEAPI) all existing
-# modules which are already built and installed as DSOs. Because under EAPI
-# the module configuration structure has a different size.
+# EXPAT:
+# Include James Clark's Expat package into Apache, for use by the
+# modules. The "default" is to include it if the lib/expat-lite/
+# directory is present. This rule will always be interpreted as "no"
+# if the directory is not present.
#
Rule SOCKS4=no
@@ -213,7 +231,20 @@ Rule SOCKS5=no
Rule IRIXNIS=no
Rule IRIXN32=yes
Rule PARANOID=no
-Rule EAPI=no
+Rule EXPAT=default
+
+# DEV_RANDOM:
+# Note: this rule is only used when compiling mod_auth_digest.
+# mod_auth_digest requires a cryptographically strong random seed for its
+# random number generator. It knows two ways of getting this: 1) from
+# a file or device (such as "/dev/random"), or 2) from the truerand
+# library. If this rule is set to 'default' then Configure will choose
+# to use /dev/random if it exists, else /dev/urandom if it exists,
+# else the truerand library. To override this behaviour set DEV_RANDOM
+# either to 'truerand' (to use the library) or to a device or file
+# (e.g. '/dev/urandom'). If the truerand library is selected, Configure
+# will assume "-L/usr/local/lib -lrand".
+Rule DEV_RANDOM=default
# The following rules should be set automatically by Configure. However, if
# they are not set by Configure (because we don't know the correct value for
@@ -255,6 +286,13 @@ Rule WANTHSREGEX=default
# AddModule modules/experimental/mod_mmap_static.o
+## mod_vhost_alias provides support for mass virtual hosting
+## by dynamically changing the document root and CGI directory
+## based on the host header or local IP address of the request.
+## See "../htdocs/manual/vhosts/mass.html".
+
+# AddModule modules/standard/mod_vhost_alias.o
+
##
## Config manipulation modules
##
@@ -264,6 +302,11 @@ Rule WANTHSREGEX=default
AddModule modules/standard/mod_env.o
+## mod_define expands variables on arbitrary directive lines.
+## It requires Extended API (EAPI).
+
+# AddModule modules/extra/mod_define.o
+
##
## Request logging modules
##
@@ -343,13 +386,6 @@ AddModule modules/standard/mod_actions.o
AddModule modules/standard/mod_userdir.o
-## The proxy module enables the server to act as a proxy for outside
-## http and ftp services. It's not as complete as it could be yet.
-## NOTE: You do not want this module UNLESS you are running a proxy;
-## it is not needed for normal (origin server) operation.
-
-# AddModule modules/proxy/libproxy.a
-
## The Alias module provides simple URL translation and redirection.
AddModule modules/standard/mod_alias.o
@@ -380,10 +416,35 @@ AddModule modules/standard/mod_auth.o
# AddModule modules/standard/mod_auth_db.o
## "digest" implements HTTP Digest Authentication rather than the less
-## secure Basic Auth used by the other modules.
+## secure Basic Auth used by the other modules. This is the old version.
# AddModule modules/standard/mod_digest.o
+## "auth_digest" implements HTTP/1.1 Digest Authentication (RFC 2617)
+## rather than the less secure Basic Auth used by the other modules.
+## This is an updated version of mod_digest, but it is not as well tested
+## and is therefore marked experimental. Use either the one above, or
+## this one below, but not both digest modules.
+## Note: if you add this module in then you might also need the
+## truerand library (available for example from
+## ftp://research.att.com/dist/mab/librand.shar) - see the Rule
+## DEV_RANDOM above for more info.
+##
+## Must be added above (run later than) the proxy module because the
+## WWW-Authenticate and Proxy-Authenticate headers are parsed in the
+## post-read-request phase and it needs to know if this is a proxy request.
+
+# AddModule modules/experimental/mod_auth_digest.o
+
+## Optional Proxy
+##
+## The proxy module enables the server to act as a proxy for outside
+## http and ftp services. It's not as complete as it could be yet.
+## NOTE: You do not want this module UNLESS you are running a proxy;
+## it is not needed for normal (origin server) operation.
+
+# AddModule modules/proxy/libproxy.a
+
## Optional response header manipulation modules.
##
## cern_meta mimics the behavior of the CERN web server with regards to
diff --git a/usr.sbin/httpd/src/Configure b/usr.sbin/httpd/src/Configure
index b3b36170a9b..307bfc4b21b 100644
--- a/usr.sbin/httpd/src/Configure
+++ b/usr.sbin/httpd/src/Configure
@@ -64,6 +64,7 @@
# fp2rp:
# slo.sh:
+LANG=C; export LANG
exitcode=0
trap 'rm -f $tmpfile $tmpfile2 $tmpfile3 $tmpconfig $awkfile; exit $exitcode' 0 1 2 3 15
@@ -76,7 +77,8 @@ tmpfile2=$tmpfile.2
tmpfile3=$tmpfile.3
awkfile=$tmpfile.4
tmpconfig=$tmpfile.5
-SUBDIRS="ap main modules"
+SUBDIRS="ap main"
+APLIBDIRS=""
####################################################################
## Now handle any arguments, which, for now, is -file
@@ -90,12 +92,6 @@ while [ "x$1" != "x" ]; do
exitcode=1
exit 1
fi
- elif [ "x$1" = "x-make" ] ; then
- shift 1; makefile_tmpl=$1; shift 1
- if [ ! -r $makefile_tmpl ]; then
- echo "$makefile_tmpl does not exist or is not readable."
- exit 1
- fi
else
echo "ERROR: Bad command line option '$1'"
echo " Please read the file INSTALL."
@@ -114,7 +110,7 @@ fi
## Now see if Configuration.tmpl is more recent than $file. If
## so, then we complain and bail out
##
-if ls -lt Configuration.tmpl $file | head -1 | \
+if ls -lt $file Configuration.tmpl | head -1 | \
grep 'Configuration.tmpl' > /dev/null
then
echo "Configuration.tmpl is more recent than $file;"
@@ -178,7 +174,7 @@ fi
## that the user was using the old default root directory
## and issue a notice about it.
##
-if [ $file != "Configuration.apaci" ]
+if [ "x$file" != "xConfiguration.apaci" ]
then
if [ -d /usr/local/etc/httpd/ ]
then
@@ -228,14 +224,14 @@ RULE_SOCKS5=`./helpers/CutRule SOCKS5 $file`
RULE_IRIXNIS=`./helpers/CutRule IRIXNIS $file`
RULE_IRIXN32=`./helpers/CutRule IRIXN32 $file`
RULE_PARANOID=`./helpers/CutRule PARANOID $file`
-RULE_EAPI=`./helpers/CutRule EAPI $file`
+RULE_EXPAT=`./helpers/CutRule EXPAT $file`
RULE_SHARED_CORE=`./helpers/CutRule SHARED_CORE $file`
RULE_SHARED_CHAIN=`./helpers/CutRule SHARED_CHAIN $file`
####################################################################
## Rule SHARED_CORE implies required DSO support
##
-if [ "$RULE_SHARED_CORE" = "yes" ]; then
+if [ "x$RULE_SHARED_CORE" = "xyes" ]; then
using_shlib=1
fi
@@ -316,6 +312,8 @@ case "$PLAT" in
OS='IBM AIX 4.3'
CFLAGS="$CFLAGS -DAIX=43 -U__STR__"
LDFLAGS="$LDFLAGS -lm"
+ RULE_SHARED_CORE=no
+ DEF_SHARED_CORE=no
;;
*-ibm-aix*)
OS='IBM AIX'
@@ -335,8 +333,8 @@ case "$PLAT" in
OSDIR="os/os2"
DEF_WANTHSREGEX=yes
OS='EMX OS/2'
- CFLAGS="$CFLAGS -DOS2 -Zbsd-signals -Zbin-files -DTCPIPV4 -g"
- LDFLAGS="$LDFLAGS -Zexe"
+ CFLAGS="$CFLAGS -DOS2 -DTCPIPV4 -g -Zmt"
+ LDFLAGS="$LDFLAGS -Zexe -Zmtd -Zsysv-signals -Zbin-files"
LIBS="$LIBS -lsocket -lufc -lbsd"
DBM_LIB="-lgdbm"
SHELL=sh
@@ -378,7 +376,7 @@ case "$PLAT" in
echo "but if you would care to port to 64-bit, send us the patches."
DEF_WANTHSREGEX=yes
DBM_LIB=""
- if [ "$RULE_IRIXNIS" = "yes" ]; then
+ if [ "x$RULE_IRIXNIS" = "xyes" ]; then
OS='SGI IRIX-64 w/NIS'
CFLAGS="$CFLAGS -DIRIX"
LIBS="$LIBS -lsun"
@@ -390,14 +388,14 @@ case "$PLAT" in
*-sgi-irix32)
DEF_WANTHSREGEX=yes
DBM_LIB=""
- if [ "$RULE_IRIXN32" = "yes" ]; then
- if [ "$RULE_IRIXNIS" = "yes" ]; then
+ if [ "x$RULE_IRIXN32" = "xyes" ]; then
+ if [ "x$RULE_IRIXNIS" = "xyes" ]; then
OS='SGI IRIX-32 w/NIS'
else
OS='SGI IRIX-32'
fi
else
- if [ "$RULE_IRIXNIS" = "yes" ]; then
+ if [ "x$RULE_IRIXNIS" = "xyes" ]; then
OS='SGI IRIX w/NIS'
else
OS='SGI IRIX'
@@ -409,7 +407,7 @@ case "$PLAT" in
*-sgi-irix)
DEF_WANTHSREGEX=yes
DBM_LIB=""
- if [ "$RULE_IRIXNIS" = "yes" ]; then
+ if [ "x$RULE_IRIXNIS" = "xyes" ]; then
OS='SGI IRIX w/NIS'
CFLAGS="$CFLAGS -DIRIX"
LIBS="$LIBS -lsun"
@@ -441,6 +439,11 @@ case "$PLAT" in
DBM_LIB=""
DB_LIB=""
;;
+ *-bsdi3)
+ if [ "x$using_shlib" = "x1" ] ; then
+ CC="shlicc2"
+ fi
+ ;;
*-bsdi*)
OS='BSDI'
DBM_LIB=""
@@ -458,7 +461,7 @@ case "$PLAT" in
PLATOSVERS=`echo $PLAT | sed 's/^.*freebsd//'`
OS="FreeBSD $PLATOSVERS"
case "$PLATOSVERS" in
- [23]*)
+ [234]*)
DEF_WANTHSREGEX=no
CFLAGS="$CFLAGS -funsigned-char"
;;
@@ -484,14 +487,16 @@ case "$PLAT" in
CC='cc'
OPTIM='-O'
CFLAGS="$CFLAGS -DNEXT"
- CFLAGS_SHLIB='-dynamic -fno-common'
- LD_SHLIB='cc'
- LDFLAGS_SHLIB='-dynamiclib -undefined warning'
DEF_WANTHSREGEX=yes
;;
*-apple-rhapsody*)
OS='Mac OS X Server'
- CFLAGS="$CFLAGS -DRHAPSODY"
+ CFLAGS="$CFLAGS -DMAC_OS_X_SERVER"
+ DEF_WANTHSREGEX=yes
+ ;;
+ *-apple-macos*)
+ OS='Mac OS'
+ CFLAGS="$CFLAGS -DMAC_OS"
DEF_WANTHSREGEX=yes
;;
*-dec-osf*)
@@ -600,6 +605,7 @@ case "$PLAT" in
LIBS="$LIBS -lsocket -lnsl -lgen"
LD_SHLIB='cc'
LDFLAGS_SHLIB="-Zlink=so"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT="-Zlink=dynamic -Wl,-Bexport"
CFLAGS_SHLIB='-Zpic'
;;
@@ -615,10 +621,9 @@ case "$PLAT" in
BS2000*-siemens-sysv4*)
OS='BS2000'
OSDIR='os/bs2000'
- CC='c89 -XLLML -XLLMK'
+ CC='c89 -XLLML -XLLMK -XL'
CFLAGS="$CFLAGS -DCHARSET_EBCDIC -DSVR4 -D_XPG_IV"
DEF_WANTHSREGEX=yes
- LIBS="$LIBS -lsocket -lnsl -lc"
DBM_LIB=""
;;
*-siemens-sysv4*)
@@ -696,10 +701,41 @@ case "$PLAT" in
OS='Paragon OSF/1'
CFLAGS="$CFLAGS -DPARAGON"
;;
- *DYNIX*)
+ *-sequent-ptx2.*.*)
+ DEF_WANTHSREGEX=yes
+ OS='SEQUENT DYNIX/ptx v2.*.*'
+ CFLAGS="$CFLAGS -DSEQUENT=20 -Wc,-pw"
+ LIBS="$LIBS -lsocket -linet -lnsl -lc -lseq"
+ ;;
+ *-sequent-ptx4.0.*)
+ DEF_WANTHSREGEX=yes
+ OS='SEQUENT DYNIX/ptx v4.0.*'
+ CFLAGS="$CFLAGS -DSEQUENT=40 -Wc,-pw"
+ LIBS="$LIBS -lsocket -linet -lnsl -lc"
+ ;;
+ *-sequent-ptx4.[123].*)
+ DEF_WANTHSREGEX=yes
+ OS='SEQUENT DYNIX/ptx v4.1.*/v4.2.*'
+ CFLAGS="$CFLAGS -DSEQUENT=41 -Wc,-pw"
+ LIBS="$LIBS -lsocket -lnsl -lc"
+ ;;
+ *-sequent-ptx4.4.*)
+ DEF_WANTHSREGEX=yes
+ OS='SEQUENT DYNIX/ptx v4.4.*'
+ CFLAGS="$CFLAGS -DSEQUENT=44 -Wc,-pw"
+ LIBS="$LIBS -lsocket -lnsl -lc"
+ ;;
+ *-sequent-ptx4.5.*)
+ DEF_WANTHSREGEX=yes
+ OS='SEQUENT DYNIX/ptx v4.5.*'
+ CFLAGS="$CFLAGS -DSEQUENT=45 -Wc,-pw"
+ LIBS="$LIBS -lsocket -lnsl -lc"
+ ;;
+ *-sequent-ptx5.0.*)
DEF_WANTHSREGEX=yes
- OS='SEQUENT'
- CFLAGS="$CFLAGS -DSEQUENT"
+ OS='SEQUENT DYNIX/ptx v5.0.*'
+ CFLAGS="$CFLAGS -DSEQUENT=50 -Wc,-pw"
+ LIBS="$LIBS -lsocket -lnsl -lc"
;;
*NEWS-OS*)
DEF_WANTHSREGEX=yes
@@ -737,6 +773,11 @@ case "$PLAT" in
CC='cc'
RANLIB='true'
;;
+ *-tandem-oss)
+ OS='Tandem OSS'
+ CFLAGS="-D_TANDEM_SOURCE -D_XOPEN_SOURCE_EXTENDED=1"
+ CC='c89'
+ ;;
*) # default: Catch systems we don't know about
OS='Unknown and unsupported OS'
echo Sorry, but we cannot grok \"$PLAT\"
@@ -788,7 +829,7 @@ echo >>Makefile.config "SHELL=$SHELL"
####################################################################
## And adjust/override WANTHSREGEX as needed
##
-if [ "$RULE_WANTHSREGEX" = "default" ]; then
+if [ "x$RULE_WANTHSREGEX" = "xdefault" ]; then
if [ "x$DEF_WANTHSREGEX" = "x" ]; then
RULE_WANTHSREGEX=yes
else
@@ -915,6 +956,7 @@ TTARGET=`egrep '^TARGET=' Makefile.config | tail -1 | awk -F= '{print $2}'`
##
TLD_SHLIB=`egrep '^LD_SHLIB=' Makefile.config | tail -1 | awk -F= '{print $2}'`
TLDFLAGS_SHLIB=`egrep '^LDFLAGS_SHLIB=' Makefile.config | tail -1 | awk -F= '{print $2}'`
+TLDFLAGS_MOD_SHLIB=`egrep '^LDFLAGS_MOD_SHLIB=' Makefile.config | tail -1 | awk -F= '{print $2}'`
TLDFLAGS_SHLIB_EXPORT=`egrep '^LDFLAGS_SHLIB_EXPORT=' Makefile.config | tail -1 | awk -F= '{print $2}'`
TCFLAGS_SHLIB=`egrep '^CFLAGS_SHLIB=' Makefile.config | tail -1 | awk -F= '{print $2}'`
@@ -943,27 +985,36 @@ if [ "x$using_shlib" = "x1" ] ; then
SHLIB_SUFFIX_NAME=so
SHLIB_SUFFIX_DEPTH=all
SHLIB_EXPORT_FILES=no
+ SHARED_CORE_EP='lib$(TARGET).ep'
+ SHCORE_IMPLIB=''
case "$PLAT" in
*-linux1)
CFLAGS_SHLIB="-fpic"
LDFLAGS_SHLIB="-Bshareable"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT="-rdynamic"
;;
*-linux2)
+ LD_SHLIB="gcc"
CFLAGS_SHLIB="-fpic"
- LDFLAGS_SHLIB="-Bshareable"
+ LDFLAGS_SHLIB="-shared"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT="-rdynamic"
SHLIB_SUFFIX_DEPTH=0
;;
*-freebsd2*)
+ LD_SHLIB="gcc"
CFLAGS_SHLIB="-fpic"
- LDFLAGS_SHLIB="-Bshareable"
+ LDFLAGS_SHLIB="-shared"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT=""
SHLIB_SUFFIX_DEPTH=2
;;
- *-freebsd3*)
+ *-freebsd3*|*-freebsd4*)
+ LD_SHLIB="gcc"
CFLAGS_SHLIB="-fpic"
- LDFLAGS_SHLIB="-Bshareable"
+ LDFLAGS_SHLIB="-shared"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
OBJFORMAT=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
if [ "x$OBJFORMAT" = "xelf" ]; then
LDFLAGS_SHLIB_EXPORT="-Wl,-E"
@@ -976,48 +1027,67 @@ if [ "x$using_shlib" = "x1" ] ; then
*-openbsd*)
CFLAGS_SHLIB="-fPIC"
LDFLAGS_SHLIB="-Bforcearchive -Bshareable"
- LDFLAGS_SHLIB_EXPORT=""
- SHLIB_SUFFIX_DEPTH=2
- ;;
- alpha-*-netbsd*|mips-*-netbsd*|powerpc-*-netbsd*)
- CFLAGS_SHLIB="-fpic -DPIC"
- LDFLAGS_SHLIB="-shared"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT=""
SHLIB_SUFFIX_DEPTH=2
;;
*-netbsd*)
- CFLAGS_SHLIB="-fpic -DPIC"
- LDFLAGS_SHLIB="-Bshareable"
- LDFLAGS_SHLIB_EXPORT=""
+ CFLAGS_SHLIB="-fPIC -DPIC"
+ if echo __ELF__ | ${CC} -E - | grep -q __ELF__; then
+ LDFLAGS_SHLIB="-Bshareable"
+ LDFLAGS_SHLIB_EXPORT=""
+ else
+ LDFLAGS_SHLIB="-shared"
+ LDFLAGS_SHLIB_EXPORT="-Wl,-E"
+ fi
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
SHLIB_SUFFIX_DEPTH=2
;;
+ *-bsdi3)
+ LD_SHLIB="shlicc2"
+ LDFLAGS_SHLIB="-r"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ ;;
*-bsdi)
CFLAGS_SHLIB="-fPIC"
LDFLAGS_SHLIB="-shared"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT="-rdynamic"
;;
- *-apple-rhapsody*)
+ *-next-openstep*)
+ LD_SHLIB='cc'
+ CFLAGS_SHLIB='-dynamic -fno-common'
+ LDFLAGS_SHLIB='-bundle -undefined warning'
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=''
+ SHLIB_SUFFIX_DEPTH=0
+ ;;
+ *-apple-rhapsody* | *-apple-macos* )
LD_SHLIB="cc"
CFLAGS_SHLIB=""
LDFLAGS_SHLIB='$(EXTRA_LDFLAGS) -bundle -undefined suppress'
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT=""
SHLIB_SUFFIX_DEPTH=0
;;
*-solaris2*)
- case $CC in
- */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
- */cc|cc ) CFLAGS_SHLIB="-KPIC" ;;
- esac
+ if [ "x`$CC -v 2>&1 | grep gcc`" != "x" ]; then
+ CFLAGS_SHLIB="-fPIC"
+ else
+ CFLAGS_SHLIB="-KPIC"
+ fi
LDFLAGS_SHLIB="-G"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT=""
SHLIB_SUFFIX_DEPTH=1
;;
*-sunos4*)
case $CC in
- */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
+ */gcc|gcc ) CFLAGS_SHLIB="-fPIC" ;;
*/acc|acc ) CFLAGS_SHLIB="-pic" ;;
esac
LDFLAGS_SHLIB="-assert pure-text"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT=""
;;
*-sgi-irix32)
@@ -1031,11 +1101,12 @@ if [ "x$using_shlib" = "x1" ] ; then
N32FLAG="-n32"
;;
esac
- if [ "$RULE_IRIXN32" = "yes" ]; then
+ if [ "x$RULE_IRIXN32" = "xyes" ]; then
LDFLAGS_SHLIB="$N32FLAG -shared"
else
LDFLAGS_SHLIB="-shared"
fi
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT=""
;;
*-sgi-irix64)
@@ -1049,11 +1120,12 @@ if [ "x$using_shlib" = "x1" ] ; then
N32FLAG="-n32"
;;
esac
- if [ "$RULE_IRIXN32" = "yes" ]; then
+ if [ "x$RULE_IRIXN32" = "xyes" ]; then
LDFLAGS_SHLIB="$N32FLAG -shared"
else
LDFLAGS_SHLIB="-shared"
fi
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT=""
;;
*-sgi-irix)
@@ -1062,6 +1134,7 @@ if [ "x$using_shlib" = "x1" ] ; then
*/cc|cc ) CFLAGS_SHLIB="-KPIC" ;;
esac
LDFLAGS_SHLIB="-shared"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT=""
;;
*-dec-osf*)
@@ -1070,6 +1143,7 @@ if [ "x$using_shlib" = "x1" ] ; then
*/cc|cc ) CFLAGS_SHLIB="" ;;
esac
LDFLAGS_SHLIB="-shared -expect_unresolved '*' -s"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT=""
;;
*-unixware*)
@@ -1078,6 +1152,7 @@ if [ "x$using_shlib" = "x1" ] ; then
*/cc|cc ) CFLAGS_SHLIB="-KPIC" ;;
esac
LDFLAGS_SHLIB="-Bdynamic -G"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT="-Wl,-Bexport"
;;
*-sco5*)
@@ -1087,8 +1162,23 @@ if [ "x$using_shlib" = "x1" ] ; then
esac
LDFLAGS_SHLIB="-G"
LDFLAGS_SHLIB_EXPORT="-Wl,-Bexport"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
SHLIB_SUFFIX_DEPTH=1
;;
+ *-sequent-ptx*)
+ case $PLAT in
+ *-sequent-ptx2*)
+ ;;
+ *-sequent-ptx4.0*)
+ ;;
+ *-sequent-ptx*)
+ CFLAGS_SHLIB="-KPIC"
+ LDFLAGS_SHLIB="-G"
+ LDFLAGS_SHLIB_EXPORT="-Wl,-Bexport"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ ;;
+ esac
+ ;;
RM*-siemens-sysv4*)
# MIPS hosts can take advantage of the LDFLAGS_SHLIB_EXPORT switch
case $CC in
@@ -1096,6 +1186,7 @@ if [ "x$using_shlib" = "x1" ] ; then
*/cc|cc ) CFLAGS_SHLIB="-KPIC" ;;
esac
LDFLAGS_SHLIB="-G"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT="-Wl,-Blargedynsym"
;;
*-siemens-sysv4*)
@@ -1105,6 +1196,7 @@ if [ "x$using_shlib" = "x1" ] ; then
*/cc|cc ) CFLAGS_SHLIB="-KPIC" ;;
esac
LDFLAGS_SHLIB="-G"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT=""
SHLIB_SUFFIX_DEPTH=0
DEF_SHARED_CORE=yes
@@ -1115,6 +1207,7 @@ if [ "x$using_shlib" = "x1" ] ; then
*/cc|cc ) CFLAGS_SHLIB="-KPIC" ;;
esac
LDFLAGS_SHLIB="-G"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT=""
DEF_SHARED_CORE=yes
;;
@@ -1124,8 +1217,8 @@ if [ "x$using_shlib" = "x1" ] ; then
*/cc|cc ) CFLAGS_SHLIB="+z" ;;
esac
LDFLAGS_SHLIB="-b"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT="-Wl,-E -Wl,-B,deferred"
- SHLIB_SUFFIX_NAME=sl
;;
*-hp-hpux10.*|*-hp-hpux11.*)
case $CC in
@@ -1133,8 +1226,8 @@ if [ "x$using_shlib" = "x1" ] ; then
*/cc|cc ) CFLAGS_SHLIB="+z" ;;
esac
LDFLAGS_SHLIB="-b"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT="-Wl,-E -Wl,-B,deferred -Wl,+s"
- SHLIB_SUFFIX_NAME=sl
;;
*-ibm-aix*)
case $CC in
@@ -1149,6 +1242,7 @@ if [ "x$using_shlib" = "x1" ] ; then
LDFLAGS_SHLIB="-H512 -T512 -bhalt:4 -bM:SRE -e _nostart"
;;
esac
+ LDFLAGS_MOD_SHLIB="$LDFLAGS_SHLIB -bI:@libexecdir@/httpd.exp -lc"
LDFLAGS_SHLIB="$LDFLAGS_SHLIB -bI:\$(SRCDIR)/support/httpd.exp "
LDFLAGS_SHLIB="$LDFLAGS_SHLIB -bE:\`echo \$@|sed -e 's:\.so\$\$:.exp:'\`"
LDFLAGS_SHLIB="$LDFLAGS_SHLIB -lc"
@@ -1158,9 +1252,33 @@ if [ "x$using_shlib" = "x1" ] ; then
*-*-powermax*)
LD_SHLIB='cc'
LDFLAGS_SHLIB="-Zlink=so"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT="-Zlink=dynamic -Wl,-Bexport"
CFLAGS_SHLIB='-Zpic'
;;
+ *-OS/2*)
+ DEF_SHARED_CORE=yes
+ LDFLAGS_SHLIB="`echo $LDFLAGS|sed -e s/-Zexe//` -Zdll"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ SHLIB_SUFFIX_NAME=dll
+ SHLIB_SUFFIX_DEPTH=0
+ LD_SHLIB=$CC
+ LD_SHCORE_DEF="ApacheCoreOS2.def"
+ LD_SHCORE_LIBS="$LIBS"
+ LIBS_SHLIB='$(SRCDIR)/ApacheCoreOS2.a -lsocket -lbsd $(EXTRA_LIBS)'
+ SHARED_CORE_EP=''
+ SHCORE_IMPLIB='ApacheCoreOS2.a'
+ OS_MODULE_INCLUDE='Makefile.OS2'
+ ;;
+ *-dgux)
+ case $CC in
+ */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
+ esac
+ DEF_SHARED_CORE=yes
+ LDFLAGS_SHLIB="-G"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
+ LDFLAGS_SHLIB_EXPORT=""
+ ;;
*)
## ok, no known explict support for shared objects
## on this platform, but we give not up immediately.
@@ -1186,6 +1304,7 @@ if [ "x$using_shlib" = "x1" ] ; then
# so we can guess the flags from its knowledge
CFLAGS_SHLIB="`$PERL -V:cccdlflags | cut -d\' -f2`"
LDFLAGS_SHLIB="`$PERL -V:lddlflags | cut -d\' -f2`"
+ LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
LDFLAGS_SHLIB_EXPORT="`$PERL -V:ccdlflags | cut -d\' -f2`"
# but additionally we have to inform the
# user that we are just guessing the flags
@@ -1263,7 +1382,7 @@ case "$OS" in
esac
;;
*IRIX-64*)
- if [ "$RULE_IRIXN32" = "yes" ]; then
+ if [ "x$RULE_IRIXN32" = "xyes" ]; then
case "$CC" in
*/cc|cc )
CFLAGS="$CFLAGS -n32"
@@ -1273,7 +1392,7 @@ case "$OS" in
fi
;;
*IRIX-32*)
- if [ "$RULE_IRIXN32" = "yes" ]; then
+ if [ "x$RULE_IRIXN32" = "xyes" ]; then
case "$CC" in
*/cc|cc )
CFLAGS="$CFLAGS -n32"
@@ -1329,11 +1448,30 @@ case "$PLAT" in
*-dg-dgux*)
# R4.11MU02 requires -lsocket -lnsl ... no idea if it's earlier or
# later than what we already knew about. PR#732
- if ./helpers/TestCompile lib socket; then
- LIBS="$LIBS -lsocket"
+ if ./helpers/TestCompile lib nsl; then
+ LIBS="$LIBS -lnsl"
+ TLIB='-lnsl'
fi
+ if TLIB=$TLIB ./helpers/TestCompile lib socket; then
+ LIBS="-lsocket $LIBS"
+ fi
+ ;;
+ BS2000*-siemens-sysv4*)
+ # Depending on the BS2000 OS and compiler/crte release,
+ # -lnsl may be available (or may be not).
+ # In standard SVR4 systems, -lsocket relies on some symbols
+ # from -lnsl, so the test for -lnsl must appear first.
if ./helpers/TestCompile lib nsl; then
LIBS="$LIBS -lnsl"
+ TLIB='-lnsl'
+ fi
+ if TLIB=$TLIB ./helpers/TestCompile lib socket; then
+ LIBS="-lsocket $LIBS"
+ fi
+ if ./helpers/TestCompile func initgroups; then
+ :
+ else
+ CFLAGS="$CFLAGS -DNEED_INITGROUPS"
fi
;;
esac
@@ -1342,7 +1480,7 @@ esac
# We assume that if they are using SOCKS4, then they've
# adjusted EXTRA_LIBS and/or EXTRA_LDFLAGS as required,
# otherwise we assume "-L/usr/local/lib -lsocks"
-if [ "$RULE_SOCKS4" = "yes" ]; then
+if [ "x$RULE_SOCKS4" = "xyes" ]; then
echo " + enabling SOCKS4 support"
CFLAGS="$CFLAGS -DSOCKS -DSOCKS4"
CFLAGS="$CFLAGS -Dconnect=Rconnect -Dselect=Rselect"
@@ -1361,7 +1499,7 @@ fi
# We assume that if they are using SOCKS5, then they've
# adjusted EXTRA_LIBS and/or EXTRA_LDFLAGS as required,
# otherwise we assume "-L/usr/local/lib -lsocks5"
-if [ "$RULE_SOCKS5" = "yes" ]; then
+if [ "x$RULE_SOCKS5" = "xyes" ]; then
echo " + enabling SOCKS5 support"
CFLAGS="$CFLAGS -DSOCKS -DSOCKS5"
CFLAGS="$CFLAGS -Dconnect=SOCKSconnect -Dselect=SOCKSselect"
@@ -1504,13 +1642,18 @@ for modfile in $MODFILES ; do
sed '1,/ConfigStart/d;/ConfigEnd/,$d' $tmpfile2 > \
$tmpfile3
echo " o $modname uses ConfigStart/End"
- if [ "$RULE_PARANOID" = "yes" ]; then
+ if [ "x$RULE_PARANOID" = "xyes" ]; then
sed 's/^/>> /' $tmpfile3
fi
. ./$tmpfile3
fi
+ if grep "Libs:" $tmpfile2 > /dev/null; then
+ modlibs1=`grep Libs: $tmpfile2 | sed 's/^.*Libs:[ ]*//'`
+ echo " o $modbase adds libraries: $modlibs1"
+ modlibs="$modlibs $modlibs1"
+ fi
rm -f $tmpfile2 $tmpfile3
- if [ "$ext" != "so" ]; then
+ if [ "x$ext" != "x$SHLIB_SUFFIX_NAME" ]; then
ext=o
fi
fi
@@ -1518,11 +1661,11 @@ for modfile in $MODFILES ; do
modname=`echo $modbase | sed 's/^.*\///' | \
sed 's/^mod_//' | sed 's/^lib//' | sed 's/$/_module/'`
fi
- if [ "$ext" != "so" ]; then
+ if [ "x$ext" != "x$SHLIB_SUFFIX_NAME" ]; then
echo "Module $modname $modbase.$ext" >>$tmpfile
fi
# optionally generate export file for some linkers
- if [ "$ext" = "so" -a "$SHLIB_EXPORT_FILES" = "yes" ]; then
+ if [ "x$ext" = "x$SHLIB_SUFFIX_NAME" -a "x$SHLIB_EXPORT_FILES" = "xyes" ]; then
echo "$modname" >$modbase.exp
fi
done
@@ -1532,34 +1675,107 @@ done
## Now HS's POSIX regex implementation if needed/wanted. We do it
## now since AddModule may have changed it
##
-if [ "$RULE_WANTHSREGEX" = "yes" ]; then
+if [ "x$RULE_WANTHSREGEX" = "xyes" ]; then
REGLIB="regex/libregex.a"
SUBDIRS="regex $SUBDIRS"
CFLAGS="$CFLAGS -DUSE_HSREGEX"
fi
####################################################################
-# Extended API support:
-if [ "$RULE_EAPI" = "yes" ]; then
+## Extended API (EAPI) support:
+##
+if [ "x$RULE_EAPI" = "x" ]; then
+ RULE_EAPI=`./helpers/CutRule EAPI $file`
+fi
+if [ "x$RULE_EAPI" = "xyes" ]; then
echo " + enabling Extended API (EAPI)"
CFLAGS="$CFLAGS -DEAPI"
# some vendor compilers are too restrictive
+ # for our ap_hook and ap_ctx sources.
case "$OS:$CC" in
*IRIX-32*:*/cc|*IRIX-32*:cc )
CFLAGS="$CFLAGS -woff 1048,1110,1164"
;;
esac
+ # MM Shared Memory Library support for EAPI
+ if [ "x$EAPI_MM" = "x" ]; then
+ EAPI_MM=`egrep '^EAPI_MM=' $file | tail -1 | awk -F= '{print $2}'`
+ fi
+ if [ "x$EAPI_MM" != "x" ]; then
+ case $EAPI_MM in
+ SYSTEM|/* ) ;;
+ * ) for p in . .. ../..; do
+ if [ -d "$p/$EAPI_MM" ]; then
+ EAPI_MM="`echo $p/$EAPI_MM | sed -e 's;/\./;/;g'`"
+ break
+ fi
+ done
+ ;;
+ esac
+ if [ "x$EAPI_MM" = "xSYSTEM" ]; then
+ echo " using MM library for EAPI: (system-wide)"
+ CFLAGS="$CFLAGS -DEAPI_MM"
+ __INCLUDES="`mm-config --cflags`"
+ if [ "x$__INCLUDES" != "x-I/usr/include" ]; then
+ INCLUDES="$INCLUDES $__INCLUDES"
+ fi
+ LDFLAGS="$LDFLAGS `mm-config --ldflags`"
+ LIBS="$LIBS `mm-config --libs`"
+ else
+ if [ -f "$EAPI_MM/.libs/libmm.a" -a -f "$EAPI_MM/mm.h" ]; then
+ echo " using MM library: $EAPI_MM (source-tree only)"
+ case $EAPI_MM in
+ /* ) ;;
+ * ) EAPI_MM="\$(SRCDIR)/$EAPI_MM" ;;
+ esac
+ CFLAGS="$CFLAGS -DEAPI_MM"
+ INCLUDES="$INCLUDES -I$EAPI_MM"
+ LDFLAGS="$LDFLAGS -L$EAPI_MM/.libs"
+ LIBS="$LIBS -lmm"
+ elif [ -f "$EAPI_MM/bin/mm-config" ]; then
+ echo " using MM library: $EAPI_MM (installed)"
+ CFLAGS="$CFLAGS -DEAPI_MM"
+ INCLUDES="$INCLUDES `$EAPI_MM/bin/mm-config --cflags`"
+ LDFLAGS="$LDFLAGS `$EAPI_MM/bin/mm-config --ldflags`"
+ LIBS="$LIBS `$EAPI_MM/bin/mm-config --libs`"
+ else
+ echo "Configure:Error: Cannot find MM library under $EAPI_MM" 1>&2
+ exit 1
+ fi
+ fi
+ fi
+fi
+
+
+####################################################################
+## Add in the Expat library if needed/wanted.
+##
+if [ -d ./lib/expat-lite/ ]; then
+ if [ "x$RULE_EXPAT" = "xdefault" ]; then
+ RULE_EXPAT=yes
+ fi
+else
+ if [ "$xRULE_EXPAT" = "xyes" ]; then
+ echo "ERROR: RULE_EXPAT set to \"yes\" but is not available."
+ exit 1
+ else
+ RULE_EXPAT=no
+ fi
+fi
+if [ "x$RULE_EXPAT" = "xyes" ]; then
+ EXPATLIB="lib/expat-lite/libexpat.a"
+ APLIBDIRS="expat-lite $APLIBDIRS"
+ CFLAGS="$CFLAGS -DUSE_EXPAT -I\$(SRCDIR)/lib/expat-lite"
fi
####################################################################
## Now the SHARED_CHAIN stuff
##
-LIBS_SHLIB=''
if [ "x$using_shlib" = "x1" ] ; then
- if [ "$RULE_SHARED_CHAIN" = "default" ] ; then
+ if [ "x$RULE_SHARED_CHAIN" = "xdefault" ] ; then
RULE_SHARED_CHAIN=$DEF_SHARED_CHAIN
fi
- if [ "$RULE_SHARED_CHAIN" = "yes" ]; then
+ if [ "x$RULE_SHARED_CHAIN" = "xyes" ]; then
echo " + enabling DSO files to be linked against others"
# determine libraries which can be safely linked
# to our DSO files, i.e. PIC libraries and shared libraries
@@ -1574,10 +1790,10 @@ fi
## Now the SHARED_CORE stuff
##
if [ "x$using_shlib" = "x1" ] ; then
- if [ "$RULE_SHARED_CORE" = "default" ] ; then
+ if [ "x$RULE_SHARED_CORE" = "xdefault" ] ; then
RULE_SHARED_CORE=$DEF_SHARED_CORE
fi
- if [ "$RULE_SHARED_CORE" = "yes" ]; then
+ if [ "x$RULE_SHARED_CORE" = "xyes" ]; then
echo " + enabling generation of Apache core as DSO"
# shuffle compiler flags from shlib variant to standard
CFLAGS="$CFLAGS $CFLAGS_SHLIB"
@@ -1587,20 +1803,20 @@ if [ "x$using_shlib" = "x1" ] ; then
# select the special subtarget for shared core generation
SUBTARGET=target_shared
# determine additional suffixes for libhttpd.so
- V=1 R=3 P=4
- if [ "$SHLIB_SUFFIX_DEPTH" = "0" ]; then
+ V=1 R=3 P=9
+ if [ "x$SHLIB_SUFFIX_DEPTH" = "x0" ]; then
SHLIB_SUFFIX_LIST=""
fi
- if [ "$SHLIB_SUFFIX_DEPTH" = "1" ]; then
+ if [ "x$SHLIB_SUFFIX_DEPTH" = "x1" ]; then
SHLIB_SUFFIX_LIST="$V"
fi
- if [ "$SHLIB_SUFFIX_DEPTH" = "2" ]; then
+ if [ "x$SHLIB_SUFFIX_DEPTH" = "x2" ]; then
SHLIB_SUFFIX_LIST="$V.$R"
fi
- if [ "$SHLIB_SUFFIX_DEPTH" = "3" ]; then
+ if [ "x$SHLIB_SUFFIX_DEPTH" = "x3" ]; then
SHLIB_SUFFIX_LIST="$V.$R.$P"
fi
- if [ "$SHLIB_SUFFIX_DEPTH" = "all" ]; then
+ if [ "x$SHLIB_SUFFIX_DEPTH" = "xall" ]; then
SHLIB_SUFFIX_LIST="$V $V.$R $V.$R.$P"
fi
fi
@@ -1623,6 +1839,13 @@ if [ "x$using_shlib" = "x1" ] ; then
if [ "x$TLDFLAGS_SHLIB_EXPORT" = "x" ]; then
echo "LDFLAGS_SHLIB_EXPORT=$LDFLAGS_SHLIB_EXPORT" >> Makefile.config
fi
+ if [ "x$TLDFLAGS_MOD_SHLIB" = "x" ]; then
+ echo "LDFLAGS_MOD_SHLIB=$LDFLAGS_MOD_SHLIB" >> Makefile.config
+ fi
+ echo "LD_SHCORE_DEF=$LD_SHCORE_DEF" >> Makefile.config
+ echo "LD_SHCORE_LIBS=$LD_SHCORE_LIBS" >> Makefile.config
+ echo "SHARED_CORE_EP=$SHARED_CORE_EP" >> Makefile.config
+ echo "SHCORE_IMPLIB=$SHCORE_IMPLIB" >> Makefile.config
fi
####################################################################
@@ -1763,10 +1986,11 @@ echo "" >>Makefile
####################################################################
## Now add the target for the main Makefile
##
-echo "SUBDIRS=$SUBDIRS" >> Makefile
+echo "SUBDIRS=$SUBDIRS lib modules" >> Makefile
echo "SUBTARGET=$SUBTARGET" >> Makefile
echo "SHLIB_SUFFIX_NAME=$SHLIB_SUFFIX_NAME" >> Makefile
echo "SHLIB_SUFFIX_LIST=$SHLIB_SUFFIX_LIST" >> Makefile
+echo "SHLIB_EXPORT_FILES=$SHLIB_EXPORT_FILES" >> Makefile
echo "" >> Makefile
####################################################################
@@ -1791,6 +2015,7 @@ echo "LIBS_SHLIB=$LIBS_SHLIB" >>Makefile.config
echo "LDFLAGS1=$LDFLAGS" >>Makefile.config
echo "MFLAGS_STATIC=$MFLAGS_STATIC" >>Makefile.config
echo "REGLIB=$REGLIB" >>Makefile.config
+echo "EXPATLIB=$EXPATLIB" >>Makefile.config
echo "RANLIB=$RANLIB" >>Makefile.config
####################################################################
@@ -1803,6 +2028,17 @@ if [ "x$using_shlib" = "x1" ] ; then
*-ibm-aix* )
DL_LIB="-lld"
;;
+ *-sequent-ptx* )
+ case $PLAT in
+ *-sequent-ptx2*)
+ ;;
+ *-sequent-ptx4.0*)
+ ;;
+ *-sequent-ptx*)
+ DL_LIB="-ldl"
+ ;;
+ esac
+ ;;
*-hp-hpux*)
if ./helpers/TestCompile func shl_load; then
:
@@ -1829,6 +2065,93 @@ if [ "x$using_shlib" = "x1" ] ; then
fi
####################################################################
+## More building ap_config_auto.h
+##
+## We check the sizeof various data types
+##
+echo " + checking sizeof various data types"
+AP_TYPE_QUAD=`./helpers/TestCompile -r sizeof 'long long'`
+if [ "x$AP_TYPE_QUAD" = "x" ]; then
+ AP_TYPE_QUAD="unknown_quad"
+ AP_LONGEST_LONG="long"
+else
+ AP_LONGEST_LONG="long long"
+fi
+
+echo "" >>$AP_CONFIG_AUTO_H
+echo "/* determine: longest possible integer type */" >>$AP_CONFIG_AUTO_H
+echo "#ifndef AP_LONGEST_LONG" >>$AP_CONFIG_AUTO_H
+echo "#define AP_LONGEST_LONG $AP_LONGEST_LONG" >>$AP_CONFIG_AUTO_H
+echo "#endif" >>$AP_CONFIG_AUTO_H
+
+####################################################################
+## More building ap_config_auto.h
+##
+## We check for the endianess of the machine
+##
+AP_BYTE_ORDER=`./helpers/TestCompile -r byteorder`
+if [ "x$AP_BYTE_ORDER" = "x21" ]; then
+ AP_BYTE_ORDER="21" # big endian
+else
+ AP_BYTE_ORDER="12" # little endian
+fi
+
+echo "" >>$AP_CONFIG_AUTO_H
+echo "/* determine: byte order of machine (12: little endian, 21: big endian) */" >>$AP_CONFIG_AUTO_H
+echo "#ifndef AP_BYTE_ORDER" >>$AP_CONFIG_AUTO_H
+echo "#define AP_BYTE_ORDER $AP_BYTE_ORDER" >>$AP_CONFIG_AUTO_H
+echo "#endif" >>$AP_CONFIG_AUTO_H
+
+##
+## Now compare the sizes of off_t to long
+##
+AP_TYPE_OFF_T=`./helpers/TestCompile -r sizeof off_t`
+if [ "x$AP_TYPE_OFF_T" = "x" ]; then
+ AP_TYPE_OFF_T="unknown_off_t"
+fi
+
+AP_TYPE_LONG=`./helpers/TestCompile -r sizeof long`
+if [ "x$AP_TYPE_LONG" = "x" ]; then
+ AP_TYPE_LONG="unknown_long"
+fi
+
+if [ "x$AP_TYPE_OFF_T" != "x$AP_TYPE_LONG" ]; then
+ echo "" >>$AP_CONFIG_AUTO_H
+ echo "/* determine: is off_t a quad */" >>$AP_CONFIG_AUTO_H
+ echo "#ifndef AP_OFF_T_IS_QUAD" >>$AP_CONFIG_AUTO_H
+ echo "#define AP_OFF_T_IS_QUAD 1" >>$AP_CONFIG_AUTO_H
+ echo "#endif" >>$AP_CONFIG_AUTO_H
+else
+ echo "" >>$AP_CONFIG_AUTO_H
+ echo "/* determine: is off_t a quad */" >>$AP_CONFIG_AUTO_H
+ echo "#ifndef AP_OFF_T_IS_QUAD" >>$AP_CONFIG_AUTO_H
+ echo "#undef AP_OFF_T_IS_QUAD" >>$AP_CONFIG_AUTO_H
+ echo "#endif" >>$AP_CONFIG_AUTO_H
+fi
+
+##
+## Now see of void * is as big as a quad (long long)
+##
+AP_TYPE_VOID_P=`./helpers/TestCompile -r sizeof 'void *'`
+if [ "x$AP_TYPE_VOID_P" = "x" ]; then
+ AP_TYPE_VOID_P="unknown_void_p"
+fi
+
+if [ "x$AP_TYPE_VOID_P" = "x$AP_TYPE_QUAD" ]; then
+ echo "" >>$AP_CONFIG_AUTO_H
+ echo "/* determine: is void * a quad */" >>$AP_CONFIG_AUTO_H
+ echo "#ifndef AP_VOID_P_IS_QUAD" >>$AP_CONFIG_AUTO_H
+ echo "#define AP_VOID_P_IS_QUAD 1" >>$AP_CONFIG_AUTO_H
+ echo "#endif" >>$AP_CONFIG_AUTO_H
+else
+ echo "" >>$AP_CONFIG_AUTO_H
+ echo "/* determine: is void * a quad */" >>$AP_CONFIG_AUTO_H
+ echo "#ifndef AP_VOID_P_IS_QUAD" >>$AP_CONFIG_AUTO_H
+ echo "#undef AP_VOID_P_IS_QUAD" >>$AP_CONFIG_AUTO_H
+ echo "#endif" >>$AP_CONFIG_AUTO_H
+fi
+
+####################################################################
## Finish building ap_config_auto.h
##
## We pick out all -D's from CFLAGS and insert them as defines into
@@ -1838,14 +2161,13 @@ fi
TEXTRA_CFLAGS=`egrep '^EXTRA_CFLAGS=' Makefile.config | tail -1 |\
sed -e 's;^EXTRA_CFLAGS=;;' -e 's;\`.*\`;;'`
tmpstr=`echo $CFLAGS $TEXTRA_CFLAGS |\
- sed -e 's;[ ]-;!-;g' -e 's/\\\"/\"/g' -e 's/\([^\\]\)"/\1/g'`
+ sed -e 's;[ ]\([+-]\);!\1;g' -e 's/\([^\\\]\)"/\1/g' -e 's/\\\"/\"/g'`
OIFS="$IFS"
IFS='!'
for cflag in $tmpstr; do
echo "$cflag" >>$tmpconfig
done
IFS="$OIFS"
-if [ -r $tmpconfig ]; then
awk >>$AP_CONFIG_AUTO_H <$tmpconfig '
/^-D.*/ {
i = index($0, "=")
@@ -1861,7 +2183,6 @@ awk >>$AP_CONFIG_AUTO_H <$tmpconfig '
printf ("#ifndef %s\n#define %s %s\n#endif\n", define, define, value)
}
'
-fi
# finish header file
echo "" >>$AP_CONFIG_AUTO_H
@@ -1870,7 +2191,7 @@ echo "#endif /* AP_CONFIG_AUTO_H */" >>$AP_CONFIG_AUTO_H
####################################################################
## Finish creating the Makefile.config file
##
-echo "LIBS1=$LIBS">> Makefile.config
+echo "LIBS1=$modlibs $LIBS">> Makefile.config
echo "##" >> Makefile.config
echo "## (End of automatically generated section)">> Makefile.config
echo "##" >> Makefile.config
@@ -1881,7 +2202,7 @@ echo "" >> Makefile.config
## check
##
-if [ "$OS" = "TPF" ] ; then
+if [ "x$OS" = "xTPF" ] ; then
:
else
echo " + doing sanity check on compiler and options"
@@ -1908,7 +2229,7 @@ $CAT Makefile.config >> Makefile
sed -e "s#@@Configuration@@#$file#" "Makefile.tmpl" >>Makefile
# xxx/Makefile
-MAKEDIRS="support main ap regex $OSDIR"
+MAKEDIRS="support $SUBDIRS"
for dir in $MAKEDIRS ; do
echo Creating Makefile in $dir
./helpers/mfhead $dir $file > $dir/Makefile
@@ -1917,6 +2238,40 @@ for dir in $MAKEDIRS ; do
done
####################################################################
+## Now create the lib/Makefile
+##
+./helpers/mfhead modules $file > lib/Makefile
+$CAT Makefile.config | sed -e 's:^SRCDIR=.*:SRCDIR=..:' >> lib/Makefile
+
+$CAT << EOF >> lib/Makefile
+APLIBS=$APLIBDIRS
+CFLAGS=\$(OPTIM) \$(CFLAGS1) \$(EXTRA_CFLAGS)
+
+default: all
+
+all clean distclean depend ::
+ @for i in \$(APLIBS) ""; do \\
+ if [ "x\$\$i" != "x" ]; then \\
+ echo "===> \$(SDP)lib/\$\$i"; \\
+ (cd \$\$i && \$(MAKE) \$(MFLAGS_STATIC) SDP='\$(SDP)' CC='\$(CC)' AUX_CFLAGS='\$(CFLAGS)' RANLIB='\$(RANLIB)' \$@) || exit 1; \\
+ echo "<=== \$(SDP)lib/\$\$i"; \\
+ fi; \\
+ done
+
+EOF
+
+####################################################################
+## Now create the lib/xxx/Makefile
+##
+
+for dir in $APLIBDIRS ; do
+ echo Creating Makefile in lib/$dir
+ ./helpers/mfhead lib/$dir $file > lib/$dir/Makefile
+ $CAT Makefile.config lib/$dir/Makefile.tmpl |\
+ sed -e "s:^SRCDIR=.*:SRCDIR=`./helpers/fp2rp lib/$dir`:" >> lib/$dir/Makefile
+done
+
+####################################################################
## Now create the modules/Makefile
##
./helpers/mfhead modules $file > modules/Makefile
@@ -1929,10 +2284,12 @@ CFLAGS=\$(OPTIM) \$(CFLAGS1) \$(EXTRA_CFLAGS)
default: all
all clean distclean depend ::
- @for i in \$(MODULES); do \\
+ @for i in \$(MODULES) ""; do \\
+ if [ "x\$\$i" != "x" ]; then \\
echo "===> \$(SDP)modules/\$\$i"; \\
(cd \$\$i && \$(MAKE) \$(MFLAGS_STATIC) SDP='\$(SDP)' CC='\$(CC)' AUX_CFLAGS='\$(CFLAGS)' RANLIB='\$(RANLIB)' \$@) || exit 1; \\
echo "<=== \$(SDP)modules/\$\$i"; \\
+ fi; \\
done
EOF
@@ -2011,7 +2368,7 @@ dummy $(LIB): $(OBJS)
ar cr $@ $(OBJS)
$(RANLIB) $@
-.SUFFIXES: .o .so
+.SUFFIXES: .o .so .dll
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $<
@@ -2039,6 +2396,10 @@ depend:
EOF
fi
+ if [ "x$OS_MODULE_INCLUDE" != "x" ]; then
+ echo "include $OS_MODULE_INCLUDE" >> $moddir/Makefile
+ fi
+
$CAT << 'EOF' >> $moddir/Makefile
##
## (End of automatically generated section)
diff --git a/usr.sbin/httpd/src/Makefile.bsd-wrapper b/usr.sbin/httpd/src/Makefile.bsd-wrapper
deleted file mode 100644
index 7de03ccf79a..00000000000
--- a/usr.sbin/httpd/src/Makefile.bsd-wrapper
+++ /dev/null
@@ -1,64 +0,0 @@
-# $OpenBSD: Makefile.bsd-wrapper,v 1.12 1999/03/08 17:42:42 beck Exp $
-.include <bsd.own.mk>
-PROG=httpd
-BINDIR=/usr/sbin
-BINOWN=root
-BINGRP=daemon
-#MAN= httpd.8
-
-all: Makefile
- ${MAKE}
-
-.FORCE: .IGNORE
-
-helpers/GuessOS:
- /usr/bin/lndir -s -e Makefile.bsd-wrapper -e obj -e obj.${MACHINE_ARCH} -e Configuration ${.CURDIR} ${.OBJDIR}; cp ${.CURDIR}/Configuration ${.OBJDIR}/Configuration
-
-config: .FORCE
- touch ${.OBJDIR}/Configuration
- PATH="/bin:/usr/bin:/sbin:/usr/sbin" \
- CC="${CC}" CFLAGS="${CFLAGS}" \
- sh ${.CURDIR}/Configure -file ${.OBJDIR}/Configuration -make ${.CURDIR}/Makefile.tmpl
-
-Makefile: helpers/GuessOS
- # This is a nasty hack
- @for f in CutRule GuessOS MakeEtags PrintPath TestCompile buildinfo.sh \
- checkheader.sh findcpp.sh fmn.sh fp2rp install.sh mfhead mkdir.sh \
- mkshadow.sh ppl.sh slo.sh; do \
- test -x ${.CURDIR}/helpers/$$f || \
- chmod +x ${.CURDIR}/helpers/$$f ; \
- done
- touch ${.OBJDIR}/Configuration
- PATH="/bin:/usr/bin:/sbin:/usr/sbin" \
- CC="${CC}" CFLAGS="${CFLAGS}" \
- sh ${.CURDIR}/Configure -file ${.OBJDIR}/Configuration -make ${.CURDIR}/Makefile.tmpl
-
-install:
- ${INSTALL} ${INSTALL_COPY} ${INSTALL_STRIP} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} ${PROG} ${DESTDIR}${BINDIR}
-
-clean cleandir:
-.if exists(${.OBJDIR}/Makefile)
- ${MAKE} clean
-.endif
- /bin/rm -f Makefile
- /bin/rm -f modules/standard/Makefile
- /bin/rm -f modules/ssl/Makefile
- /bin/rm -f modules/Makefile
- /bin/rm -f support/Makefile
- /bin/rm -f main/Makefile
- /bin/rm -f ap/Makefile
- /bin/rm -f regex/Makefile
- /bin/rm -f os/unix/Makefile
- /bin/rm -f Makefile.config
- /bin/rm -f modules.c
-
-
-depend:
- # Nothing here yet
-lint:
- #Nothing here yet
-tags:
- #Nothing here yet
-
-.include<bsd.obj.mk>
-.include<bsd.subdir.mk>
diff --git a/usr.sbin/httpd/src/Makefile.nt b/usr.sbin/httpd/src/Makefile.nt
index 68c9a10db26..02dc752f645 100644
--- a/usr.sbin/httpd/src/Makefile.nt
+++ b/usr.sbin/httpd/src/Makefile.nt
@@ -55,6 +55,10 @@ _build:
cd ap
nmake /nologo CFG="ap - Win32 %LONG%" -f ap.mak
cd ..
+ cd support
+ nmake /nologo CFG="htpasswd - Win32 %LONG%" -f htpasswd.mak
+ nmake /nologo CFG="htdigest - Win32 %LONG%" -f htdigest.mak
+ cd ..
cd main
nmake /nologo CFG="gen_uri_delims - Win32 %LONG%" -f gen_uri_delims.mak
nmake /nologo CFG="gen_test_char - Win32 %LONG%" -f gen_test_char.mak
@@ -84,6 +88,7 @@ _install:
-mkdir $(INSTDIR)\modules
-mkdir $(INSTDIR)\logs
-mkdir $(INSTDIR)\conf
+ -mkdir $(INSTDIR)\bin
copy Apache%SHORT%\Apache.exe $(INSTDIR)
copy Core%SHORT%\ApacheCore.dll $(INSTDIR)
copy os\win32\ApacheModuleStatus%SHORT%\ApacheModuleStatus.dll $(INSTDIR)\modules
@@ -97,6 +102,8 @@ _install:
copy os\win32\ApacheModuleSpeling%SHORT%\ApacheModuleSpeling.dll $(INSTDIR)\modules
copy os\win32\ApacheModuleUserTrack%SHORT%\ApacheModuleUserTrack.dll $(INSTDIR)\modules
copy modules\proxy\%LONG%\ApacheModuleProxy.dll $(INSTDIR)\modules
+ copy support\%LONG%\htpasswd.exe $(INSTDIR)\bin
+ copy support\%LONG%\htdigest.exe $(INSTDIR)\bin
_clean:
cd os\win32
@@ -108,6 +115,10 @@ _clean:
cd ap
nmake /nologo CFG="ap - Win32 %LONG%" -f ap.mak clean
cd ..
+ cd support
+ nmake /nologo CFG="htpasswd - Win32 %LONG%" -f htpasswd.mak clean
+ nmake /nologo CFG="htdigest - Win32 %LONG%" -f htdigest.mak clean
+ cd ..
cd main
nmake /nologo CFG="gen_uri_delims - Win32 %LONG%" -f gen_uri_delims.mak clean
del uri_delims.h
diff --git a/usr.sbin/httpd/src/Makefile.tmpl b/usr.sbin/httpd/src/Makefile.tmpl
index b76ca00e433..a0b666a1efc 100644
--- a/usr.sbin/httpd/src/Makefile.tmpl
+++ b/usr.sbin/httpd/src/Makefile.tmpl
@@ -11,13 +11,20 @@ OBJS= \
$(OSDIR)/libos.a \
ap/libap.a
-TYPE=test
+TYPE=
+ALGO=
CRT=
KEY=
+VIEW=
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $<
+# Used to generate import library for OS/2
+.SUFFIXES: .def
+.def.a:
+ emximp -o $@ $<
+
all: @@Configuration@@ $(TARGET)
@@Configuration@@: Configuration.tmpl
@@ -32,14 +39,15 @@ $(TARGET): $(EXTRA_DEPS) $(SUBTARGET)
target_static: subdirs modules.o
$(CC) -c $(INCLUDES) $(CFLAGS) buildmark.c
$(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_SHLIB_EXPORT) \
- -o $(TARGET) buildmark.o $(OBJS) $(REGLIB) $(LIBS)
+ -o $(TARGET) buildmark.o $(OBJS) $(REGLIB) $(EXPATLIB) $(LIBS)
target_compile_only: subdirs modules.o
$(CC) -c $(INCLUDES) $(CFLAGS) buildmark.c
-target_shared: lib$(TARGET).ep
+target_shared: $(SHCORE_IMPLIB) $(SHARED_CORE_EP) lib$(TARGET).$(SHLIB_SUFFIX_NAME)
$(CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_SHLIB_EXPORT) \
- -o $(TARGET) -DSHARED_CORE_BOOTSTRAP main/http_main.c
+ -o $(TARGET) -DSHARED_CORE_BOOTSTRAP main/http_main.c \
+ ap/libap.a $(LIBS) $(SHCORE_IMPLIB)
lib$(TARGET).ep: lib$(TARGET).$(SHLIB_SUFFIX_NAME)
$(CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_SHLIB_EXPORT) \
@@ -48,7 +56,7 @@ lib$(TARGET).ep: lib$(TARGET).$(SHLIB_SUFFIX_NAME)
lib$(TARGET).$(SHLIB_SUFFIX_NAME): subdirs modules.o
$(CC) -c $(INCLUDES) $(CFLAGS) buildmark.c
- $(LD_SHLIB) $(LDFLAGS_SHLIB) -o lib$(TARGET).$(SHLIB_SUFFIX_NAME) buildmark.o $(OBJS) $(REGLIB)
+ $(LD_SHLIB) $(LDFLAGS_SHLIB) -o lib$(TARGET).$(SHLIB_SUFFIX_NAME) buildmark.o $(OBJS) $(REGLIB) $(EXPATLIB) $(LD_SHCORE_DEF) $(LD_SHCORE_LIBS)
@if [ ".$(SHLIB_SUFFIX_LIST)" != . ]; then \
rm -f lib$(TARGET).$(SHLIB_SUFFIX_NAME).*; \
for suffix in $(SHLIB_SUFFIX_LIST) ""; do \
@@ -60,10 +68,10 @@ lib$(TARGET).$(SHLIB_SUFFIX_NAME): subdirs modules.o
certificate:
@./support/mkcert.sh \
- "$(MAKE)" "$(MFLAGS_STATIC)" \
+ "$(MAKE)" "$(MFLAGS) $(MFLAGS_STATIC)" \
"$(SSL_PROGRAM)" ./support \
- "$(TYPE)" "$(CRT)" "$(KEY)"
- @cd ../conf/ssl.crt; $(MAKE) $(MFLAGS_STATIC) SSLEAY=$(SSL_PROGRAM) >/dev/null 2>&1
+ "$(TYPE)" "$(ALGO)" "$(CRT)" "$(KEY)" "$(VIEW)"
+ @cd ../conf/ssl.crt; $(MAKE) $(MFLAGS_STATIC) SSL_PROGRAM=$(SSL_PROGRAM) >/dev/null 2>&1
subdirs:
@for i in $(SUBDIRS); do \
@@ -98,6 +106,7 @@ distclean:
-rm -f modules.c
-rm -f modules/Makefile
-rm -f regex/Makefile
+ -rm -f lib/Makefile
-rm -f Makefile.config
-rm -f Makefile
diff --git a/usr.sbin/httpd/src/Makefile_win32.txt b/usr.sbin/httpd/src/Makefile_win32.txt
index bcd50c90a86..e4e3bc1e799 100644
--- a/usr.sbin/httpd/src/Makefile_win32.txt
+++ b/usr.sbin/httpd/src/Makefile_win32.txt
@@ -33,6 +33,10 @@ _build:
cd ap
nmake /nologo CFG="ap - Win32 Release" -f ap.mak
cd ..
+ cd support
+ nmake /nologo CFG="htpasswd - Win32 Release" -f htpasswd.mak
+ nmake /nologo CFG="htdigest - Win32 Release" -f htdigest.mak
+ cd ..
cd main
nmake /nologo CFG="gen_uri_delims - Win32 Release" -f gen_uri_delims.mak
nmake /nologo CFG="gen_test_char - Win32 Release" -f gen_test_char.mak
@@ -62,6 +66,7 @@ _install:
-mkdir $(INSTDIR)\modules
-mkdir $(INSTDIR)\logs
-mkdir $(INSTDIR)\conf
+ -mkdir $(INSTDIR)\bin
copy ApacheR\Apache.exe $(INSTDIR)
copy CoreR\ApacheCore.dll $(INSTDIR)
copy os\win32\ApacheModuleStatusR\ApacheModuleStatus.dll $(INSTDIR)\modules
@@ -75,6 +80,8 @@ _install:
copy os\win32\ApacheModuleSpelingR\ApacheModuleSpeling.dll $(INSTDIR)\modules
copy os\win32\ApacheModuleUserTrackR\ApacheModuleUserTrack.dll $(INSTDIR)\modules
copy modules\proxy\Release\ApacheModuleProxy.dll $(INSTDIR)\modules
+ copy support\Release\htpasswd.exe $(INSTDIR)\bin
+ copy support\Release\htdigest.exe $(INSTDIR)\bin
clean:
cd os\win32
@@ -86,6 +93,10 @@ clean:
cd ap
nmake /nologo CFG="ap - Win32 Release" -f ap.mak clean
cd ..
+ cd support
+ nmake /nologo CFG="htpasswd - Win32 Release" -f htpasswd.mak clean
+ nmake /nologo CFG="htdigest - Win32 Release" -f htdigest.mak clean
+ cd ..
cd main
nmake /nologo CFG="gen_uri_delims - Win32 Release" -f gen_uri_delims.mak clean
del uri_delims.h
diff --git a/usr.sbin/httpd/src/Makefile_win32_debug.txt b/usr.sbin/httpd/src/Makefile_win32_debug.txt
index 599676f86ec..15817ee34b3 100644
--- a/usr.sbin/httpd/src/Makefile_win32_debug.txt
+++ b/usr.sbin/httpd/src/Makefile_win32_debug.txt
@@ -33,6 +33,10 @@ _build:
cd ap
nmake /nologo CFG="ap - Win32 Debug" -f ap.mak
cd ..
+ cd support
+ nmake /nologo CFG="htpasswd - Win32 Debug" -f htpasswd.mak
+ nmake /nologo CFG="htdigest - Win32 Debug" -f htdigest.mak
+ cd ..
cd main
nmake /nologo CFG="gen_uri_delims - Win32 Debug" -f gen_uri_delims.mak
nmake /nologo CFG="gen_test_char - Win32 Debug" -f gen_test_char.mak
@@ -62,6 +66,7 @@ _install:
-mkdir $(INSTDIR)\modules
-mkdir $(INSTDIR)\logs
-mkdir $(INSTDIR)\conf
+ -mkdir $(INSTDIR)\bin
copy ApacheD\Apache.exe $(INSTDIR)
copy CoreD\ApacheCore.dll $(INSTDIR)
copy os\win32\ApacheModuleStatusD\ApacheModuleStatus.dll $(INSTDIR)\modules
@@ -75,6 +80,8 @@ _install:
copy os\win32\ApacheModuleSpelingD\ApacheModuleSpeling.dll $(INSTDIR)\modules
copy os\win32\ApacheModuleUserTrackD\ApacheModuleUserTrack.dll $(INSTDIR)\modules
copy modules\proxy\Debug\ApacheModuleProxy.dll $(INSTDIR)\modules
+ copy support\Debug\htpasswd.exe $(INSTDIR)\bin
+ copy support\Debug\htdigest.exe $(INSTDIR)\bin
clean:
cd os\win32
@@ -86,6 +93,10 @@ clean:
cd ap
nmake /nologo CFG="ap - Win32 Debug" -f ap.mak clean
cd ..
+ cd support
+ nmake /nologo CFG="htpasswd - Win32 Debug" -f htpasswd.mak clean
+ nmake /nologo CFG="htdigest - Win32 Debug" -f htdigest.mak clean
+ cd ..
cd main
nmake /nologo CFG="gen_uri_delims - Win32 Debug" -f gen_uri_delims.mak clean
del uri_delims.h
diff --git a/usr.sbin/httpd/src/README.EAPI b/usr.sbin/httpd/src/README.EAPI
new file mode 100644
index 00000000000..ffd1dee4a77
--- /dev/null
+++ b/usr.sbin/httpd/src/README.EAPI
@@ -0,0 +1,340 @@
+
+ Extended API (EAPI)
+ ===================
+
+ What is EAPI
+ ============
+
+ Extended API (EAPI) is a comprehensive API addition which can be _OPTIONALLY_
+ enabled with ``Rule EAPI=yes'' in src/Configuration or ``--enable-rule=EAPI''
+ on the APACI configure command line. This then defines a -DEAPI and this way
+ the EAPI code is compiled into Apache. When this define is not present _NO_
+ EAPI code is compiled into Apache at all, because all(!) EAPI patches are
+ encapsulated in #ifdef EAPI...#endif.
+
+ What is provided by EAPI?
+ =========================
+
+ EAPI's additions to the Apache API fall into the following categories:
+
+ o Context Attachment Support for Data Structures
+ o Loosly-coupled Hook Interface for Inter-Module Communication
+ o Direct and Pool-based Shared Memory Support
+ o Additional Apache Module Hooks
+ o Specialized EAPI Goodies
+
+ They are discussed in details now....
+
+ Context Attachment Support for Data Structures
+ ----------------------------------------------
+
+ Attaching private information to a request_rec, conn_rec, server_rec or even
+ BUFF structure is for a lot of modules the most elegant solution to keep
+ states between API phases without the need for any global variables. That's
+ especially true for modules which operate on lower I/O levels (where no
+ per-module configuration structure is available) or have to deal with various
+ callback functions of third-party libraries (where one need to find the
+ private context which can be hard without global variables).
+
+ The EAPI way to solve this situation is:
+
+ 1. A generic context library was written which allows one
+ to create a context and later store and retrieve context variables
+ identified by a unique key.
+
+ 2. The Apache kernel was extended to provide contexts for all standard data
+ structures like request_rec, server_rec, conn_rec, BUFF, etc. This way
+ modules can easily attach information to all these structures with the
+ help of the context API.
+
+ Point 1 is implemented by new src/ap/ap_ctx.c and src/include/ap_ctx.h source
+ files. Point 2 is implemented by EAPI patches to various src/main/*.c and
+ src/include/*.h files.
+
+ Example:
+
+ | /* a module implements on-the-fly compression for
+ | the buffer code and for this uses a third-party library which
+ | don't uses a filedescriptor. Instead a CLIB* is used. The module has to
+ | attach this CLIB* to the BUFF in oder to have it available whenever a
+ | BUFF is used somewhere. */
+ | BUFF *buff;
+ | CLIB *comp;
+ | comp = CLIB_new_from_fd(buff->fd);
+ | ap_ctx_set(buff->ctx, "CLIB", comp);
+ | :
+ |
+ | /* later when it deals with a BUFF, it can easily find back the
+ | CLIB* via the BUFF* */
+ | comp = (CLIB *)ap_ctx_get(buff->ctx, "CLIB");
+ | :
+
+ Possible use cases from practice are:
+
+ o attaching third-party structures to Apache structures
+ o replacing global module variables with clean context variables
+ o custom attachments for complex modules like mod_php, mod_php, etc.
+ o companion support for the hook interface (see below)
+ o etc. pp.
+
+ Loosly-coupled Hook Interface for Inter-Module Communication
+ ------------------------------------------------------------
+
+ Apache is structured into modules which is a nice idea. With the Dynamic
+ Shared Object (DSO) facility it gets even nicer because then modules are then
+ really stand-alone objects. The drawback is that DSO restricts modules. The
+ most popular problem is that no inter-module symbol references are allowed.
+ The classical problem: Module A implements some nice functions module B would
+ like to use to avoid reimplementing the wheel. But B cannot call A's
+ functions because this violates both the design idea of stand-alone modules
+ and the DSO restrictions. Additionally a module C could exists which also
+ provides a variant of the functionality of A's function. Then B should get
+ the variant (either A's or C's) which is best or available at all.
+
+ Real Life Example:
+
+ mod_rewrite provides %{XXXX} constructs to lookup variables. The available
+ variables are (and have to be) hard-coded into mod_rewrite. Now our mod_clib
+ which does on-the-fly compression provides a variable CLIB_FACTOR which gives
+ information about the shrink factor of the compression and a user wants to
+ use this shrink factor to make an URL-rewriting decision (<grin>). No chance
+ without EAPI. With EAPI it's easy: Inside the if-cascade for the various
+ variables in mod_rewrite one replaces:
+
+ | char *result;
+ | request_rec *r;
+ | :
+ | if (strcasecmp(var, "...") == 0) {
+ | :
+ | else if (strcasecmp(var, "SCRIPT_GROUP") == 0) {
+ | result = ...
+ | }
+ | else {
+ | if (result == NULL) {
+ | ...complain...
+ | }
+ | }
+ | :
+
+ with
+
+ | char *result;
+ | request_rec *r;
+ | :
+ | if (strcasecmp(var, "...") == 0) {
+ | :
+ | else if (strcasecmp(var, "SCRIPT_GROUP") == 0) {
+ | result = ...
+ | }
+ | else {
+ | ap_hook_use("ap::lookup_variable",
+ | AP_HOOK_SIG4(ptr,ptr,ptr,ctx),
+ | AP_HOOK_DECLINE(NULL),
+ | &result, r, var);
+ | if (result == NULL) {
+ | ...complain...
+ | }
+ | }
+ | :
+
+ What this does is that when XXXX of %{XXXX} isn't known, a hook named
+ ap::lookup_variable is called with the request_rec and the var ("XXX") and
+ the result variable. When no one has registered for this hook, nothing
+ happens. ap_hook_use() immediately returns and nothing was changed.
+
+ But now let's assume mod_clib is additionally loaded as a DSO. And without
+ changing anything now magically mod_rewrite implements %{CLIB_FACTOR}. How?
+ Look inside mod_clib.c:
+
+ | /* mod_clib registeres for the ap::lookup_variable hook
+ | inside it's init phase */
+ | CLIB *comp;
+ | ap_hook_register("ap::lookup_variable",
+ | my_lookup_variable, AP_HOOK_CTX(comp));
+ |
+ | /* and implements the my_lookup_variable() function */
+ | char *my_lookup_variable(request_rec *r, char *name, CLIB *comp)
+ | {
+ | if (strcmp(name, "CLIB_FACTOR") == 0)
+ | return ap_psrintf(r->pool, "%d", comp->factor);
+ | return NULL;
+ | }
+
+ What happens? When mod_rewrite calls the ap_hook_use() function internally
+ the hook facility knows that mod_clib has registered for this hook and calls
+ the equivalent of
+
+ | result = my_lookup_variable(r, var, <comp>);
+
+ where <comp> is the CLIB* context variable mod_clib has registered for
+ itself. Now assume a second module exists which also provides variables and
+ want to allow mod_rewrite to lookup them. It registers after mod_clib with
+
+ | ap_hook_register("ap::lookup_variable",
+ | my_lookup_variable2, AP_HOOK_CTX(whatever));
+ |
+
+ and then the following happens: The hook facility does for mod_rewrite the
+ equivalent of:
+
+ | result = my_lookup_variable(r, var, <comp>);
+ | if (result == NULL)
+ | result = my_lookup_variable2(r, var, <whatever>);
+
+ As you can see the hook functions decline in this example with NULL. That's
+ the NULL from AP_HOOK_DECLINE(NULL) and can be any value of any type, of
+ course.
+
+ The same idea can be also used by mod_log_config and every other module which
+ wants to lookup a variable inside Apache. Which variables are available
+ depend on the available modules which implement them. And this all works
+ nicely with the DSO facility, because the ap_hook_xxx() API is part of the
+ Apache kernel code. And nothing has to be changed inside Apache when another
+ modules wants to create a new hook, because the mechanism is totally generic.
+
+ So when our module A wants to let other modules to use it's function it just
+ has to configure a hook for this. Then other modules call this hook. Is
+ module A not there the boolean return value of the hook call will indicate
+ this. When module A is there the function is called.
+
+ Direct and Pool-based Shared Memory Support
+ -------------------------------------------
+
+ Since years it was annoying that Apache's pre-forked process model basically
+ means that every server lives it's own life (= address space) and this way
+ module authors cannot easily spread module configuration or other data
+ accross the processes. The most elegant solution is to use shared memory
+ segments. The drawback is that there is no portable API for shared memory
+ handling and there is no convinient memory allocation API for working inside
+ shared memory segments.
+
+ The EAPI way to solve this situation is:
+
+ 1. A stand-alone and resuable library was written (named MM from "memory
+ mapped" and available from http://www.engelschall.com/sw/mm/) which
+ abstracts the shared memory and memory mutex fiddling into a low-level
+ API. Internally the shared memory and mutex functionality is implemented
+ in various platform-depended ways: 4.4BSD or POSIX.1 anonymous memory
+ mapping, /dev/zero-based memory mapping, temporary file memory mapping, or
+ SysV IPC shared memory for allocating the shared memory areas and POSIX.1
+ fcntl(2), BSD flock(2) or SysV IPC semaphores for implementing mutual
+ exclusion capabilities.
+
+ Additionally MM provides a high-level malloc()-style API based on this
+ abstracted shared memory low-level API. The idea is just to allocate the
+ requested memory chunks from shared memory segments instead of the heap.
+
+ 2. EAPI now provides an easy method (with the EAPI_MM configuration
+ variable) to build Apache against this MM library. For this the whole MM
+ API (mm_xxx() functions) is encapsulated in an Apache API subpart
+ (ap_mm_xxx() functions). This way the API is fixed and always present (no
+ #ifdef EAPI stuff in modules!), but useable only when EAPI was used in
+ conjunction with MM. A simple ``EAPI_MM=/path/to/mm ./configure
+ --enable-rule=EAPI ...'' is enough to put MM under the ap_mm_xxx() API.
+ This way modules can use a consistent, powerful and abstracted ap_mm_xxx()
+ API for dealing with shared memory.
+
+ 3. Because inside Apache mostly all memory handling is done via the
+ pool facility, additional support for ``shared memory pools'' is provided.
+ This way modules can use all ap_pxxx() functions in combination with
+ shared memory.
+
+ Point 1 is implemented inside the MM package. Point 2 is implemented by the
+ new src/ap/ap_mm.c and src/include/ap_mm.h source files. Point 3 is
+ implemented by EAPI patches to src/main/alloc.c and src/include/alloc.h.
+
+ Example:
+
+ | /* inside a module init function (before the forking!)
+ | for instance a module allocates a structure with a counter
+ | in a shared memory segment */
+ | pool *p;
+ | pool *sp;
+ | struct mystuff { int cnt } *my;
+ | sp = ap_make_shared_sub_pool(p);
+ | my = (struct mystuff *)ap_palloc(sp, sizeof(struct mystuff));
+ | my->cnt = 0;
+ |
+ | :
+ | /* then under request processing time it's changed by one process */
+ | ap_acquire_pool(sp, AP_POOL_RW);
+ | my->cnt++;
+ | ap_release_pool(sp);
+ | :
+ |
+ | /* and at the same time read by other processes */
+ | ap_acquire_pool(sp, AP_POOL_RD);
+ | ap_rprintf(r, "The counter is %d\n", my->cnt);
+ | ap_release_pool(sp);
+
+ Possible use cases from practice are:
+
+ o assembling traffic or other accounting details
+ o establishing of high-performance inter-process caches
+ o inter-process wide keeping of session state information
+ o shared memory support for mod_perl, mod_php, etc.
+ o etc. pp.
+
+ Additional Apache Module Hooks
+ ------------------------------
+
+ The above three EAPI additions are all very generic facilities. But there
+ were also specialized things which were missing in Apache (and needed by
+ modules). Mostly additional API phases. EAPI adds the following additional
+ hook pointers to the module structure:
+
+ add_module:
+ Called from within ap_add_module() right after the module structure
+ was linked into the Apache internal module list. It is mainly
+ intended to be used to define configuration defines (<IfDefine>)
+ which have to be available directly after a LoadModule/AddModule.
+ Actually this is the earliest possible hook a module can use. It's
+ especially important for the modules when they use the hook facility.
+
+ remove_module:
+ Called from within ap_remove_module() right before the module
+ structure is kicked out from the Apache internal module list.
+ Actually this is last possible hook a module can use and exists for
+ consistency with the add_module hook.
+
+ rewrite_command:
+ Called right after a configuration directive line was read and
+ before it is processed. It is mainly intended to be used for
+ rewriting directives in order to provide backward compatibility to
+ old directive variants.
+
+ new_connection:
+ Called from within the internal new_connection() function, right
+ after the conn_rec structure for the new established connection was
+ created and before Apache starts processing the request with
+ ap_read_request(). It is mainly intended to be used to setup/run
+ connection dependent things like sending start headers for
+ on-the-fly compression, etc.
+
+ close_connection:
+ Called from within the Apache dispatching loop just before any
+ ap_bclose() is performed on the socket connection, but a long time
+ before any pool cleanups are done for the connection (which can be
+ too late for some applications). It is mainly intended to be used
+ to close/finalize connection dependent things like sending end
+ headers for on-the-fly compression, etc.
+
+ Specialized EAPI Goodies
+ ------------------------
+
+ And finally EAPI now uses some of the new functionality to add a few new
+ EAPI-based goodies to mod_rewrite, mod_status and mod_proxy:
+
+ mod_rewrite:
+ The above presented example of lookup hooks is implemented which allows
+ mod_rewrite to lookup arbitrary variables provides by not known modules.
+
+ mod_status:
+ Any module now can register to an EAPI hook of mod_status which
+ allows it to put additional text on the /status webpages.
+
+ mod_proxy:
+ Some EAPI hooks are provided to allow other modules to control the HTTP
+ client processing inside mod_proxy. This can be used for a lot of
+ tricks.
+
diff --git a/usr.sbin/httpd/src/ap/Makefile.tmpl b/usr.sbin/httpd/src/ap/Makefile.tmpl
index 346b6b6df79..75209a1522c 100644
--- a/usr.sbin/httpd/src/ap/Makefile.tmpl
+++ b/usr.sbin/httpd/src/ap/Makefile.tmpl
@@ -5,8 +5,9 @@ LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
LIB=libap.a
-OBJS=ap_execve.o ap_cpystrn.o ap_signal.o \
- ap_slack.o ap_snprintf.o ap_fnmatch.o ap_hook.o ap_ctx.o
+OBJS=ap_cpystrn.o ap_execve.o ap_fnmatch.o ap_getpass.o ap_md5c.o ap_signal.o \
+ ap_slack.o ap_snprintf.o ap_sha1.o ap_checkpass.o ap_base64.o \
+ ap_hook.o ap_ctx.o ap_mm.o
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $<
@@ -41,25 +42,38 @@ depend:
# DO NOT REMOVE
ap_cpystrn.o: ap_cpystrn.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
- $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/alloc.h \
- $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h
+ $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h
ap_execve.o: ap_execve.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
- $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/alloc.h \
- $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h
+ $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h
ap_fnmatch.o: ap_fnmatch.c $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
- $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(INCDIR)/ap_ctype.h \
- $(INCDIR)/hsregex.h $(INCDIR)/fnmatch.h
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(OSDIR)/os-inline.c \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/fnmatch.h
+ap_getpass.o: ap_getpass.c $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(OSDIR)/os-inline.c \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap.h
+ap_md5c.o: ap_md5c.c $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(OSDIR)/os-inline.c \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_md5.h \
+ $(INCDIR)/ap.h
+ap_sha1.o: ap_sha1.c $(INCDIR)/ap_config.h $(INCDIR)/ap_sha1.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(OSDIR)/os-inline.c
ap_signal.o: ap_signal.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
- $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/alloc.h \
- $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h
+ $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h
ap_slack.o: ap_slack.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
- $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/alloc.h \
- $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
- $(INCDIR)/http_log.h
+ $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_log.h
ap_snprintf.o: ap_snprintf.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
- $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/alloc.h \
- $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h
+ $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h
diff --git a/usr.sbin/httpd/src/ap/ap.dsp b/usr.sbin/httpd/src/ap/ap.dsp
index bbcdda44e0a..9d9c3194f14 100644
--- a/usr.sbin/httpd/src/ap/ap.dsp
+++ b/usr.sbin/httpd/src/ap/ap.dsp
@@ -102,5 +102,21 @@ SOURCE=.\ap_snprintf.c
# PROP Default_Filter ""
# End Group
+# Begin Source File
+
+SOURCE=.\ap_md5c.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ap_sha1.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ap_checkpass.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ap_base64.c
+# End Source File
# End Target
# End Project
diff --git a/usr.sbin/httpd/src/ap/ap.mak b/usr.sbin/httpd/src/ap/ap.mak
index 1e7c74a81b0..84f7b22898b 100644
--- a/usr.sbin/httpd/src/ap/ap.mak
+++ b/usr.sbin/httpd/src/ap/ap.mak
@@ -25,8 +25,6 @@ NULL=
NULL=nul
!ENDIF
-CPP=cl.exe
-
!IF "$(CFG)" == "ap - Win32 Release"
OUTDIR=.\Release
@@ -48,35 +46,77 @@ ALL : "$(OUTDIR)\ap.lib"
CLEAN :
-@erase "$(INTDIR)\ap_cpystrn.obj"
-@erase "$(INTDIR)\ap_fnmatch.obj"
+ -@erase "$(INTDIR)\ap_md5c.obj"
-@erase "$(INTDIR)\ap_hook.obj"
-@erase "$(INTDIR)\ap_ctx.obj"
+ -@erase "$(INTDIR)\ap_mm.obj"
-@erase "$(INTDIR)\ap_signal.obj"
-@erase "$(INTDIR)\ap_slack.obj"
-@erase "$(INTDIR)\ap_snprintf.obj"
+ -@erase "$(INTDIR)\ap_sha1.obj"
+ -@erase "$(INTDIR)\ap_base64.obj"
+ -@erase "$(INTDIR)\ap_checkpass.obj"
-@erase "$(INTDIR)\vc50.idb"
-@erase "$(OUTDIR)\ap.lib"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+CPP=cl.exe
CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D\
"_WINDOWS" /Fp"$(INTDIR)\ap.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
CPP_OBJS=.\Release/
CPP_SBRS=.
+
+.c{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\ap.bsc"
BSC32_SBRS= \
-
+
LIB32=link.exe -lib
LIB32_FLAGS=/nologo /out:"$(OUTDIR)\ap.lib"
LIB32_OBJS= \
"$(INTDIR)\ap_cpystrn.obj" \
"$(INTDIR)\ap_fnmatch.obj" \
+ "$(INTDIR)\ap_md5c.obj" \
"$(INTDIR)\ap_hook.obj" \
"$(INTDIR)\ap_ctx.obj" \
+ "$(INTDIR)\ap_mm.obj" \
"$(INTDIR)\ap_signal.obj" \
"$(INTDIR)\ap_slack.obj" \
- "$(INTDIR)\ap_snprintf.obj"
+ "$(INTDIR)\ap_snprintf.obj" \
+ "$(INTDIR)\ap_sha1.obj" \
+ "$(INTDIR)\ap_base64.obj" \
+ "$(INTDIR)\ap_checkpass.obj"
"$(OUTDIR)\ap.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
$(LIB32) @<<
@@ -104,42 +144,27 @@ ALL : "$(OUTDIR)\ap.lib"
CLEAN :
-@erase "$(INTDIR)\ap_cpystrn.obj"
-@erase "$(INTDIR)\ap_fnmatch.obj"
+ -@erase "$(INTDIR)\ap_md5c.obj"
-@erase "$(INTDIR)\ap_hook.obj"
-@erase "$(INTDIR)\ap_ctx.obj"
+ -@erase "$(INTDIR)\ap_mm.obj"
-@erase "$(INTDIR)\ap_signal.obj"
-@erase "$(INTDIR)\ap_slack.obj"
-@erase "$(INTDIR)\ap_snprintf.obj"
+ -@erase "$(INTDIR)\ap_sha1.obj"
+ -@erase "$(INTDIR)\ap_base64.obj"
+ -@erase "$(INTDIR)\ap_checkpass.obj"
-@erase "$(INTDIR)\vc50.idb"
-@erase "$(OUTDIR)\ap.lib"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+CPP=cl.exe
CPP_PROJ=/nologo /MDd /W3 /GX /Z7 /Od /I "../include" /D "WIN32" /D "_DEBUG" /D\
"_WINDOWS" /Fp"$(INTDIR)\ap.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
CPP_OBJS=.\Debug/
CPP_SBRS=.
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\ap.bsc"
-BSC32_SBRS= \
-
-LIB32=link.exe -lib
-LIB32_FLAGS=/nologo /out:"$(OUTDIR)\ap.lib"
-LIB32_OBJS= \
- "$(INTDIR)\ap_cpystrn.obj" \
- "$(INTDIR)\ap_fnmatch.obj" \
- "$(INTDIR)\ap_hook.obj" \
- "$(INTDIR)\ap_ctx.obj" \
- "$(INTDIR)\ap_signal.obj" \
- "$(INTDIR)\ap_slack.obj" \
- "$(INTDIR)\ap_snprintf.obj"
-
-"$(OUTDIR)\ap.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
- $(LIB32) @<<
- $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
-<<
-
-!ENDIF
.c{$(CPP_OBJS)}.obj::
$(CPP) @<<
@@ -171,6 +196,33 @@ LIB32_OBJS= \
$(CPP_PROJ) $<
<<
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\ap.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\ap.lib"
+LIB32_OBJS= \
+ "$(INTDIR)\ap_cpystrn.obj" \
+ "$(INTDIR)\ap_fnmatch.obj" \
+ "$(INTDIR)\ap_md5c.obj" \
+ "$(INTDIR)\ap_hook.obj" \
+ "$(INTDIR)\ap_ctx.obj" \
+ "$(INTDIR)\ap_mm.obj" \
+ "$(INTDIR)\ap_signal.obj" \
+ "$(INTDIR)\ap_slack.obj" \
+ "$(INTDIR)\ap_snprintf.obj" \
+ "$(INTDIR)\ap_sha1.obj" \
+ "$(INTDIR)\ap_base64.obj" \
+ "$(INTDIR)\ap_checkpass.obj"
+
+"$(OUTDIR)\ap.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+ $(LIB32) @<<
+ $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ENDIF
+
!IF "$(CFG)" == "ap - Win32 Release" || "$(CFG)" == "ap - Win32 Debug"
SOURCE=.\ap_cpystrn.c
@@ -180,17 +232,24 @@ SOURCE=.\ap_cpystrn.c
DEP_CPP_AP_CP=\
"..\include\alloc.h"\
"..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
"..\include\buff.h"\
- "..\include\conf.h"\
"..\include\hsregex.h"\
"..\include\httpd.h"\
"..\include\util_uri.h"\
"..\os\win32\os.h"\
"..\os\win32\readdir.h"\
-
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
NODEP_CPP_AP_CP=\
- "..\include\apctype.h"\
-
+ "..\include\ap_config_auto.h"\
+ "..\include\ebcdic.h"\
+ "..\include\os.h"\
+ "..\include\sfio.h"\
+
"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) $(DEP_CPP_AP_CP) "$(INTDIR)"
@@ -200,17 +259,16 @@ NODEP_CPP_AP_CP=\
DEP_CPP_AP_CP=\
"..\include\alloc.h"\
"..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
"..\include\buff.h"\
- "..\include\conf.h"\
"..\include\hsregex.h"\
"..\include\httpd.h"\
"..\include\util_uri.h"\
"..\os\win32\os.h"\
"..\os\win32\readdir.h"\
-
-NODEP_CPP_AP_CP=\
- "..\include\hide.h"\
-
+
"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) $(DEP_CPP_AP_CP) "$(INTDIR)"
@@ -218,23 +276,43 @@ NODEP_CPP_AP_CP=\
!ENDIF
SOURCE=.\ap_fnmatch.c
+
+!IF "$(CFG)" == "ap - Win32 Release"
+
DEP_CPP_AP_FN=\
"..\include\ap_config.h"\
"..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
"..\include\fnmatch.h"\
"..\include\hsregex.h"\
"..\os\win32\os.h"\
{$(INCLUDE)}"sys\stat.h"\
{$(INCLUDE)}"sys\types.h"\
-
+
NODEP_CPP_AP_FN=\
"..\include\ap_config_auto.h"\
"..\include\os.h"\
-
+
"$(INTDIR)\ap_fnmatch.obj" : $(SOURCE) $(DEP_CPP_AP_FN) "$(INTDIR)"
+!ELSEIF "$(CFG)" == "ap - Win32 Debug"
+
+DEP_CPP_AP_FN=\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\fnmatch.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+"$(INTDIR)\ap_fnmatch.obj" : $(SOURCE) $(DEP_CPP_AP_FN) "$(INTDIR)"
+
+
+!ENDIF
+
SOURCE=.\ap_signal.c
!IF "$(CFG)" == "ap - Win32 Release"
@@ -242,17 +320,24 @@ SOURCE=.\ap_signal.c
DEP_CPP_AP_SI=\
"..\include\alloc.h"\
"..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
"..\include\buff.h"\
- "..\include\conf.h"\
"..\include\hsregex.h"\
"..\include\httpd.h"\
"..\include\util_uri.h"\
"..\os\win32\os.h"\
"..\os\win32\readdir.h"\
-
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
NODEP_CPP_AP_SI=\
- "..\include\apctype.h"\
-
+ "..\include\ap_config_auto.h"\
+ "..\include\ebcdic.h"\
+ "..\include\os.h"\
+ "..\include\sfio.h"\
+
"$(INTDIR)\ap_signal.obj" : $(SOURCE) $(DEP_CPP_AP_SI) "$(INTDIR)"
@@ -262,17 +347,16 @@ NODEP_CPP_AP_SI=\
DEP_CPP_AP_SI=\
"..\include\alloc.h"\
"..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
"..\include\buff.h"\
- "..\include\conf.h"\
"..\include\hsregex.h"\
"..\include\httpd.h"\
"..\include\util_uri.h"\
"..\os\win32\os.h"\
"..\os\win32\readdir.h"\
-
-NODEP_CPP_AP_SI=\
- "..\include\hide.h"\
-
+
"$(INTDIR)\ap_signal.obj" : $(SOURCE) $(DEP_CPP_AP_SI) "$(INTDIR)"
@@ -286,18 +370,25 @@ SOURCE=.\ap_slack.c
DEP_CPP_AP_SL=\
"..\include\alloc.h"\
"..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
"..\include\buff.h"\
- "..\include\conf.h"\
"..\include\hsregex.h"\
"..\include\http_log.h"\
"..\include\httpd.h"\
"..\include\util_uri.h"\
"..\os\win32\os.h"\
"..\os\win32\readdir.h"\
-
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
NODEP_CPP_AP_SL=\
- "..\include\apctype.h"\
-
+ "..\include\ap_config_auto.h"\
+ "..\include\ebcdic.h"\
+ "..\include\os.h"\
+ "..\include\sfio.h"\
+
"$(INTDIR)\ap_slack.obj" : $(SOURCE) $(DEP_CPP_AP_SL) "$(INTDIR)"
@@ -307,18 +398,17 @@ NODEP_CPP_AP_SL=\
DEP_CPP_AP_SL=\
"..\include\alloc.h"\
"..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
"..\include\buff.h"\
- "..\include\conf.h"\
"..\include\hsregex.h"\
"..\include\http_log.h"\
"..\include\httpd.h"\
"..\include\util_uri.h"\
"..\os\win32\os.h"\
"..\os\win32\readdir.h"\
-
-NODEP_CPP_AP_SL=\
- "..\include\hide.h"\
-
+
"$(INTDIR)\ap_slack.obj" : $(SOURCE) $(DEP_CPP_AP_SL) "$(INTDIR)"
@@ -332,17 +422,24 @@ SOURCE=.\ap_snprintf.c
DEP_CPP_AP_SN=\
"..\include\alloc.h"\
"..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
"..\include\buff.h"\
- "..\include\conf.h"\
"..\include\hsregex.h"\
"..\include\httpd.h"\
"..\include\util_uri.h"\
"..\os\win32\os.h"\
"..\os\win32\readdir.h"\
-
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
NODEP_CPP_AP_SN=\
- "..\include\apctype.h"\
-
+ "..\include\ap_config_auto.h"\
+ "..\include\ebcdic.h"\
+ "..\include\os.h"\
+ "..\include\sfio.h"\
+
"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) $(DEP_CPP_AP_SN) "$(INTDIR)"
@@ -350,19 +447,176 @@ NODEP_CPP_AP_SN=\
!ELSEIF "$(CFG)" == "ap - Win32 Debug"
DEP_CPP_AP_SN=\
- "..\include\conf.h"\
+ "..\include\alloc.h"\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
"..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
"..\os\win32\os.h"\
-
-NODEP_CPP_AP_SN=\
- "..\include\hide.h"\
-
+ "..\os\win32\readdir.h"\
+
"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) $(DEP_CPP_AP_SN) "$(INTDIR)"
!ENDIF
+SOURCE=.\ap_md5c.c
+
+!IF "$(CFG)" == "ap - Win32 Release"
+
+DEP_CPP_AP_MD=\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_AP_MD=\
+ "..\include\ap_config_auto.h"\
+ "..\include\os.h"\
+ ".\ebcdic.h"\
+
+
+"$(INTDIR)\ap_md5c.obj" : $(SOURCE) $(DEP_CPP_AP_MD) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "ap - Win32 Debug"
+
+DEP_CPP_AP_MD=\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+"$(INTDIR)\ap_md5c.obj" : $(SOURCE) $(DEP_CPP_AP_MD) "$(INTDIR)"
+
+
+!ENDIF
+
+
+SOURCE=.\ap_checkpass.c
+
+!IF "$(CFG)" == "ap - Win32 Release"
+
+DEP_CPP_AP_CH=\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_AP_CH=\
+ "..\include\ap_config_auto.h"\
+ "..\include\os.h"\
+ ".\ebcdic.h"\
+
+
+"$(INTDIR)\ap_checkpass.obj" : $(SOURCE) $(DEP_CPP_AP_CH) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "ap - Win32 Debug"
+
+DEP_CPP_AP_CH=\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+"$(INTDIR)\ap_checkpass.obj" : $(SOURCE) $(DEP_CPP_AP_CH) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\ap_sha1.c
+
+!IF "$(CFG)" == "ap - Win32 Release"
+
+DEP_CPP_AP_SH=\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_sha1.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_AP_SH=\
+ "..\include\ap_config_auto.h"\
+ "..\include\os.h"\
+ ".\ebcdic.h"\
+
+
+"$(INTDIR)\ap_sha1.obj" : $(SOURCE) $(DEP_CPP_AP_SH) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "ap - Win32 Debug"
+
+DEP_CPP_AP_SH=\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_sha1.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+"$(INTDIR)\ap_sha1.obj" : $(SOURCE) $(DEP_CPP_AP_SH) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\ap_base64.c
+
+!IF "$(CFG)" == "ap - Win32 Release"
+
+DEP_CPP_AP_BA=\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_AP_BA=\
+ "..\include\ap_config_auto.h"\
+ "..\include\os.h"\
+ ".\ebcdic.h"\
+
+
+"$(INTDIR)\ap_base64.obj" : $(SOURCE) $(DEP_CPP_AP_BA) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "ap - Win32 Debug"
+
+DEP_CPP_AP_BA=\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+"$(INTDIR)\ap_base64.obj" : $(SOURCE) $(DEP_CPP_AP_BA) "$(INTDIR)"
+
+
+!ENDIF
!ENDIF
diff --git a/usr.sbin/httpd/src/ap/ap_base64.c b/usr.sbin/httpd/src/ap/ap_base64.c
new file mode 100644
index 00000000000..89cda4b5c26
--- /dev/null
+++ b/usr.sbin/httpd/src/ap/ap_base64.c
@@ -0,0 +1,272 @@
+/* ====================================================================
+ * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+
+/* base64 encoder/decoder. Originally part of main/util.c
+ * but moved here so that support/ab and ap_sha1.c could
+ * use it. This meant removing the ap_palloc()s and adding
+ * ugly 'len' functions, which is quite a nasty cost.
+ */
+
+#include <string.h>
+
+#include "ap_config.h"
+#include "ap.h"
+
+#ifdef CHARSET_EBCDIC
+#include "ebcdic.h"
+#endif /* CHARSET_EBCDIC */
+
+/* aaaack but it's fast and const should make it shared text page. */
+static const unsigned char pr2six[256] =
+{
+#ifndef CHARSET_EBCDIC
+ /* ASCII table */
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
+ 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
+ 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+#else /*CHARSET_EBCDIC*/
+ /* EBCDIC table */
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 64, 64, 64, 64, 64, 64,
+ 64, 35, 36, 37, 38, 39, 40, 41, 42, 43, 64, 64, 64, 64, 64, 64,
+ 64, 64, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 64, 64, 64, 64, 64, 64,
+ 64, 9, 10, 11, 12, 13, 14, 15, 16, 17, 64, 64, 64, 64, 64, 64,
+ 64, 64, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64
+#endif /*CHARSET_EBCDIC*/
+};
+
+API_EXPORT(int) ap_base64decode_len(const char *bufcoded)
+{
+ int nbytesdecoded;
+ register const unsigned char *bufin;
+ register int nprbytes;
+
+ bufin = (const unsigned char *) bufcoded;
+ while (pr2six[*(bufin++)] <= 63);
+
+ nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
+ nbytesdecoded = ((nprbytes + 3) / 4) * 3;
+
+ return nbytesdecoded + 1;
+}
+
+API_EXPORT(int) ap_base64decode(char *bufplain, const char *bufcoded)
+{
+#ifdef CHARSET_EBCDIC
+ int i;
+#endif /* CHARSET_EBCDIC */
+ int len;
+
+ len = ap_base64decode_binary((unsigned char *) bufplain, bufcoded);
+#ifdef CHARSET_EBCDIC
+ for (i = 0; i < len; i++)
+ bufplain[i] = os_toebcdic[bufplain[i]];
+#endif /* CHARSET_EBCDIC */
+ return len;
+}
+
+/* This is the same as ap_base64udecode() except on EBCDIC machines, where
+ * the conversion of the output to ebcdic is left out.
+ */
+API_EXPORT(int) ap_base64decode_binary(unsigned char *bufplain,
+ const char *bufcoded)
+{
+ int nbytesdecoded;
+ register const unsigned char *bufin;
+ register unsigned char *bufout;
+ register int nprbytes;
+
+ bufin = (const unsigned char *) bufcoded;
+ while (pr2six[*(bufin++)] <= 63);
+ nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
+ nbytesdecoded = ((nprbytes + 3) / 4) * 3;
+
+ bufout = (unsigned char *) bufplain;
+ bufin = (const unsigned char *) bufcoded;
+
+ while (nprbytes > 4) {
+ *(bufout++) =
+ (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
+ *(bufout++) =
+ (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
+ *(bufout++) =
+ (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
+ bufin += 4;
+ nprbytes -= 4;
+ }
+
+ /* Note: (nprbytes == 1) would be an error, so just ingore that case */
+ if (nprbytes > 1) {
+ *(bufout++) =
+ (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
+ }
+ if (nprbytes > 2) {
+ *(bufout++) =
+ (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
+ }
+ if (nprbytes > 3) {
+ *(bufout++) =
+ (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
+ }
+
+ *(bufout++) = '\0';
+ nbytesdecoded -= (4 - nprbytes) & 3;
+ return nbytesdecoded;
+}
+
+static const char basis_64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+API_EXPORT(int) ap_base64encode_len(int len)
+{
+ return ((len + 2) / 3 * 4) + 1;
+}
+
+API_EXPORT(int) ap_base64encode(char *encoded, const char *string, int len)
+{
+#ifndef CHARSET_EBCDIC
+ return ap_base64encode_binary(encoded, (const unsigned char *) string, len);
+#else /* CHARSET_EBCDIC */
+ int i;
+ char *p;
+
+ p = encoded;
+ for (i = 0; i < len - 2; i += 3) {
+ *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
+ *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) |
+ ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)];
+ *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2) |
+ ((int) (os_toascii[string[i + 2]] & 0xC0) >> 6)];
+ *p++ = basis_64[os_toascii[string[i + 2]] & 0x3F];
+ }
+ if (i < len) {
+ *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
+ if (i == (len - 1)) {
+ *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4)];
+ *p++ = '=';
+ }
+ else {
+ *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) |
+ ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)];
+ *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2)];
+ }
+ *p++ = '=';
+ }
+
+ *p++ = '\0';
+ return p - encoded;
+#endif /* CHARSET_EBCDIC */
+}
+
+/* This is the same as ap_base64encode() except on EBCDIC machines, where
+ * the conversion of the input to ascii is left out.
+ */
+API_EXPORT(int) ap_base64encode_binary(char *encoded,
+ const unsigned char *string, int len)
+{
+ int i;
+ char *p;
+
+ p = encoded;
+ for (i = 0; i < len - 2; i += 3) {
+ *p++ = basis_64[(string[i] >> 2) & 0x3F];
+ *p++ = basis_64[((string[i] & 0x3) << 4) |
+ ((int) (string[i + 1] & 0xF0) >> 4)];
+ *p++ = basis_64[((string[i + 1] & 0xF) << 2) |
+ ((int) (string[i + 2] & 0xC0) >> 6)];
+ *p++ = basis_64[string[i + 2] & 0x3F];
+ }
+ if (i < len) {
+ *p++ = basis_64[(string[i] >> 2) & 0x3F];
+ if (i == (len - 1)) {
+ *p++ = basis_64[((string[i] & 0x3) << 4)];
+ *p++ = '=';
+ }
+ else {
+ *p++ = basis_64[((string[i] & 0x3) << 4) |
+ ((int) (string[i + 1] & 0xF0) >> 4)];
+ *p++ = basis_64[((string[i + 1] & 0xF) << 2)];
+ }
+ *p++ = '=';
+ }
+
+ *p++ = '\0';
+ return p - encoded;
+}
diff --git a/usr.sbin/httpd/src/ap/ap_checkpass.c b/usr.sbin/httpd/src/ap/ap_checkpass.c
new file mode 100644
index 00000000000..63258c9e275
--- /dev/null
+++ b/usr.sbin/httpd/src/ap/ap_checkpass.c
@@ -0,0 +1,111 @@
+/* ====================================================================
+ * Copyright (c) 1996-1999 The Apache Group. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ * Simple password verify, which 'know's about various password
+ * types, such as the simple base64 encoded crypt()s, MD5 $ marked
+ * FreeBSD style and netscape SHA1's.
+ */
+#include <string.h>
+
+#include "ap_config.h"
+#include "ap_md5.h"
+#include "ap_sha1.h"
+#include "ap.h"
+#if HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+
+/*
+ * Validate a plaintext password against a smashed one. Use either
+ * crypt() (if available), ap_MD5Encode() or ap_SHA1Encode depending
+ * upon the format of the smashed input password.
+ *
+ * Return NULL if they match, or an explanatory text string if they don't.
+ */
+
+API_EXPORT(char *) ap_validate_password(const char *passwd, const char *hash)
+{
+ char sample[120];
+
+
+ /* FreeBSD style MD5 string
+ */
+ if (strncmp(hash, AP_MD5PW_ID, AP_MD5PW_IDLEN) == 0) {
+
+ ap_MD5Encode((const unsigned char *)passwd,
+ (const unsigned char *)hash, sample, sizeof(sample));
+ }
+ /* Netscape / SHA1 ldap style strng
+ */
+ else if (strncmp(hash, AP_SHA1PW_ID, AP_SHA1PW_IDLEN) == 0) {
+
+ ap_sha1_base64(passwd, strlen(passwd), sample);
+ }
+ else {
+ /*
+ * It's not our algorithm, so feed it to crypt() if possible.
+ */
+#if defined(WIN32) || defined(TPF)
+ /*
+ * On Windows, the only alternative to our MD5 algorithm is plain
+ * text.
+ */
+ ap_cpystrn(sample, passwd, sizeof(sample) - 1);
+#else
+ ap_cpystrn(sample, (char *)crypt(passwd, hash), sizeof(sample) - 1);
+#endif
+ }
+ return (strcmp(sample, hash) == 0) ? NULL : "password mismatch";
+}
diff --git a/usr.sbin/httpd/src/ap/ap_ctx.c b/usr.sbin/httpd/src/ap/ap_ctx.c
index db457edae0e..f714fc3ac5a 100644
--- a/usr.sbin/httpd/src/ap/ap_ctx.c
+++ b/usr.sbin/httpd/src/ap/ap_ctx.c
@@ -60,6 +60,8 @@
** Written by Ralf S. Engelschall <rse@engelschall.com>
*/
+#ifdef EAPI
+
#include "httpd.h"
#include "ap_config.h"
#include "ap_ctx.h"
@@ -126,3 +128,28 @@ API_EXPORT(void *) ap_ctx_get(ap_ctx *ctx, char *key)
return NULL;
}
+API_EXPORT(ap_ctx *) ap_ctx_overlay(pool *p, ap_ctx *over, ap_ctx *base)
+{
+ ap_ctx *new;
+ int i;
+
+#ifdef POOL_DEBUG
+ if (p != NULL) {
+ if (!ap_pool_is_ancestor(over->cr_pool, p))
+ ap_log_assert("ap_ctx_overlay: overlay's pool is not an ancestor of p",
+ __FILE__, __LINE__);
+ if (!ap_pool_is_ancestor(base->cr_pool, p))
+ ap_log_assert("ap_ctx_overlay: base's pool is not an ancestor of p",
+ __FILE__, __LINE__);
+ }
+#endif
+ if ((new = ap_ctx_new(p)) == NULL)
+ return NULL;
+ memcpy(new->cr_entry, base->cr_entry,
+ sizeof(ap_ctx_entry *)*(AP_CTX_MAX_ENTRIES+1));
+ for (i = 0; over->cr_entry[i] != NULL; i++)
+ ap_ctx_set(new, over->cr_entry[i]->ce_key, over->cr_entry[i]->ce_val);
+ return new;
+}
+
+#endif /* EAPI */
diff --git a/usr.sbin/httpd/src/ap/ap_execve.c b/usr.sbin/httpd/src/ap/ap_execve.c
index 435334610c1..e126b8a5d76 100644
--- a/usr.sbin/httpd/src/ap/ap_execve.c
+++ b/usr.sbin/httpd/src/ap/ap_execve.c
@@ -126,8 +126,10 @@ int ap_execle(const char *filename, const char *argv0, ...)
}
va_end(adummy);
- if ((argv = (char **) malloc((argc + 2) * sizeof(*argv))) == NULL)
+ if ((argv = (char **) malloc((argc + 2) * sizeof(*argv))) == NULL) {
+ fprintf(stderr, "Ouch! Out of memory in ap_execle()!\n");
return -1;
+ }
/* Pass two --- copy the argument strings into the result space */
va_start(adummy, argv0);
@@ -222,8 +224,10 @@ int ap_execve(const char *filename, const char *argv[],
else {
int i = count_args(argv) + 1; /* +1 for leading SHELL_PATH */
- if ((script_argv = malloc(sizeof(*script_argv) * i)) == NULL)
+ if ((script_argv = malloc(sizeof(*script_argv) * i)) == NULL) {
+ fprintf(stderr, "Ouch! Out of memory in ap_execve()!\n");
return -1;
+ }
script_argv[0] = SHELL_PATH;
@@ -345,6 +349,10 @@ static const char **hashbang(const char *filename, char **argv)
newargv = (char **) malloc((p - lbuf + 1)
+ (i + sargc + 1) * sizeof(*newargv));
+ if (newargv == NULL) {
+ fprintf(stderr, "Ouch! Out of memory in hashbang()!\n");
+ return NULL;
+ }
ws = &((char *) newargv)[(i + sargc + 1) * sizeof(*newargv)];
/* Copy entries to allocated memory */
diff --git a/usr.sbin/httpd/src/ap/ap_getpass.c b/usr.sbin/httpd/src/ap/ap_getpass.c
new file mode 100644
index 00000000000..80988d16fdd
--- /dev/null
+++ b/usr.sbin/httpd/src/ap/ap_getpass.c
@@ -0,0 +1,167 @@
+/* ====================================================================
+ * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+/*
+ * ap_getpass.c: abstraction to provide for obtaining a password from the
+ * command line in whatever way the OS supports. In the best case, it's a
+ * wrapper for the system library's getpass() routine; otherwise, we
+ * use one we define ourselves.
+ */
+
+#include "ap_config.h"
+#include <sys/types.h>
+#include <errno.h>
+#include "ap.h"
+
+#ifdef WIN32
+#include <conio.h>
+#endif
+
+#ifndef CHARSET_EBCDIC
+#define LF 10
+#define CR 13
+#else /* CHARSET_EBCDIC */
+#define LF '\n'
+#define CR '\r'
+#endif /* CHARSET_EBCDIC */
+
+#define MAX_STRING_LEN 256
+
+#define ERR_OVERFLOW 5
+
+#ifdef MPE
+/*
+ * MPE lacks getpass() and a way to suppress stdin echo. So for now, just
+ * issue the prompt and read the results with echo. (Ugh).
+ */
+
+static char *getpass(const char *prompt)
+{
+ static char password[MAX_STRING_LEN];
+
+ fputs(prompt, stderr);
+ gets((char *) &password);
+
+ if (strlen((char *) &password) > (MAX_STRING_LEN - 1)) {
+ password[MAX_STRING_LEN - 1] = '\0';
+ }
+
+ return (char *) &password;
+}
+
+#endif
+
+#ifdef WIN32
+/*
+ * Windows lacks getpass(). So we'll re-implement it here.
+ */
+
+static char *getpass(const char *prompt)
+{
+ static char password[MAX_STRING_LEN];
+ int n = 0;
+
+ fputs(prompt, stderr);
+
+ while ((password[n] = _getch()) != '\r') {
+ if (password[n] >= ' ' && password[n] <= '~') {
+ n++;
+ printf("*");
+ }
+ else {
+ printf("\n");
+ fputs(prompt, stderr);
+ n = 0;
+ }
+ }
+
+ password[n] = '\0';
+ printf("\n");
+
+ if (n > (MAX_STRING_LEN - 1)) {
+ password[MAX_STRING_LEN - 1] = '\0';
+ }
+
+ return (char *) &password;
+}
+#endif
+
+/*
+ * Use the OS getpass() routine (or our own) to obtain a password from
+ * the input stream.
+ *
+ * Exit values:
+ * 0: Success
+ * 5: Partial success; entered text truncated to the size of the
+ * destination buffer
+ *
+ * Restrictions: Truncation also occurs according to the host system's
+ * getpass() semantics, or at position 255 if our own version is used,
+ * but the caller is *not* made aware of it.
+ */
+
+API_EXPORT(int) ap_getpass(const char *prompt, char *pwbuf, size_t bufsiz)
+{
+ char *pw_got;
+ int result = 0;
+
+ pw_got = getpass(prompt);
+ if (strlen(pw_got) > (bufsiz - 1)) {
+ result = ERR_OVERFLOW;
+ }
+ ap_cpystrn(pwbuf, pw_got, bufsiz);
+ return result;
+}
diff --git a/usr.sbin/httpd/src/ap/ap_hook.c b/usr.sbin/httpd/src/ap/ap_hook.c
index 532001bd417..3f649b63928 100644
--- a/usr.sbin/httpd/src/ap/ap_hook.c
+++ b/usr.sbin/httpd/src/ap/ap_hook.c
@@ -62,7 +62,8 @@
** Implementation of a Generic Hook Interface for Apache
** Written by Ralf S. Engelschall <rse@engelschall.com>
**
-** See ap_hook.h for documentation.
+** See POD document at end of ap_hook.h for description.
+** View it with the command ``pod2man ap_hook.h | nroff -man | more''
**
** Attention: This source file is a little bit tricky.
** It's a combination of a C source and an embedded Perl script
@@ -77,6 +78,8 @@
* -- D. E. Knuth
*/
+#ifdef EAPI
+
#include "httpd.h"
#include "http_log.h"
#include "ap_config.h"
@@ -208,7 +211,7 @@ API_EXPORT(int) ap_hook_configure(char *hook, ap_hook_sig sig, ap_hook_mode mode
else {
he->he_sig = sig;
he->he_modeid = modeid;
- if (modeid == AP_HOOK_MODE_DECLINE) {
+ if (modeid == AP_HOOK_MODE_DECLINE || modeid == AP_HOOK_MODE_DECLTMP) {
if (AP_HOOK_SIG_HAS(sig, RC, char))
he->he_modeval.v_char = va_arg(ap, va_type(char));
else if (AP_HOOK_SIG_HAS(sig, RC, int))
@@ -313,7 +316,7 @@ API_EXPORT(int) ap_hook_use(char *hook, ap_hook_sig sig, ap_hook_mode modeid, ..
va_start(ap, modeid);
- if (modeid == AP_HOOK_MODE_DECLINE) {
+ if (modeid == AP_HOOK_MODE_DECLINE || modeid == AP_HOOK_MODE_DECLTMP) {
if (AP_HOOK_SIG_HAS(sig, RC, char))
modeval.v_char = va_arg(ap, va_type(char));
else if (AP_HOOK_SIG_HAS(sig, RC, int))
@@ -393,6 +396,7 @@ API_EXPORT(int) ap_hook_call(char *hook, ...)
static int ap_hook_call_func(va_list ap, ap_hook_entry *he, ap_hook_func *hf)
{
void *v_rc;
+ ap_hook_value v_tmp;
int rc;
/*
@@ -444,21 +448,20 @@ static int ap_hook_call_func(va_list ap, ap_hook_entry *he, ap_hook_func *hf)
*
* 3. Actually currently used hooks.
*
- * int func(ptr,ptr,int) e.g. ap::buff::read [http_main.c]
- * int func(ptr,ptr,int) e.g. ap::buff::write [http_main.c]
- * int func(ptr,ptr,int) e.g. ap::buff::writev [http_main.c]
- * int func(ptr,ptr,int) e.g. ap::buff::sendwithtimeout [http_main.c]
- * int func(ptr,ptr,int) e.g. ap::buff::recvwithtimeout [http_main.c]
- * int func(ptr,ptr) e.g. ap::mod_proxy::canon [mod_proxy.c]
- * int func(ptr,ptr,ptr,int) e.g. ap::mod_proxy::http::canon [mod_proxy.c]
- * int func(ptr,ptr,ptr,ptr,int) e.g. ap::mod_proxy::http::handler [mod_proxy.c]
- * int func(ptr,ptr) e.g. ap::mod_proxy::error [mod_proxy.c]
- * int func(ptr,ptr,ptr,ptr,int,ptr) e.g. ap::mod_proxy::handler [mod_proxy.c]
- * int func(ptr) e.g. ap::mod_proxy::http::handler::set_destport [proxy_http.c]
- * ptr func(ptr,ptr) e.g. ap::mod_proxy::http::handler::new_connection [proxy_http.c]
- * int func(ptr,ptr,ptr,int,ptr) e.g. ap::mod_proxy::http::handler::write_host_header [proxy_http.c]
- * ptr func(ptr,ptr,ptr,ptr,ptr) e.g. ap::mod_ssl::var_lookup [ssl_engine_vars.c]
- * ptr func(ptr,ptr) e.g. ap::mod_rewrite::lookup_variable [mod_rewrite.c]
+ * int func(ptr) [2x]
+ * int func(ptr,ptr) [2x]
+ * int func(ptr,ptr,int) [5x]
+ * int func(ptr,ptr,ptr,int) [1x]
+ * int func(ptr,ptr,ptr,int,ptr) [1x]
+ * int func(ptr,ptr,ptr,ptr,int) [1x]
+ * int func(ptr,ptr,ptr,ptr,int,ptr) [1x]
+ * ptr func(ptr,ptr) [3x]
+ * ptr func(ptr,ptr,ptr,ptr,ptr) [1x]
+ * void func(ptr) [2x]
+ * void func(ptr,int,int) [1x]
+ * void func(ptr,ptr) [5x]
+ * void func(ptr,ptr,ptr) [3x]
+ * void func(ptr,ptr,ptr,ptr) [2x]
*
* To simplify the programming task we generate the actual dispatch code
* for these calls via the embedded Perl script at the end of this source
@@ -473,8 +476,27 @@ static int ap_hook_call_func(va_list ap, ap_hook_entry *he, ap_hook_func *hf)
rc = TRUE;
v_rc = NULL;
- if (!AP_HOOK_SIG_HAS(he->he_sig, RC, void))
- v_rc = va_arg(ap, void *);
+ if (!AP_HOOK_SIG_HAS(he->he_sig, RC, void)) {
+ if (he->he_modeid == AP_HOOK_MODE_DECLTMP) {
+ /* the return variable is a temporary one */
+ if (AP_HOOK_SIG_HAS(he->he_sig, RC, char))
+ v_rc = &v_tmp.v_char;
+ else if (AP_HOOK_SIG_HAS(he->he_sig, RC, int))
+ v_rc = &v_tmp.v_int;
+ else if (AP_HOOK_SIG_HAS(he->he_sig, RC, long))
+ v_rc = &v_tmp.v_long;
+ else if (AP_HOOK_SIG_HAS(he->he_sig, RC, float))
+ v_rc = &v_tmp.v_float;
+ else if (AP_HOOK_SIG_HAS(he->he_sig, RC, double))
+ v_rc = &v_tmp.v_double;
+ else if (AP_HOOK_SIG_HAS(he->he_sig, RC, ptr))
+ v_rc = &v_tmp.v_ptr;
+ }
+ else {
+ /* the return variable is provided by caller */
+ v_rc = va_arg(ap, void *);
+ }
+ }
/* ----BEGIN GENERATED SECTION-------- */
if (he->he_sig == AP_HOOK_SIG1(void)) {
@@ -708,6 +730,16 @@ static int ap_hook_call_func(va_list ap, ap_hook_entry *he, ap_hook_func *hf)
*((int *)v_rc) = ((int(*)(void *, void *, void *, int))(hf->hf_ptr))(v1, v2, v3, v4);
rc = (*((int *)v_rc) != he->he_modeval.v_int);
}
+ else if (he->he_sig == AP_HOOK_SIG6(int, ptr, ptr, ptr, int, ptr)) {
+ /* Call: int func(ptr,ptr,ptr,int,ptr) */
+ void *v1 = va_arg(ap, va_type(ptr));
+ void *v2 = va_arg(ap, va_type(ptr));
+ void *v3 = va_arg(ap, va_type(ptr));
+ int v4 = va_arg(ap, va_type(int));
+ void *v5 = va_arg(ap, va_type(ptr));
+ *((int *)v_rc) = ((int(*)(void *, void *, void *, int, void *))(hf->hf_ptr))(v1, v2, v3, v4, v5);
+ rc = (*((int *)v_rc) != he->he_modeval.v_int);
+ }
else if (he->he_sig == AP_HOOK_SIG6(int, ptr, ptr, ptr, ptr, int)) {
/* Call: int func(ptr,ptr,ptr,ptr,int) */
void *v1 = va_arg(ap, va_type(ptr));
@@ -729,16 +761,6 @@ static int ap_hook_call_func(va_list ap, ap_hook_entry *he, ap_hook_func *hf)
*((int *)v_rc) = ((int(*)(void *, void *, void *, void *, int, void *))(hf->hf_ptr))(v1, v2, v3, v4, v5, v6);
rc = (*((int *)v_rc) != he->he_modeval.v_int);
}
- else if (he->he_sig == AP_HOOK_SIG6(int, ptr, ptr, ptr, int, ptr)) {
- /* Call: int func(ptr,ptr,ptr,int,ptr) */
- void *v1 = va_arg(ap, va_type(ptr));
- void *v2 = va_arg(ap, va_type(ptr));
- void *v3 = va_arg(ap, va_type(ptr));
- int v4 = va_arg(ap, va_type(int));
- void *v5 = va_arg(ap, va_type(ptr));
- *((int *)v_rc) = ((int(*)(void *, void *, void *, int, void *))(hf->hf_ptr))(v1, v2, v3, v4, v5);
- rc = (*((int *)v_rc) != he->he_modeval.v_int);
- }
else if (he->he_sig == AP_HOOK_SIG6(ptr, ptr, ptr, ptr, ptr, ptr)) {
/* Call: ptr func(ptr,ptr,ptr,ptr,ptr) */
void *v1 = va_arg(ap, va_type(ptr));
@@ -749,11 +771,38 @@ static int ap_hook_call_func(va_list ap, ap_hook_entry *he, ap_hook_func *hf)
*((void * *)v_rc) = ((void *(*)(void *, void *, void *, void *, void *))(hf->hf_ptr))(v1, v2, v3, v4, v5);
rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
}
- else if (he->he_sig == AP_HOOK_SIG2(ptr, char)) {
- /* Call: ptr func(char) */
- char v1 = va_arg(ap, va_type(char));
- *((void * *)v_rc) = ((void *(*)(char))(hf->hf_ptr))(v1);
- rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
+ else if (he->he_sig == AP_HOOK_SIG2(void, ptr)) {
+ /* Call: void func(ptr) */
+ void *v1 = va_arg(ap, va_type(ptr));
+ ((void(*)(void *))(hf->hf_ptr))(v1);
+ }
+ else if (he->he_sig == AP_HOOK_SIG4(void, ptr, int, int)) {
+ /* Call: void func(ptr,int,int) */
+ void *v1 = va_arg(ap, va_type(ptr));
+ int v2 = va_arg(ap, va_type(int));
+ int v3 = va_arg(ap, va_type(int));
+ ((void(*)(void *, int, int))(hf->hf_ptr))(v1, v2, v3);
+ }
+ else if (he->he_sig == AP_HOOK_SIG3(void, ptr, ptr)) {
+ /* Call: void func(ptr,ptr) */
+ void *v1 = va_arg(ap, va_type(ptr));
+ void *v2 = va_arg(ap, va_type(ptr));
+ ((void(*)(void *, void *))(hf->hf_ptr))(v1, v2);
+ }
+ else if (he->he_sig == AP_HOOK_SIG4(void, ptr, ptr, ptr)) {
+ /* Call: void func(ptr,ptr,ptr) */
+ void *v1 = va_arg(ap, va_type(ptr));
+ void *v2 = va_arg(ap, va_type(ptr));
+ void *v3 = va_arg(ap, va_type(ptr));
+ ((void(*)(void *, void *, void *))(hf->hf_ptr))(v1, v2, v3);
+ }
+ else if (he->he_sig == AP_HOOK_SIG5(void, ptr, ptr, ptr, ptr)) {
+ /* Call: void func(ptr,ptr,ptr,ptr) */
+ void *v1 = va_arg(ap, va_type(ptr));
+ void *v2 = va_arg(ap, va_type(ptr));
+ void *v3 = va_arg(ap, va_type(ptr));
+ void *v4 = va_arg(ap, va_type(ptr));
+ ((void(*)(void *, void *, void *, void *))(hf->hf_ptr))(v1, v2, v3, v4);
}
/* ----END GENERATED SECTION---------- */
else
@@ -767,6 +816,8 @@ static int ap_hook_call_func(va_list ap, ap_hook_entry *he, ap_hook_func *hf)
return rc;
}
+#endif /* EAPI */
+
/*
=cut
##
@@ -785,6 +836,7 @@ my $end = '----END GENERATED SECTION----------';
if ($ARGV[0] eq 'used') {
my @S = `find .. -type f -name "*.c" -print`;
my $s;
+ my %T = ();
foreach $s (@S) {
$s =~ s|\n$||;
open(FP, "<$s") || die;
@@ -799,10 +851,15 @@ if ($ARGV[0] eq 'used') {
my ($rc, $args) = ($sig =~ m|^([^,]+)(.*)$|);
$args =~ s|^,||;
$src =~ s|^.+/||;
- printf(" * %-6s%-30s e.g. %s [%s]\n", $rc, "func($args)", $hook, $src);
+ my $sig = sprintf("%-6sfunc(%s)", $rc, $args);
+ $T{$sig}++;
}
$source =~ s|\("([^"]+)",\s*AP_HOOK_SIG[0-9]\((.+?)\)|&printme($s, $1, $2), ''|sge;
}
+ my $t;
+ foreach $t (sort(keys(%T))) {
+ printf(" * %-40s [%dx]\n", $t, $T{$t});
+ }
exit(0);
}
diff --git a/usr.sbin/httpd/src/main/md5c.c b/usr.sbin/httpd/src/ap/ap_md5c.c
index a94601d3109..7a8aee5965d 100644
--- a/usr.sbin/httpd/src/main/md5c.c
+++ b/usr.sbin/httpd/src/ap/ap_md5c.c
@@ -88,13 +88,28 @@
*
*/
+/*
+ * The ap_MD5Encode() routine uses much code obtained from the FreeBSD 3.0
+ * MD5 crypt() function, which is licenced as follows:
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ */
+
#include <string.h>
#include "ap_config.h"
#include "ap_md5.h"
+#include "ap.h"
#ifdef CHARSET_EBCDIC
#include "ebcdic.h"
#endif /*CHARSET_EBCDIC*/
+#if HAVE_CRYPT_H
+#include <crypt.h>
+#endif
/* Constants for MD5Transform routine.
*/
@@ -166,7 +181,7 @@ static unsigned char PADDING[64] =
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
-API_EXPORT(void) ap_MD5Init(AP_MD5_CTX * context)
+API_EXPORT(void) ap_MD5Init(AP_MD5_CTX *context)
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants. */
@@ -180,8 +195,8 @@ API_EXPORT(void) ap_MD5Init(AP_MD5_CTX * context)
operation, processing another message block, and updating the
context.
*/
-API_EXPORT(void) ap_MD5Update(AP_MD5_CTX * context, const unsigned char *input,
- unsigned int inputLen)
+API_EXPORT(void) ap_MD5Update(AP_MD5_CTX *context, const unsigned char *input,
+ unsigned int inputLen)
{
unsigned int i, idx, partLen;
@@ -189,8 +204,10 @@ API_EXPORT(void) ap_MD5Update(AP_MD5_CTX * context, const unsigned char *input,
idx = (unsigned int) ((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
- if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3))
+ if ((context->count[0] += ((UINT4) inputLen << 3))
+ < ((UINT4) inputLen << 3)) {
context->count[1]++;
+ }
context->count[1] += (UINT4) inputLen >> 29;
partLen = 64 - idx;
@@ -201,13 +218,15 @@ API_EXPORT(void) ap_MD5Update(AP_MD5_CTX * context, const unsigned char *input,
memcpy(&context->buffer[idx], input, partLen);
MD5Transform(context->state, context->buffer);
- for (i = partLen; i + 63 < inputLen; i += 64)
+ for (i = partLen; i + 63 < inputLen; i += 64) {
MD5Transform(context->state, &input[i]);
+ }
idx = 0;
}
- else
+ else {
i = 0;
+ }
/* Buffer remaining input */
memcpy(&context->buffer[idx], &input[i], inputLen - i);
@@ -224,8 +243,9 @@ API_EXPORT(void) ap_MD5Update(AP_MD5_CTX * context, const unsigned char *input,
idx = 0;
}
- else
+ else {
i = 0;
+ }
/* Buffer remaining input */
ebcdic2ascii_strictly(&context->buffer[idx], &input[i], inputLen - i);
@@ -235,7 +255,7 @@ API_EXPORT(void) ap_MD5Update(AP_MD5_CTX * context, const unsigned char *input,
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
-API_EXPORT(void) ap_MD5Final(unsigned char digest[16], AP_MD5_CTX * context)
+API_EXPORT(void) ap_MD5Final(unsigned char digest[16], AP_MD5_CTX *context)
{
unsigned char bits[8];
unsigned int idx, padLen;
@@ -262,10 +282,10 @@ API_EXPORT(void) ap_MD5Final(unsigned char digest[16], AP_MD5_CTX * context)
/* Pad out to 56 mod 64. */
idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
padLen = (idx < 56) ? (56 - idx) : (120 - idx);
- ap_MD5Update(context, PADDING, padLen);
+ ap_MD5Update(context, (const unsigned char *)PADDING, padLen);
/* Append length (before padding) */
- ap_MD5Update(context, bits, 8);
+ ap_MD5Update(context, (const unsigned char *)bits, 8);
/* Store state in digest */
Encode(digest, context->state, 16);
@@ -380,7 +400,7 @@ static void Encode(unsigned char *output, const UINT4 *input, unsigned int len)
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
- a multiple of 4.
+ * a multiple of 4.
*/
static void Decode(UINT4 *output, const unsigned char *input, unsigned int len)
{
@@ -390,3 +410,174 @@ static void Decode(UINT4 *output, const unsigned char *input, unsigned int len)
output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
(((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
}
+
+/*
+ * The following MD5 password encryption code was largely borrowed from
+ * the FreeBSD 3.0 /usr/src/lib/libcrypt/crypt.c file, which is
+ * licenced as stated at the top of this file.
+ */
+API_EXPORT(void) ap_to64(char *s, unsigned long v, int n)
+{
+ static unsigned char itoa64[] = /* 0 ... 63 => ASCII - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+ while (--n >= 0) {
+ *s++ = itoa64[v&0x3f];
+ v >>= 6;
+ }
+}
+
+API_EXPORT(void) ap_MD5Encode(const unsigned char *pw,
+ const unsigned char *salt,
+ char *result, size_t nbytes)
+{
+ /*
+ * Minimum size is 8 bytes for salt, plus 1 for the trailing NUL,
+ * plus 4 for the '$' separators, plus the password hash itself.
+ * Let's leave a goodly amount of leeway.
+ */
+
+ char passwd[120], *p;
+ const unsigned char *sp, *ep;
+ unsigned char final[16];
+ int i;
+ unsigned int sl;
+ int pl;
+ unsigned int pwlen;
+ AP_MD5_CTX ctx, ctx1;
+ unsigned long l;
+
+ /*
+ * Refine the salt first. It's possible we were given an already-hashed
+ * string as the salt argument, so extract the actual salt value from it
+ * if so. Otherwise just use the string up to the first '$' as the salt.
+ */
+ sp = salt;
+
+ /*
+ * If it starts with the magic string, then skip that.
+ */
+ if (strncmp((char *)sp, AP_MD5PW_ID, AP_MD5PW_IDLEN) == 0) {
+ sp += AP_MD5PW_IDLEN;
+ }
+
+ /*
+ * It stops at the first '$' or 8 chars, whichever comes first
+ */
+ for (ep = sp; (*ep != '\0') && (*ep != '$') && (ep < (sp + 8)); ep++) {
+ continue;
+ }
+
+ /*
+ * Get the length of the true salt
+ */
+ sl = ep - sp;
+
+ /*
+ * 'Time to make the doughnuts..'
+ */
+ ap_MD5Init(&ctx);
+
+ pwlen = strlen((char *)pw);
+ /*
+ * The password first, since that is what is most unknown
+ */
+ ap_MD5Update(&ctx, pw, pwlen);
+
+ /*
+ * Then our magic string
+ */
+ ap_MD5Update(&ctx, (const unsigned char *) AP_MD5PW_ID, AP_MD5PW_IDLEN);
+
+ /*
+ * Then the raw salt
+ */
+ ap_MD5Update(&ctx, sp, sl);
+
+ /*
+ * Then just as many characters of the MD5(pw, salt, pw)
+ */
+ ap_MD5Init(&ctx1);
+ ap_MD5Update(&ctx1, pw, pwlen);
+ ap_MD5Update(&ctx1, sp, sl);
+ ap_MD5Update(&ctx1, pw, pwlen);
+ ap_MD5Final(final, &ctx1);
+ for(pl = pwlen; pl > 0; pl -= 16) {
+ ap_MD5Update(&ctx, final, (pl > 16) ? 16 : (unsigned int) pl);
+ }
+
+ /*
+ * Don't leave anything around in vm they could use.
+ */
+ memset(final, 0, sizeof(final));
+
+ /*
+ * Then something really weird...
+ */
+ for (i = pwlen; i != 0; i >>= 1) {
+ if (i & 1) {
+ ap_MD5Update(&ctx, final, 1);
+ }
+ else {
+ ap_MD5Update(&ctx, pw, 1);
+ }
+ }
+
+ /*
+ * Now make the output string. We know our limitations, so we
+ * can use the string routines without bounds checking.
+ */
+ ap_cpystrn(passwd, AP_MD5PW_ID, AP_MD5PW_IDLEN + 1);
+ ap_cpystrn(passwd + AP_MD5PW_IDLEN, (char *)sp, sl + 1);
+ passwd[AP_MD5PW_IDLEN + sl] = '$';
+ passwd[AP_MD5PW_IDLEN + sl + 1] = '\0';
+
+ ap_MD5Final(final, &ctx);
+
+ /*
+ * And now, just to make sure things don't run too fast..
+ * On a 60 Mhz Pentium this takes 34 msec, so you would
+ * need 30 seconds to build a 1000 entry dictionary...
+ */
+ for (i = 0; i < 1000; i++) {
+ ap_MD5Init(&ctx1);
+ if (i & 1) {
+ ap_MD5Update(&ctx1, pw, pwlen);
+ }
+ else {
+ ap_MD5Update(&ctx1, final, 16);
+ }
+ if (i % 3) {
+ ap_MD5Update(&ctx1, sp, sl);
+ }
+
+ if (i % 7) {
+ ap_MD5Update(&ctx1, pw, pwlen);
+ }
+
+ if (i & 1) {
+ ap_MD5Update(&ctx1, final, 16);
+ }
+ else {
+ ap_MD5Update(&ctx1, pw, pwlen);
+ }
+ ap_MD5Final(final,&ctx1);
+ }
+
+ p = passwd + strlen(passwd);
+
+ l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; ap_to64(p, l, 4); p += 4;
+ l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; ap_to64(p, l, 4); p += 4;
+ l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; ap_to64(p, l, 4); p += 4;
+ l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; ap_to64(p, l, 4); p += 4;
+ l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; ap_to64(p, l, 4); p += 4;
+ l = final[11] ; ap_to64(p, l, 2); p += 2;
+ *p = '\0';
+
+ /*
+ * Don't leave anything around in vm they could use.
+ */
+ memset(final, 0, sizeof(final));
+
+ ap_cpystrn(result, passwd, nbytes - 1);
+}
diff --git a/usr.sbin/httpd/src/ap/ap_mm.c b/usr.sbin/httpd/src/ap/ap_mm.c
new file mode 100644
index 00000000000..198b99c515f
--- /dev/null
+++ b/usr.sbin/httpd/src/ap/ap_mm.c
@@ -0,0 +1,178 @@
+/* ====================================================================
+ * Copyright (c) 1999 The Apache Group. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ */
+
+/*
+** ap_mm.c -- wrapper for MM shared memory library
+**
+** This file has two reason:
+**
+** 1. Under DSO context we need stubs inside the Apache core code
+** to make sure the MM library's code is actually available
+** to the module DSOs.
+**
+** 2. When the MM library cannot be built on the current platform
+** still provide dummy stubs so modules using the ap_mm_xxx()
+** functions can be still built. But modules should use
+** ap_mm_useable() to find out whether they really can use
+** the MM stuff.
+*/
+ /*
+ * "What you see is all you get."
+ * -- Brian Kernighan
+ */
+#ifdef EAPI
+
+#include "httpd.h"
+#include "ap_mm.h"
+
+#ifdef EAPI_MM
+#include "mm.h"
+API_EXPORT(int) ap_mm_useable(void) { return TRUE; }
+#define STUB(val,nul) { return val; }
+#define STUB_STMT(stmt) { stmt; return; }
+#else
+API_EXPORT(int) ap_mm_useable(void) { return FALSE; }
+#define STUB(val,nul) { return nul; }
+#define STUB_STMT(stmt) { return; }
+#endif
+
+API_EXPORT(int) ap_MM_create(size_t size, char *file)
+ STUB(MM_create(size, file), FALSE)
+API_EXPORT(int) ap_MM_permission(mode_t mode, uid_t owner, gid_t group)
+ STUB(MM_permission(mode, owner, group), -1)
+API_EXPORT(void) ap_MM_destroy(void)
+ STUB_STMT(MM_destroy())
+API_EXPORT(int) ap_MM_lock(ap_mm_lock_mode mode)
+ STUB(MM_lock(mode), FALSE)
+API_EXPORT(int) ap_MM_unlock(void)
+ STUB(MM_unlock(), FALSE)
+API_EXPORT(void *) ap_MM_malloc(size_t size)
+ STUB(MM_malloc(size), NULL)
+API_EXPORT(void *) ap_MM_realloc(void *ptr, size_t size)
+ STUB(MM_realloc(ptr, size), NULL)
+API_EXPORT(void) ap_MM_free(void *ptr)
+ STUB_STMT(MM_free(ptr))
+API_EXPORT(void *) ap_MM_calloc(size_t number, size_t size)
+ STUB(MM_calloc(number, size), NULL)
+API_EXPORT(char *) ap_MM_strdup(const char *str)
+ STUB(MM_strdup(str), NULL)
+API_EXPORT(size_t) ap_MM_sizeof(void *ptr)
+ STUB(MM_sizeof(ptr), 0)
+API_EXPORT(size_t) ap_MM_maxsize(void)
+ STUB(MM_maxsize(), 0)
+API_EXPORT(size_t) ap_MM_available(void)
+ STUB(MM_available(), 0)
+API_EXPORT(char *) ap_MM_error(void)
+ STUB(MM_error(), NULL)
+
+API_EXPORT(AP_MM *) ap_mm_create(size_t size, char *file)
+ STUB(mm_create(size, file), NULL)
+API_EXPORT(int) ap_mm_permission(AP_MM *mm, mode_t mode, uid_t owner, gid_t group)
+ STUB(mm_permission(mm, mode, owner, group), -1)
+API_EXPORT(void) ap_mm_destroy(AP_MM *mm)
+ STUB_STMT(mm_destroy(mm))
+API_EXPORT(int) ap_mm_lock(AP_MM *mm, ap_mm_lock_mode mode)
+ STUB(mm_lock(mm, mode), FALSE)
+API_EXPORT(int) ap_mm_unlock(AP_MM *mm)
+ STUB(mm_unlock(mm), FALSE)
+API_EXPORT(void *) ap_mm_malloc(AP_MM *mm, size_t size)
+ STUB(mm_malloc(mm, size), NULL)
+API_EXPORT(void *) ap_mm_realloc(AP_MM *mm, void *ptr, size_t size)
+ STUB(mm_realloc(mm, ptr, size), NULL)
+API_EXPORT(void) ap_mm_free(AP_MM *mm, void *ptr)
+ STUB_STMT(mm_free(mm, ptr))
+API_EXPORT(void *) ap_mm_calloc(AP_MM *mm, size_t number, size_t size)
+ STUB(mm_calloc(mm, number, size), NULL)
+API_EXPORT(char *) ap_mm_strdup(AP_MM *mm, const char *str)
+ STUB(mm_strdup(mm, str), NULL)
+API_EXPORT(size_t) ap_mm_sizeof(AP_MM *mm, void *ptr)
+ STUB(mm_sizeof(mm, ptr), 0)
+API_EXPORT(size_t) ap_mm_maxsize(void)
+ STUB(mm_maxsize(), 0)
+API_EXPORT(size_t) ap_mm_available(AP_MM *mm)
+ STUB(mm_available(mm), 0)
+API_EXPORT(char *) ap_mm_error(void)
+ STUB(mm_error(), NULL)
+API_EXPORT(void) ap_mm_display_info(AP_MM *mm)
+ STUB_STMT(mm_display_info(mm))
+
+API_EXPORT(void *) ap_mm_core_create(size_t size, char *file)
+ STUB(mm_core_create(size, file), NULL)
+API_EXPORT(int) ap_mm_core_permission(void *core, mode_t mode, uid_t owner, gid_t group)
+ STUB(mm_core_permission(core, mode, owner, group), -1)
+API_EXPORT(void) ap_mm_core_delete(void *core)
+ STUB_STMT(mm_core_delete(core))
+API_EXPORT(size_t) ap_mm_core_size(void *core)
+ STUB(mm_core_size(core), 0)
+API_EXPORT(int) ap_mm_core_lock(void *core, ap_mm_lock_mode mode)
+ STUB(mm_core_lock(core, mode), FALSE)
+API_EXPORT(int) ap_mm_core_unlock(void *core)
+ STUB(mm_core_unlock(core), FALSE)
+API_EXPORT(size_t) ap_mm_core_maxsegsize(void)
+ STUB(mm_core_maxsegsize(), 0)
+API_EXPORT(size_t) ap_mm_core_align2page(size_t size)
+ STUB(mm_core_align2page(size), 0)
+API_EXPORT(size_t) ap_mm_core_align2word(size_t size)
+ STUB(mm_core_align2word(size), 0)
+
+API_EXPORT(void) ap_mm_lib_error_set(unsigned int type, const char *str)
+ STUB_STMT(mm_lib_error_set(type, str))
+API_EXPORT(char *) ap_mm_lib_error_get(void)
+ STUB(mm_lib_error_get(), NULL)
+API_EXPORT(int) ap_mm_lib_version(void)
+ STUB(mm_lib_version(), 0)
+
+#endif /* EAPI */
diff --git a/usr.sbin/httpd/src/ap/ap_sha1.c b/usr.sbin/httpd/src/ap/ap_sha1.c
new file mode 100644
index 00000000000..1d4d9ea49b6
--- /dev/null
+++ b/usr.sbin/httpd/src/ap/ap_sha1.c
@@ -0,0 +1,383 @@
+/* ====================================================================
+ * Copyright (c) 1996-1999 The Apache Group. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ * The exported function:
+ *
+ * ap_sha1_base64(const char *clear, int len, char *out);
+ *
+ * provides a means to SHA1 crypt/encode a plaintext password in
+ * a way which makes password files compatible with those commonly
+ * used in netscape web and ldap installations. It was put together
+ * by Clinton Wong <clintdw@netcom.com>, who also notes that:
+ *
+ * Note: SHA1 support is useful for migration purposes, but is less
+ * secure than Apache's password format, since Apache's (MD5)
+ * password format uses a random eight character salt to generate
+ * one of many possible hashes for the same password. Netscape
+ * uses plain SHA1 without a salt, so the same password
+ * will always generate the same hash, making it easier
+ * to break since the search space is smaller.
+ *
+ * See also the documentation in support/SHA1 as to hints on how to
+ * migrate an existing netscape installation and other supplied utitlites.
+ *
+ * This software also makes use of the following component:
+ *
+ * NIST Secure Hash Algorithm
+ * heavily modified by Uwe Hollerbach uh@alumni.caltech edu
+ * from Peter C. Gutmann's implementation as found in
+ * Applied Cryptography by Bruce Schneier
+ * This code is hereby placed in the public domain
+ */
+
+#include <string.h>
+
+#include "ap_config.h"
+#include "ap_sha1.h"
+#include "ap.h"
+#ifdef CHARSET_EBCDIC
+#include "ebcdic.h"
+#endif /*CHARSET_EBCDIC*/
+
+/* a bit faster & bigger, if defined */
+#define UNROLL_LOOPS
+
+/* NIST's proposed modification to SHA, 7/11/94 */
+#define USE_MODIFIED_SHA
+
+/* SHA f()-functions */
+#define f1(x,y,z) ((x & y) | (~x & z))
+#define f2(x,y,z) (x ^ y ^ z)
+#define f3(x,y,z) ((x & y) | (x & z) | (y & z))
+#define f4(x,y,z) (x ^ y ^ z)
+
+/* SHA constants */
+#define CONST1 0x5a827999L
+#define CONST2 0x6ed9eba1L
+#define CONST3 0x8f1bbcdcL
+#define CONST4 0xca62c1d6L
+
+/* 32-bit rotate */
+
+#define ROT32(x,n) ((x << n) | (x >> (32 - n)))
+
+#define FUNC(n,i) \
+ temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n; \
+ E = D; D = C; C = ROT32(B,30); B = A; A = temp
+
+#define SHA_BLOCKSIZE 64
+
+typedef unsigned char AP_BYTE;
+
+/* do SHA transformation */
+static void sha_transform(AP_SHA1_CTX *sha_info)
+{
+ int i;
+ AP_LONG temp, A, B, C, D, E, W[80];
+
+ for (i = 0; i < 16; ++i) {
+ W[i] = sha_info->data[i];
+ }
+ for (i = 16; i < 80; ++i) {
+ W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
+#ifdef USE_MODIFIED_SHA
+ W[i] = ROT32(W[i], 1);
+#endif /* USE_MODIFIED_SHA */
+ }
+ A = sha_info->digest[0];
+ B = sha_info->digest[1];
+ C = sha_info->digest[2];
+ D = sha_info->digest[3];
+ E = sha_info->digest[4];
+#ifdef UNROLL_LOOPS
+ FUNC(1, 0); FUNC(1, 1); FUNC(1, 2); FUNC(1, 3); FUNC(1, 4);
+ FUNC(1, 5); FUNC(1, 6); FUNC(1, 7); FUNC(1, 8); FUNC(1, 9);
+ FUNC(1,10); FUNC(1,11); FUNC(1,12); FUNC(1,13); FUNC(1,14);
+ FUNC(1,15); FUNC(1,16); FUNC(1,17); FUNC(1,18); FUNC(1,19);
+
+ FUNC(2,20); FUNC(2,21); FUNC(2,22); FUNC(2,23); FUNC(2,24);
+ FUNC(2,25); FUNC(2,26); FUNC(2,27); FUNC(2,28); FUNC(2,29);
+ FUNC(2,30); FUNC(2,31); FUNC(2,32); FUNC(2,33); FUNC(2,34);
+ FUNC(2,35); FUNC(2,36); FUNC(2,37); FUNC(2,38); FUNC(2,39);
+
+ FUNC(3,40); FUNC(3,41); FUNC(3,42); FUNC(3,43); FUNC(3,44);
+ FUNC(3,45); FUNC(3,46); FUNC(3,47); FUNC(3,48); FUNC(3,49);
+ FUNC(3,50); FUNC(3,51); FUNC(3,52); FUNC(3,53); FUNC(3,54);
+ FUNC(3,55); FUNC(3,56); FUNC(3,57); FUNC(3,58); FUNC(3,59);
+
+ FUNC(4,60); FUNC(4,61); FUNC(4,62); FUNC(4,63); FUNC(4,64);
+ FUNC(4,65); FUNC(4,66); FUNC(4,67); FUNC(4,68); FUNC(4,69);
+ FUNC(4,70); FUNC(4,71); FUNC(4,72); FUNC(4,73); FUNC(4,74);
+ FUNC(4,75); FUNC(4,76); FUNC(4,77); FUNC(4,78); FUNC(4,79);
+#else /* !UNROLL_LOOPS */
+ for (i = 0; i < 20; ++i) {
+ FUNC(1,i);
+ }
+ for (i = 20; i < 40; ++i) {
+ FUNC(2,i);
+ }
+ for (i = 40; i < 60; ++i) {
+ FUNC(3,i);
+ }
+ for (i = 60; i < 80; ++i) {
+ FUNC(4,i);
+ }
+#endif /* !UNROLL_LOOPS */
+ sha_info->digest[0] += A;
+ sha_info->digest[1] += B;
+ sha_info->digest[2] += C;
+ sha_info->digest[3] += D;
+ sha_info->digest[4] += E;
+}
+
+union endianTest {
+ long Long;
+ char Char[sizeof(long)];
+};
+
+static char isLittleEndian(void)
+{
+ static union endianTest u;
+ u.Long = 1;
+ return (u.Char[0] == 1);
+}
+
+/* change endianness of data */
+
+/* count is the number of bytes to do an endian flip */
+static void maybe_byte_reverse(AP_LONG *buffer, int count)
+{
+ int i;
+ AP_BYTE ct[4], *cp;
+
+ if (isLittleEndian()) { /* do the swap only if it is little endian */
+ count /= sizeof(AP_LONG);
+ cp = (AP_BYTE *) buffer;
+ for (i = 0; i < count; ++i) {
+ ct[0] = cp[0];
+ ct[1] = cp[1];
+ ct[2] = cp[2];
+ ct[3] = cp[3];
+ cp[0] = ct[3];
+ cp[1] = ct[2];
+ cp[2] = ct[1];
+ cp[3] = ct[0];
+ cp += sizeof(AP_LONG);
+ }
+ }
+}
+
+/* initialize the SHA digest */
+
+API_EXPORT(void) ap_SHA1Init(AP_SHA1_CTX *sha_info)
+{
+ sha_info->digest[0] = 0x67452301L;
+ sha_info->digest[1] = 0xefcdab89L;
+ sha_info->digest[2] = 0x98badcfeL;
+ sha_info->digest[3] = 0x10325476L;
+ sha_info->digest[4] = 0xc3d2e1f0L;
+ sha_info->count_lo = 0L;
+ sha_info->count_hi = 0L;
+ sha_info->local = 0;
+}
+
+/* update the SHA digest */
+
+API_EXPORT(void) ap_SHA1Update_binary(AP_SHA1_CTX *sha_info,
+ const unsigned char *buffer,
+ unsigned int count)
+{
+ unsigned int i;
+
+ if ((sha_info->count_lo + ((AP_LONG) count << 3)) < sha_info->count_lo) {
+ ++sha_info->count_hi;
+ }
+ sha_info->count_lo += (AP_LONG) count << 3;
+ sha_info->count_hi += (AP_LONG) count >> 29;
+ if (sha_info->local) {
+ i = SHA_BLOCKSIZE - sha_info->local;
+ if (i > count) {
+ i = count;
+ }
+ memcpy(((AP_BYTE *) sha_info->data) + sha_info->local, buffer, i);
+ count -= i;
+ buffer += i;
+ sha_info->local += i;
+ if (sha_info->local == SHA_BLOCKSIZE) {
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ else {
+ return;
+ }
+ }
+ while (count >= SHA_BLOCKSIZE) {
+ memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
+ buffer += SHA_BLOCKSIZE;
+ count -= SHA_BLOCKSIZE;
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ memcpy(sha_info->data, buffer, count);
+ sha_info->local = count;
+}
+
+API_EXPORT(void) ap_SHA1Update(AP_SHA1_CTX *sha_info, const char *buf,
+ unsigned int count)
+{
+#ifdef CHARSET_EBCDIC
+ int i;
+ const AP_BYTE *buffer = (const AP_BYTE *) buf;
+
+ if ((sha_info->count_lo + ((AP_LONG) count << 3)) < sha_info->count_lo) {
+ ++sha_info->count_hi;
+ }
+ sha_info->count_lo += (AP_LONG) count << 3;
+ sha_info->count_hi += (AP_LONG) count >> 29;
+ /* Is there a remainder of the previous Update operation? */
+ if (sha_info->local) {
+ i = SHA_BLOCKSIZE - sha_info->local;
+ if (i > count) {
+ i = count;
+ }
+ ebcdic2ascii_strictly(((AP_BYTE *) sha_info->data) + sha_info->local,
+ buffer, i);
+ count -= i;
+ buffer += i;
+ sha_info->local += i;
+ if (sha_info->local == SHA_BLOCKSIZE) {
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ else {
+ return;
+ }
+ }
+ while (count >= SHA_BLOCKSIZE) {
+ ebcdic2ascii_strictly((AP_BYTE *)sha_info->data, buffer, SHA_BLOCKSIZE);
+ buffer += SHA_BLOCKSIZE;
+ count -= SHA_BLOCKSIZE;
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ ebcdic2ascii_strictly((AP_BYTE *)sha_info->data, buffer, count);
+ sha_info->local = count;
+#else
+ ap_SHA1Update_binary(sha_info, (const unsigned char *) buf, count);
+#endif
+}
+
+/* finish computing the SHA digest */
+
+API_EXPORT(void) ap_SHA1Final(unsigned char digest[SHA_DIGESTSIZE],
+ AP_SHA1_CTX *sha_info)
+{
+ int count, i, j;
+ AP_LONG lo_bit_count, hi_bit_count, k;
+
+ lo_bit_count = sha_info->count_lo;
+ hi_bit_count = sha_info->count_hi;
+ count = (int) ((lo_bit_count >> 3) & 0x3f);
+ ((AP_BYTE *) sha_info->data)[count++] = 0x80;
+ if (count > SHA_BLOCKSIZE - 8) {
+ memset(((AP_BYTE *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ memset((AP_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
+ }
+ else {
+ memset(((AP_BYTE *) sha_info->data) + count, 0,
+ SHA_BLOCKSIZE - 8 - count);
+ }
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_info->data[14] = hi_bit_count;
+ sha_info->data[15] = lo_bit_count;
+ sha_transform(sha_info);
+
+ for (i = 0, j = 0; j < SHA_DIGESTSIZE; i++) {
+ k = sha_info->digest[i];
+ digest[j++] = (unsigned char) ((k >> 24) & 0xff);
+ digest[j++] = (unsigned char) ((k >> 16) & 0xff);
+ digest[j++] = (unsigned char) ((k >> 8) & 0xff);
+ digest[j++] = (unsigned char) (k & 0xff);
+ }
+}
+
+
+API_EXPORT(void) ap_sha1_base64(const char *clear, int len, char *out)
+{
+ int l;
+ AP_SHA1_CTX context;
+ AP_BYTE digest[SHA_DIGESTSIZE];
+
+ if (strncmp(clear, AP_SHA1PW_ID, AP_SHA1PW_IDLEN) == 0) {
+ clear += AP_SHA1PW_IDLEN;
+ }
+
+ ap_SHA1Init(&context);
+ ap_SHA1Update(&context, clear, len);
+ ap_SHA1Final(digest, &context);
+
+ /* private marker. */
+ ap_cpystrn(out, AP_SHA1PW_ID, AP_SHA1PW_IDLEN + 1);
+
+ /* SHA1 hash is always 20 chars */
+ l = ap_base64encode_binary(out + AP_SHA1PW_IDLEN, digest, sizeof(digest));
+ out[l + AP_SHA1PW_IDLEN] = '\0';
+
+ /*
+ * output of base64 encoded SHA1 is always 28 chars + AP_SHA1PW_IDLEN
+ */
+}
diff --git a/usr.sbin/httpd/src/ap/ap_snprintf.c b/usr.sbin/httpd/src/ap/ap_snprintf.c
index 19292a92792..648d55fca74 100644
--- a/usr.sbin/httpd/src/ap/ap_snprintf.c
+++ b/usr.sbin/httpd/src/ap/ap_snprintf.c
@@ -78,12 +78,23 @@ typedef enum {
#ifndef TRUE
#define TRUE 1
#endif
+#ifndef AP_LONGEST_LONG
+#define AP_LONGEST_LONG long
+#endif
#define NUL '\0'
#define INT_NULL ((int *)0)
#define WIDE_INT long
+#define WIDEST_INT AP_LONGEST_LONG
typedef WIDE_INT wide_int;
typedef unsigned WIDE_INT u_wide_int;
+typedef WIDEST_INT widest_int;
+#ifdef __TANDEM
+/* Although Tandem supports "long long" there is no unsigned variant. */
+typedef unsigned long u_widest_int;
+#else
+typedef unsigned WIDEST_INT u_widest_int;
+#endif
typedef int bool_int;
#define S_NULL "(null)"
@@ -338,6 +349,10 @@ static char *ap_gcvt(double number, int ndigit, char *buf, boolean_e altform)
* The caller provides a buffer for the string: that is the buf_end argument
* which is a pointer to the END of the buffer + 1 (i.e. if the buffer
* is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
+ *
+ * Note: we have 2 versions. One is used when we need to use quads
+ * (conv_10_quad), the other when we don't (conv_10). We're assuming the
+ * latter is faster.
*/
static char *conv_10(register wide_int num, register bool_int is_unsigned,
register bool_int *is_negative, char *buf_end,
@@ -386,6 +401,61 @@ static char *conv_10(register wide_int num, register bool_int is_unsigned,
return (p);
}
+static char *conv_10_quad(register widest_int num, register bool_int is_unsigned,
+ register bool_int *is_negative, char *buf_end,
+ register int *len)
+{
+ register char *p = buf_end;
+ register u_widest_int magnitude;
+
+ /*
+ * If the value is less than the maximum unsigned long value,
+ * then we know we aren't using quads, so use the faster function
+ */
+ if (num <= ULONG_MAX)
+ return(conv_10( (wide_int)num, is_unsigned, is_negative,
+ buf_end, len));
+
+ if (is_unsigned) {
+ magnitude = (u_widest_int) num;
+ *is_negative = FALSE;
+ }
+ else {
+ *is_negative = (num < 0);
+
+ /*
+ * On a 2's complement machine, negating the most negative integer
+ * results in a number that cannot be represented as a signed integer.
+ * Here is what we do to obtain the number's magnitude:
+ * a. add 1 to the number
+ * b. negate it (becomes positive)
+ * c. convert it to unsigned
+ * d. add 1
+ */
+ if (*is_negative) {
+ widest_int t = num + 1;
+
+ magnitude = ((u_widest_int) -t) + 1;
+ }
+ else
+ magnitude = (u_widest_int) num;
+ }
+
+ /*
+ * We use a do-while loop so that we write at least 1 digit
+ */
+ do {
+ register u_widest_int new_magnitude = magnitude / 10;
+
+ *--p = (char) (magnitude - new_magnitude * 10 + '0');
+ magnitude = new_magnitude;
+ }
+ while (magnitude);
+
+ *len = buf_end - p;
+ return (p);
+}
+
static char *conv_in_addr(struct in_addr *ia, char *buf_end, int *len)
@@ -525,6 +595,9 @@ static char *conv_fp(register char format, register double num,
* The caller provides a buffer for the string: that is the buf_end argument
* which is a pointer to the END of the buffer + 1 (i.e. if the buffer
* is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
+ *
+ * As with conv_10, we have a faster version which is used when
+ * the number isn't quad size.
*/
static char *conv_p2(register u_wide_int num, register int nbits,
char format, char *buf_end, register int *len)
@@ -545,6 +618,28 @@ static char *conv_p2(register u_wide_int num, register int nbits,
return (p);
}
+static char *conv_p2_quad(register u_widest_int num, register int nbits,
+ char format, char *buf_end, register int *len)
+{
+ register int mask = (1 << nbits) - 1;
+ register char *p = buf_end;
+ static const char low_digits[] = "0123456789abcdef";
+ static const char upper_digits[] = "0123456789ABCDEF";
+ register const char *digits = (format == 'X') ? upper_digits : low_digits;
+
+ if (num <= ULONG_MAX)
+ return(conv_p2( (u_wide_int)num, nbits, format, buf_end, len));
+
+ do {
+ *--p = digits[num & mask];
+ num >>= nbits;
+ }
+ while (num);
+
+ *len = buf_end - p;
+ return (p);
+}
+
/*
* Do format conversion placing the output in buffer
@@ -570,16 +665,22 @@ API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
char prefix_char;
double fp_num;
+ widest_int i_quad = (widest_int) 0;
+ u_widest_int ui_quad;
wide_int i_num = (wide_int) 0;
u_wide_int ui_num;
char num_buf[NUM_BUF_SIZE];
char char_buf[2]; /* for printing %% and %<unknown> */
+ enum var_type_enum {
+ IS_QUAD, IS_LONG, IS_SHORT, IS_INT
+ };
+ enum var_type_enum var_type = IS_INT;
+
/*
* Flag variables
*/
- boolean_e is_long;
boolean_e alternate_form;
boolean_e print_sign;
boolean_e print_blank;
@@ -677,14 +778,20 @@ API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
/*
* Modifier check
*/
- if (*fmt == 'l') {
- is_long = YES;
+ if (*fmt == 'q') {
+ var_type = IS_QUAD;
+ fmt++;
+ }
+ else if (*fmt == 'l') {
+ var_type = IS_LONG;
+ fmt++;
+ }
+ else if (*fmt == 'h') {
+ var_type = IS_SHORT;
fmt++;
}
else {
- if (*fmt == 'h') /* "short" backward compatibility */
- ++fmt;
- is_long = NO;
+ var_type = IS_INT;
}
/*
@@ -700,23 +807,41 @@ API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
*/
switch (*fmt) {
case 'u':
- if (is_long)
- i_num = va_arg(ap, u_wide_int);
- else
- i_num = (wide_int) va_arg(ap, unsigned int);
- s = conv_10(i_num, 1, &is_negative,
+ if (var_type == IS_QUAD) {
+ i_quad = va_arg(ap, u_widest_int);
+ s = conv_10_quad(i_quad, 1, &is_negative,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ else {
+ if (var_type == IS_LONG)
+ i_num = (wide_int) va_arg(ap, u_wide_int);
+ else if (var_type == IS_SHORT)
+ i_num = (wide_int) (unsigned short) va_arg(ap, unsigned int);
+ else
+ i_num = (wide_int) va_arg(ap, unsigned int);
+ s = conv_10(i_num, 1, &is_negative,
&num_buf[NUM_BUF_SIZE], &s_len);
+ }
FIX_PRECISION(adjust_precision, precision, s, s_len);
break;
case 'd':
case 'i':
- if (is_long)
- i_num = va_arg(ap, wide_int);
- else
- i_num = (wide_int) va_arg(ap, int);
- s = conv_10(i_num, 0, &is_negative,
+ if (var_type == IS_QUAD) {
+ i_quad = va_arg(ap, widest_int);
+ s = conv_10_quad(i_quad, 0, &is_negative,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ else {
+ if (var_type == IS_LONG)
+ i_num = (wide_int) va_arg(ap, wide_int);
+ else if (var_type == IS_SHORT)
+ i_num = (wide_int) (short) va_arg(ap, int);
+ else
+ i_num = (wide_int) va_arg(ap, int);
+ s = conv_10(i_num, 0, &is_negative,
&num_buf[NUM_BUF_SIZE], &s_len);
+ }
FIX_PRECISION(adjust_precision, precision, s, s_len);
if (is_negative)
@@ -729,12 +854,21 @@ API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
case 'o':
- if (is_long)
- ui_num = va_arg(ap, u_wide_int);
- else
- ui_num = (u_wide_int) va_arg(ap, unsigned int);
- s = conv_p2(ui_num, 3, *fmt,
+ if (var_type == IS_QUAD) {
+ ui_quad = va_arg(ap, u_widest_int);
+ s = conv_p2_quad(ui_quad, 3, *fmt,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ else {
+ if (var_type == IS_LONG)
+ ui_num = (u_wide_int) va_arg(ap, u_wide_int);
+ else if (var_type == IS_SHORT)
+ ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int);
+ else
+ ui_num = (u_wide_int) va_arg(ap, unsigned int);
+ s = conv_p2(ui_num, 3, *fmt,
&num_buf[NUM_BUF_SIZE], &s_len);
+ }
FIX_PRECISION(adjust_precision, precision, s, s_len);
if (alternate_form && *s != '0') {
*--s = '0';
@@ -745,12 +879,21 @@ API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
case 'x':
case 'X':
- if (is_long)
- ui_num = (u_wide_int) va_arg(ap, u_wide_int);
- else
- ui_num = (u_wide_int) va_arg(ap, unsigned int);
- s = conv_p2(ui_num, 4, *fmt,
+ if (var_type == IS_QUAD) {
+ ui_quad = va_arg(ap, u_widest_int);
+ s = conv_p2_quad(ui_quad, 4, *fmt,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ else {
+ if (var_type == IS_LONG)
+ ui_num = (u_wide_int) va_arg(ap, u_wide_int);
+ else if (var_type == IS_SHORT)
+ ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int);
+ else
+ ui_num = (u_wide_int) va_arg(ap, unsigned int);
+ s = conv_p2(ui_num, 4, *fmt,
&num_buf[NUM_BUF_SIZE], &s_len);
+ }
FIX_PRECISION(adjust_precision, precision, s, s_len);
if (alternate_form && i_num != 0) {
*--s = *fmt; /* 'x' or 'X' */
@@ -840,7 +983,14 @@ API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
case 'n':
- *(va_arg(ap, int *)) = cc;
+ if (var_type == IS_QUAD)
+ *(va_arg(ap, widest_int *)) = cc;
+ else if (var_type == IS_LONG)
+ *(va_arg(ap, long *)) = cc;
+ else if (var_type == IS_SHORT)
+ *(va_arg(ap, short *)) = cc;
+ else
+ *(va_arg(ap, int *)) = cc;
break;
/*
@@ -850,16 +1000,25 @@ API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
case 'p':
switch(*++fmt) {
/*
- * If the pointer size is equal to the size of an unsigned
- * integer we convert the pointer to a hex number, otherwise
- * we print "%p" to indicate that we don't handle "%p".
+ * If the pointer size is equal to or smaller than the size
+ * of the largest unsigned int, we convert the pointer to a
+ * hex number, otherwise we print "%p" to indicate that we
+ * don't handle "%p".
*/
case 'p':
- ui_num = (u_wide_int) va_arg(ap, void *);
-
- if (sizeof(char *) <= sizeof(u_wide_int))
- s = conv_p2(ui_num, 4, 'x',
- &num_buf[NUM_BUF_SIZE], &s_len);
+#ifdef AP_VOID_P_IS_QUAD
+ if (sizeof(void *) <= sizeof(u_widest_int)) {
+ ui_quad = (u_widest_int) va_arg(ap, void *);
+ s = conv_p2_quad(ui_quad, 4, 'x',
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+#else
+ if (sizeof(void *) <= sizeof(u_wide_int)) {
+ ui_num = (u_wide_int) va_arg(ap, void *);
+ s = conv_p2(ui_num, 4, 'x',
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+#endif
else {
s = "%p";
s_len = 2;
diff --git a/usr.sbin/httpd/src/helpers/GuessOS b/usr.sbin/httpd/src/helpers/GuessOS
index bac2b5ebc10..c68cfb5aba2 100644
--- a/usr.sbin/httpd/src/helpers/GuessOS
+++ b/usr.sbin/httpd/src/helpers/GuessOS
@@ -7,6 +7,8 @@
# addition: Any changes or additions to this script should be
# Emailed to the Apache group (apache@apache.org).
#
+# Initially written by Jim Jagielski for the Apache configuration mechanism
+#
# Be as similar to the output of config.guess/config.sub
# as possible.
@@ -114,7 +116,11 @@ case "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}" in
echo "i486-whatever-bsdi"; exit 0
;;
- BSD/386:*|BSD/OS:*)
+ BSD/386|BSD/OS:3.*)
+ echo "${MACHINE}-whatever-bsdi3"; exit 0
+ ;;
+
+ BSD/386:*|BSD/OS:*)
echo "${MACHINE}-whatever-bsdi"; exit 0
;;
@@ -144,6 +150,10 @@ case "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}" in
echo "${MACHINE}-dec-osf"; exit 0
;;
+ NONSTOP_KERNEL:*:*:*)
+ echo "${MACHINE}-tandem-oss"; exit 0;
+ ;;
+
QNX:*)
if [ "$VERSION" -gt 422 ]; then
echo "${MACHINE}-qssl-qnx32"
@@ -188,8 +198,15 @@ case "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}" in
echo "${MACHINE}-whatever-unixware212"; exit 0
;;
- DYNIX/ptx:4*:*)
- echo "${MACHINE}-whatever-sysv4"; exit 0
+ DYNIX/ptx:4*:*:i386)
+ PTXVER=`echo ${VERSION}|sed -e 's/[^.]//'`
+ echo "${MACHINE}-sequent-ptx${PTXVER}"; exit 0
+ ;;
+
+ *:3.2.0:*:i386)
+ # uname on DYNIX/ptx below V4.0.0 is brain dead
+ PTXVER=`echo ${VERSION}|sed -e 's/[^.]//'`
+ echo "${MACHINE}-sequent-ptx${PTXVER}"; exit 0
;;
*:4.0:3.0:[345][0-9]?? | *:4.0:3.0:3[34]??[/,]* | library:*)
@@ -242,6 +259,11 @@ case "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}" in
echo "${MACHINE}-apple-rhapsody${RELEASE}"; exit 0
;;
+ "Mac OS":*:*:*)
+ MACHINE=`uname -p`
+ echo "${MACHINE}-apple-macos${RELEASE}"; exit 0
+ ;;
+
"RISC iX":*)
echo "arm-whatever-riscix"; exit 0;
;;
@@ -274,7 +296,7 @@ fi
# Apache is not compiled on the TPF platform
# therefore an environment variable is used
-if [ "$TPF" = "YES" ]; then
+if [ "x$TPF" = "xYES" ]; then
echo "TPF"
exit 0
fi
diff --git a/usr.sbin/httpd/src/helpers/PrintPath b/usr.sbin/httpd/src/helpers/PrintPath
index 71335280fd3..908d2740083 100644
--- a/usr.sbin/httpd/src/helpers/PrintPath
+++ b/usr.sbin/httpd/src/helpers/PrintPath
@@ -10,6 +10,9 @@
# Usage:
# PrintPath [-s] [-pPATHNAME] program [program ...]
#
+# Initially written by Jim Jagielski for the Apache configuration mechanism
+# (with kudos to Kernighan/Pike)
+#
# This script falls under the Apache License.
# See http://www.apache.org/docs/LICENSE
@@ -91,7 +94,7 @@ do
do
if [ $test_exec_flag $path/${program}${ext} ] && \
[ ! -d $path/${program}${ext} ]; then
- if [ "$echo" = "yes" ]; then
+ if [ "x$echo" = "xyes" ]; then
echo $path/${program}${ext}
fi
exit 0
diff --git a/usr.sbin/httpd/src/helpers/TestCompile b/usr.sbin/httpd/src/helpers/TestCompile
index 6be8d474301..4622a3f2fc7 100644
--- a/usr.sbin/httpd/src/helpers/TestCompile
+++ b/usr.sbin/httpd/src/helpers/TestCompile
@@ -22,6 +22,14 @@ trap 'rm -f Makefile dummy dummy.exe testfunc.c testfunc testfunc.exe; exit $exs
# ./helpers/TestCompile sanity
# Which does a simple sanity check/test compile
#
+# ./helpers/TestCompile sizeof <type>
+# Which prints out the sizeof <type> (sure would be nice
+# if sizeof could be use in preprocessor if's)
+#
+# ./helpers/TestCompile byteorder
+# Which prints out the byte order of the machine
+# (12: little endian, 21: big endian)
+#
# It does these by creating a small mini-makefile, based on
# ../Makefile.config and trying to compile a small dummy
# program. If the compilation succeeds, we assume the test
@@ -32,6 +40,8 @@ trap 'rm -f Makefile dummy dummy.exe testfunc.c testfunc testfunc.exe; exit $exs
# located) if you want to test it out. Configure must
# also call it as './helpers/TestCompile'
#
+# Initially written by Jim Jagielski for the Apache configuration mechanism
+#
# This script falls under the Apache License.
# See http://www.apache.org/docs/LICENSE
@@ -39,8 +49,15 @@ trap 'rm -f Makefile dummy dummy.exe testfunc.c testfunc testfunc.exe; exit $exs
cd ./helpers
#
-# Handle "verbose" and "silent" flags
+# Handle "verbose", "silent" and "runit" flags. Allow for them
+# to be set via the environment
#
+if [ "x$VERBOSE" = "x" ]; then
+ VERBOSE="no"
+fi
+if [ "x$TCRUNIT" = "x" ]; then
+ TCRUNIT="no";
+fi
case "$1" in
"-v")
VERBOSE="yes"
@@ -50,6 +67,10 @@ case "$1" in
VERBOSE="no"
shift
;;
+ "-r")
+ TCRUNIT="yes"
+ shift
+ ;;
esac
#
@@ -61,8 +82,8 @@ case "$1" in
if [ "x$2" = "x" ]; then
exit
fi
- TLIB="-l$2"
- if [ "$VERBOSE" = "yes" ]; then
+ TLIB="-l$2 $TLIB"
+ if [ "x$VERBOSE" = "xyes" ]; then
ERRDIR=""
else
ERRDIR='2>/dev/null'
@@ -74,9 +95,52 @@ case "$1" in
echo "int main(void) { $3(); return(0); }" > testfunc.c
fi
;;
+ "sizeof")
+ if [ "x$2" = "x" ]; then
+ exit
+ fi
+ TLIB=""
+ if [ "x$VERBOSE" = "xyes" ]; then
+ ERRDIR=""
+ else
+ ERRDIR='2>/dev/null'
+ fi
+ TARGET='testfunc'
+ cat <<EOF >testfunc.c
+#include <stdio.h>
+#include <sys/types.h>
+int main(void) {
+ printf("%d\n", sizeof($2));
+ return(0);
+}
+EOF
+ ;;
+ "byteorder")
+ TLIB=""
+ if [ "x$VERBOSE" = "xyes" ]; then
+ ERRDIR=""
+ else
+ ERRDIR='2>/dev/null'
+ fi
+ TARGET='testfunc'
+ cat <<EOF >testfunc.c
+#include <stdio.h>
+#include <sys/types.h>
+int main(void) {
+ /* Are we little or big endian? From Harbison & Steele */
+ union {
+ long l;
+ char c[sizeof(long)];
+ } u;
+ u.l = 1;
+ printf("%s\n", u.c[sizeof(long)-1] == 1 ? "21" : "12");
+ return(0);
+}
+EOF
+ ;;
"sanity")
TLIB=""
- if [ "$VERBOSE" = "no" ]; then
+ if [ "x$VERBOSE" = "xno" ]; then
ERRDIR='2>/dev/null'
else
ERRDIR=""
@@ -88,7 +152,7 @@ case "$1" in
exit
fi
TLIB=""
- if [ "$VERBOSE" = "yes" ]; then
+ if [ "x$VERBOSE" = "xyes" ]; then
ERRDIR=""
else
ERRDIR='2>/dev/null'
@@ -106,7 +170,7 @@ EOF
exit
fi
TLIB=""
- if [ "$VERBOSE" = "yes" ]; then
+ if [ "x$VERBOSE" = "xyes" ]; then
ERRDIR=""
else
ERRDIR='2>/dev/null'
@@ -143,7 +207,7 @@ testfunc:
EOF
# Now run that Makefile
-eval "${MAKE} ${TARGET} >/dev/null $ERRDIR"
+eval "${MAKE-make} ${TARGET} $ERRDIR >&2"
# And see if dummy exists and is executable, if so, then we
# assume the condition we are testing for is good
@@ -152,5 +216,8 @@ eval "${MAKE} ${TARGET} >/dev/null $ERRDIR"
# have PrintPath just search this directory.
if ./PrintPath -s -p`pwd` $TARGET ; then
+ if [ "x$TCRUNIT" = "xyes" ]; then
+ `pwd`/$TARGET
+ fi
exstat=0
fi
diff --git a/usr.sbin/httpd/src/helpers/binbuild.sh b/usr.sbin/httpd/src/helpers/binbuild.sh
index 3279148fcbc..e6c3a4b4a9f 100644
--- a/usr.sbin/httpd/src/helpers/binbuild.sh
+++ b/usr.sbin/httpd/src/helpers/binbuild.sh
@@ -7,14 +7,21 @@
# See http://www.apache.org/docs/LICENSE
-APDIR=$(basename $(pwd))
-VER=$(echo $APDIR |sed s/apache-//)
-OS=$(src/helpers/GuessOS)
-USER="$(src/helpers/buildinfo.sh -n %u@%h%d)"
-TAR="$(src/helpers/findprg.sh tar)"
-GTAR="$(src/helpers/findprg.sh gtar)"
-GZIP="$(src/helpers/findprg.sh gzip)"
CONFIGPARAM="--with-layout=BinaryDistribution --enable-module=most --enable-shared=max"
+APDIR=`pwd`
+APDIR=`basename $APDIR`
+VER=`echo $APDIR |sed s/apache_//`
+OS=`src/helpers/GuessOS`
+TAR="`src/helpers/PrintPath tar`"
+GTAR="`src/helpers/PrintPath gtar`"
+GZIP="`src/helpers/PrintPath gzip`"
+
+if [ x$1 != x ]
+then
+ USER=$1
+else
+ USER="`src/helpers/buildinfo.sh -n %u@%h%d`"
+fi
if [ ! -f ./ABOUT_APACHE ]
then
@@ -58,7 +65,10 @@ then
exit 1;
fi
-echo "Binary images successfully created..."
+echo "Binary image successfully created..."
+
+./bindist/bin/httpd -v
+
echo "Creating supplementary files..."
( echo " " && \
@@ -89,7 +99,7 @@ echo "Creating supplementary files..."
./bindist/bin/httpd -V && \
echo "----------------------------------------------------------------------" \
) > README.bindist
-cp README.bindist ../apache-$VER-$OS.README
+cp README.bindist ../apache_$VER-$OS.README
( echo " " && \
echo "Apache $VER binary installation" && \
@@ -119,6 +129,64 @@ cp README.bindist ../apache-$VER-$OS.README
echo "# This script installs the Apache binary distribution and" && \
echo "# was automatically created by binbuild.sh." && \
echo " " && \
+ echo "lmkdir()" && \
+ echo "{" && \
+ echo " path=\"\"" && \
+ echo " dirs=\`echo \$1 | sed -e 's%/% %g'\`" && \
+ echo " mode=\$2" && \
+ echo " " && \
+ echo " set -- \${dirs}" && \
+ echo " " && \
+ echo " for d in \${dirs}" && \
+ echo " do" && \
+ echo " path=\"\${path}/\$d\"" && \
+ echo " if test ! -d \"\${path}\" ; then" && \
+ echo " mkdir \${path}" && \
+ echo " if test \$? -ne 0 ; then" && \
+ echo " echo \"Failed to create directory: \${path}\"" && \
+ echo " exit 1" && \
+ echo " fi" && \
+ echo " chmod \${mode} \${path}" && \
+ echo " fi" && \
+ echo " done" && \
+ echo "}" && \
+ echo " " && \
+ echo "lcopy()" && \
+ echo "{" && \
+ echo " from=\$1" && \
+ echo " to=\$2" && \
+ echo " dmode=\$3" && \
+ echo " fmode=\$4" && \
+ echo " " && \
+ echo " test -d \${to} || lmkdir \${to} \${dmode}" && \
+ echo " (cd \${from} && tar -cf - *) | (cd \${to} && tar -xf -)" && \
+ echo " " && \
+ echo " if test \"X\${fmode}\" != X ; then" && \
+ echo " find \${to} -type f -print | xargs chmod \${fmode}" && \
+ echo " fi" && \
+ echo " if test \"X\${dmode}\" != X ; then" && \
+ echo " find \${to} -type d -print | xargs chmod \${dmode}" && \
+ echo " fi" && \
+ echo "}" && \
+ echo " " && \
+ echo "##" && \
+ echo "## determine path to (optional) Perl interpreter" && \
+ echo "##" && \
+ echo "PERL=no-perl5-on-this-system" && \
+ echo "perls='perl5 perl'" && \
+ echo "path=\`echo \$PATH | sed -e 's/:/ /g'\`" && \
+ echo " " && \
+ echo "for dir in \${path} ; do" && \
+ echo " for pperl in \${perls} ; do" && \
+ echo " if test -f \"\${dir}/\${pperl}\" ; then" && \
+ echo " if \`\${dir}/\${pperl} -v | grep 'version 5\.' >/dev/null 2>&1\` ; then" && \
+ echo " PERL=\"\${dir}/\${pperl}\"" && \
+ echo " break" && \
+ echo " fi" && \
+ echo " fi" && \
+ echo " done" && \
+ echo "done" && \
+ echo " " && \
echo "if [ .\$1 = . ]" && \
echo "then" && \
echo " SR=/usr/local/apache" && \
@@ -127,41 +195,46 @@ cp README.bindist ../apache-$VER-$OS.README
echo "fi" && \
echo "echo \"Installing binary distribution for platform $OS\"" && \
echo "echo \"into directory \$SR ...\"" && \
- echo "./src/helpers/mkdir.sh \$SR" && \
- echo "cp -r bindist/proxy \$SR/proxy" && \
- echo "cp -r bindist/man \$SR/man" && \
- echo "cp -r bindist/logs \$SR/logs" && \
- echo "cp -r bindist/libexec \$SR/libexec" && \
- echo "cp -r bindist/include \$SR/include" && \
- echo "cp -r bindist/icons \$SR/icons" && \
- echo "cp -r bindist/cgi-bin \$SR/cgi-bin" && \
- echo "cp -r bindist/bin \$SR/bin" && \
+ echo "lmkdir \$SR 755" && \
+ echo "lmkdir \$SR/proxy 750" && \
+ echo "lmkdir \$SR/logs 750" && \
+ echo "lcopy bindist/man \$SR/man 755 644" && \
+ echo "lcopy bindist/libexec \$SR/libexec 750 644" && \
+ echo "lcopy bindist/include \$SR/include 755 644" && \
+ echo "lcopy bindist/icons \$SR/icons 755 644" && \
+ echo "lcopy bindist/cgi-bin \$SR/cgi-bin 750 750" && \
+ echo "lcopy bindist/bin \$SR/bin 750 750" && \
echo "if [ -d \$SR/conf ]" && \
echo "then" && \
echo " echo \"[Preserving existing configuration files.]\"" && \
- echo " cp -r bindist/conf/*.default \$SR/conf/" && \
+ echo " cp bindist/conf/*.default \$SR/conf/" && \
echo "else" && \
- echo " cp -r bindist/conf \$SR/conf" && \
+ echo " lcopy bindist/conf \$SR/conf 750 640" && \
echo "fi" && \
echo "if [ -d \$SR/htdocs ]" && \
echo "then" && \
echo " echo \"[Preserving existing htdocs directory.]\"" && \
echo "else" && \
- echo " cp -r bindist/htdocs \$SR/htdocs" && \
+ echo " lcopy bindist/htdocs \$SR/htdocs 755 644" && \
echo "fi" && \
- echo "sed -e s%/usr/local/apache%\$SR/% \$SR/conf/httpd.conf.default > \$SR/conf/httpd.conf" && \
- echo "sed -e s%PIDFILE=%PIDFILE=\$SR/% -e s%HTTPD=%HTTPD=\\\"\$SR/% -e \"s%/httpd$%/httpd -d \$SR\\\"%\" bindist/bin/apachectl > \$SR/bin/apachectl" && \
+ echo " " && \
+ echo "sed -e \"s;^#!/.*;#!\$PERL;\" -e \"s;\@prefix\@;\$SR;\" -e \"s;\@sbindir\@;\$SR/bin;\" \\" && \
+ echo " -e \"s;\@libexecdir\@;\$SR/libexec;\" -e \"s;\@includedir\@;\$SR/include;\" \\" && \
+ echo " -e \"s;\@sysconfdir\@;\$SR/conf;\" bindist/bin/apxs > \$SR/bin/apxs" && \
+ echo "sed -e \"s;^#!/.*;#!\$PERL;\" bindist/bin/dbmmanage > \$SR/bin/dbmmanage" && \
+ echo "sed -e \"s%/usr/local/apache%\$SR%\" \$SR/conf/httpd.conf.default > \$SR/conf/httpd.conf" && \
+ echo "sed -e \"s%PIDFILE=%PIDFILE=\$SR/%\" -e \"s%HTTPD=%HTTPD=\\\"\$SR/%\" -e \"s%httpd\$%httpd -d \$SR -R \$SR/libexec\\\"%\" bindist/bin/apachectl > \$SR/bin/apachectl" && \
echo " " && \
echo "echo \"Ready.\"" && \
echo "echo \" +--------------------------------------------------------+\"" && \
echo "echo \" | You now have successfully installed the Apache $VER |\"" && \
echo "echo \" | HTTP server. To verify that Apache actually works |\"" && \
- echo "echo \" | correctly you now should first check the (initially |\"" && \
- echo "echo \" | created or preserved) configuration files |\"" && \
+ echo "echo \" | correctly you should first check the (initially |\"" && \
+ echo "echo \" | created or preserved) configuration files: |\"" && \
echo "echo \" | |\"" && \
echo "echo \" | \$SR/conf/httpd.conf\"" && \
echo "echo \" | |\"" && \
- echo "echo \" | and then you should be able to immediately fire up |\"" && \
+ echo "echo \" | You should then be able to immediately fire up |\"" && \
echo "echo \" | Apache the first time by running: |\"" && \
echo "echo \" | |\"" && \
echo "echo \" | \$SR/bin/apachectl start \"" &&\
@@ -173,9 +246,10 @@ cp README.bindist ../apache-$VER-$OS.README
) > install-bindist.sh
chmod 755 install-bindist.sh
-sed -e "s%\"/htdocs%\"/usr/local/apache/htdocs%" \
- -e "s%\"/icons%\"/usr/local/apache/icons%" \
- -e "s%\"/cgi-bin%\"/usr/local/apache/cgi-bin%" \
+sed -e "s%\"htdocs%\"/usr/local/apache/htdocs%" \
+ -e "s%\"icons%\"/usr/local/apache/icons%" \
+ -e "s%\"cgi-bin%\"/usr/local/apache/cgi-bin%" \
+ -e "s%\"proxy%\"/usr/local/apache/proxy%" \
-e "s%^ServerAdmin.*%ServerAdmin you@your.address%" \
-e "s%#ServerName.*%#ServerName localhost%" \
-e "s%Port 8080%Port 80%" \
@@ -189,30 +263,30 @@ then
echo "ERROR: Failed to build Apache. See \"build.log\" for details."
exit 1;
else
- if [ ".$GTAR" != . ]
+ if [ "x$GTAR" != "x" ]
then
- $GTAR -zcf ../apache-$VER-$OS.tar.gz -C .. --owner=root --group=root apache-$VER
+ $GTAR -zcf ../apache_$VER-$OS.tar.gz -C .. apache_$VER
else
- if [ ".$TAR" != . ]
+ if [ "x$TAR" != "x" ]
then
- $TAR -cf ../apache-$VER-$OS.tar -C .. apache-$VER
- if [ ".$GZIP" != . ]
+ $TAR -cf ../apache_$VER-$OS.tar -C .. apache_$VER
+ if [ "x$GZIP" != "x" ]
then
- $GZIP ../apache-$VER-$OS.tar
+ $GZIP ../apache_$VER-$OS.tar
fi
else
echo "ERROR: Could not find a 'tar' program!"
echo " Please execute the following commands manually:"
- echo " tar -cf ../apache-$VER-$OS.tar ."
- echo " gzip ../apache-$VER-$OS.tar"
+ echo " tar -cf ../apache_$VER-$OS.tar ."
+ echo " gzip ../apache_$VER-$OS.tar"
fi
fi
- if [ -f ../apache-$VER-$OS.tar.gz ] && [ -f ../apache-$VER-$OS.README ]
+ if [ -f ../apache_$VER-$OS.tar.gz ] && [ -f ../apache_$VER-$OS.README ]
then
echo "Ready."
- echo "You can find the binary archive (apache-$VER-$OS.tar.gz)"
- echo "and the readme file (apache-$VER-$OS.README) in the"
+ echo "You can find the binary archive (apache_$VER-$OS.tar.gz)"
+ echo "and the readme file (apache_$VER-$OS.README) in the"
echo "parent directory."
exit 0;
else
diff --git a/usr.sbin/httpd/src/helpers/buildinfo.sh b/usr.sbin/httpd/src/helpers/buildinfo.sh
index 8aa0541c206..5c2a72d6b35 100644
--- a/usr.sbin/httpd/src/helpers/buildinfo.sh
+++ b/usr.sbin/httpd/src/helpers/buildinfo.sh
@@ -1,7 +1,7 @@
#!/bin/sh
##
## buildinfo.sh -- Determine Build Information
-## Written by Ralf S. Engelschall <rse@apache.org>
+## Initially written by Ralf S. Engelschall <rse@apache.org>
## for the Apache's Autoconf-style Interface (APACI)
##
#
@@ -16,10 +16,10 @@ error=no
if [ $# -ne 1 -a $# -ne 2 ]; then
error=yes
fi
-if [ $# -eq 2 -a ".$1" != ".-n" ]; then
+if [ $# -eq 2 -a "x$1" != "x-n" ]; then
error=yes
fi
-if [ $error = yes ]; then
+if [ "x$error" = "xyes" ]; then
echo "$0:Error: invalid argument line"
echo "$0:Usage: $0 [-n] <format-string>"
echo "Where <format-string> can contain:"
@@ -55,15 +55,15 @@ time_monthname=''
# determine username
#
username="$LOGNAME"
-if [ ".$username" = . ]; then
+if [ "x$username" = "x" ]; then
username="$USER"
- if [ ".$username" = . ]; then
- username="`whoami 2>/dev/null |\
+ if [ "x$username" = "x" ]; then
+ username="`(whoami) 2>/dev/null |\
awk '{ printf("%s", $1); }'`"
- if [ ".$username" = . ]; then
- username="`who am i 2>/dev/null |\
+ if [ "x$username" = "x" ]; then
+ username="`(who am i) 2>/dev/null |\
awk '{ printf("%s", $1); }'`"
- if [ ".$username" = . ]; then
+ if [ "x$username" = "x" ]; then
username='unknown'
fi
fi
@@ -73,12 +73,12 @@ fi
#
# determine hostname and domainname
#
-hostname="`uname -n 2>/dev/null |\
+hostname="`(uname -n) 2>/dev/null |\
awk '{ printf("%s", $1); }'`"
-if [ ".$hostname" = . ]; then
- hostname="`hostname 2>/dev/null |\
+if [ "x$hostname" = "x" ]; then
+ hostname="`(hostname) 2>/dev/null |\
awk '{ printf("%s", $1); }'`"
- if [ ".$hostname" = . ]; then
+ if [ "x$hostname" = "x" ]; then
hostname='unknown'
fi
fi
@@ -88,14 +88,14 @@ case $hostname in
hostname="`echo $hostname | cut -d. -f1`"
;;
esac
-if [ ".$domainname" = . ]; then
+if [ "x$domainname" = "x" ]; then
if [ -f /etc/resolv.conf ]; then
domainname="`egrep '^[ ]*domain' /etc/resolv.conf | head -1 |\
sed -e 's/.*domain//' \
-e 's/^[ ]*//' -e 's/^ *//' -e 's/^ *//' \
-e 's/^\.//' -e 's/^/./' |\
awk '{ printf("%s", $1); }'`"
- if [ ".$domainname" = . ]; then
+ if [ "x$domainname" = "x" ]; then
domainname="`egrep '^[ ]*search' /etc/resolv.conf | head -1 |\
sed -e 's/.*search//' \
-e 's/^[ ]*//' -e 's/^ *//' -e 's/^ *//' \
@@ -112,11 +112,11 @@ fi
time_day="`date '+%d' | awk '{ printf("%s", $1); }'`"
time_month="`date '+%m' | awk '{ printf("%s", $1); }'`"
time_year="`date '+%Y' 2>/dev/null | awk '{ printf("%s", $1); }'`"
-if test ".$time_year" = .; then
+if [ "x$time_year" = "x" ]; then
time_year="`date '+%y' | awk '{ printf("%s", $1); }'`"
case $time_year in
- 9[0-9]*) time_year="19$time_year" ;;
- *) time_year="20$time_year" ;;
+ [5-9][0-9]) time_year="19$time_year" ;;
+ [0-4][0-9]) time_year="20$time_year" ;;
esac
fi
case $time_month in
@@ -137,7 +137,7 @@ esac
#
# create result string
#
-if [ ".$newline" = .yes ]; then
+if [ "x$newline" = "xyes" ]; then
echo $format_string |\
sed -e "s;%u;$username;g" \
-e "s;%h;$hostname;g" \
diff --git a/usr.sbin/httpd/src/helpers/checkheader.sh b/usr.sbin/httpd/src/helpers/checkheader.sh
index 4f3fd064d64..26cd176c682 100644
--- a/usr.sbin/httpd/src/helpers/checkheader.sh
+++ b/usr.sbin/httpd/src/helpers/checkheader.sh
@@ -1,7 +1,8 @@
#!/bin/sh
##
## checkheader.sh -- Check whether a C header file exists
-## Written by Ralf S. Engelschall for the Apache configuration mechanism
+## Initially written by Ralf S. Engelschall for the Apache
+## configuration mechanism
##
#
# This script falls under the Apache License.
@@ -10,10 +11,10 @@
header=$1
rc=1
-if [ ".$CPP" = . ]; then
+if [ "x$CPP" = "x" ]; then
CPP='NOT-AVAILABLE'
fi
-if [ ".$CPP" != ".NOT-AVAILABLE" ]; then
+if [ "x$CPP" != "xNOT-AVAILABLE" ]; then
# create a test C source
cat >conftest.c <<EOF
#include <$header>
@@ -21,7 +22,7 @@ Syntax Error
EOF
(eval "$CPP conftest.c >/dev/null") 2>conftest.out
my_error=`grep -v '^ *+' conftest.out`
- if [ ".$my_error" = . ]; then
+ if [ "x$my_error" = "x" ]; then
rc=0
fi
else
diff --git a/usr.sbin/httpd/src/helpers/dummy.c b/usr.sbin/httpd/src/helpers/dummy.c
index b1e4964cbbf..cf938b8402c 100644
--- a/usr.sbin/httpd/src/helpers/dummy.c
+++ b/usr.sbin/httpd/src/helpers/dummy.c
@@ -6,7 +6,7 @@ int foo ( const char *c )
return *c;
}
int main(void) {
- const char *c = '\0';
+ const char *c = "";
(void)foo(c);
return 0;
}
diff --git a/usr.sbin/httpd/src/helpers/find-dbm-lib b/usr.sbin/httpd/src/helpers/find-dbm-lib
index 0355965af59..3792d9301eb 100644
--- a/usr.sbin/httpd/src/helpers/find-dbm-lib
+++ b/usr.sbin/httpd/src/helpers/find-dbm-lib
@@ -18,13 +18,13 @@ if [ "x$found_dbm" = "x" ]; then
elif ./helpers/TestCompile lib ndbm dbm_open; then
DBM_LIB="-lndbm"
fi
- if [ "X$DBM_LIB" != "X" ]; then
+ if [ "x$DBM_LIB" != "x" ]; then
LIBS="$LIBS $DBM_LIB"
found_dbm=1
fi
;;
*)
- if [ "X$DBM_LIB" != "X" ]; then
+ if [ "x$DBM_LIB" != "x" ]; then
oldLIBS="$LIBS"
LIBS="$LIBS $DBM_LIB"
if ./helpers/TestCompile func dbm_open; then
@@ -33,10 +33,21 @@ if [ "x$found_dbm" = "x" ]; then
found_dbm=0
LIBS="$oldLIBS"
fi
+ else
+ for dblib in dbm ndbm db
+ do
+ DBM_LIB=""
+ if ./helpers/TestCompile lib $dblib dbm_open; then
+ DBM_LIB="-l${dblib}"
+ LIBS="$LIBS $DBM_LIB"
+ found_dbm=1
+ break
+ fi
+ done
fi
;;
esac
- if [ "X$found_dbm" = "X1" ]; then
+ if [ "x$found_dbm" = "x1" ]; then
echo " + using $DBM_LIB for DBM support"
fi
fi
diff --git a/usr.sbin/httpd/src/helpers/findcpp.sh b/usr.sbin/httpd/src/helpers/findcpp.sh
index f5a261f34eb..a870f7371ae 100644
--- a/usr.sbin/httpd/src/helpers/findcpp.sh
+++ b/usr.sbin/httpd/src/helpers/findcpp.sh
@@ -1,7 +1,8 @@
#!/bin/sh
##
## findcpp.sh -- Find out how to _directly_ run the C Pre-Processor (CPP)
-## Written by Ralf S. Engelschall for the Apache configuration mechanism
+## Initially written by Ralf S. Engelschall for the Apache configuration
+## mechanism
##
#
# This script falls under the Apache License.
@@ -19,16 +20,16 @@ Syntax Error
EOF
# some braindead systems have a CPP define for a directory :-(
-if [ ".$CPP" != . ]; then
+if [ "x$CPP" != "x" ]; then
if [ -d "$CPP" ]; then
CPP=''
fi
fi
-if [ ".$CPP" != . ]; then
+if [ "x$CPP" != "x" ]; then
# case 1: user provided a default CPP variable (we only check)
(eval "$CPP conftest.c >/dev/null") 2>conftest.out
my_error=`grep -v '^ *+' conftest.out`
- if [ ".$my_error" != . ]; then
+ if [ "x$my_error" != "x" ]; then
CPP=''
fi
else
@@ -37,21 +38,21 @@ else
CPP="${CC-cc} -E"
(eval "$CPP conftest.c >/dev/null") 2>conftest.out
my_error=`grep -v '^ *+' conftest.out`
- if [ ".$my_error" != . ]; then
+ if [ "x$my_error" != "x" ]; then
# 2. try the -E option and GCC's -traditional-ccp option
CPP="${CC-cc} -E -traditional-cpp"
(eval "$CPP conftest.c >/dev/null") 2>conftest.out
my_error=`grep -v '^ *+' conftest.out`
- if [ ".$my_error" != . ]; then
+ if [ "x$my_error" != "x" ]; then
# 3. try a standalone cpp command in $PATH and lib dirs
CPP="`./helpers/PrintPath cpp`"
- if [ ".$CPP" = . ]; then
+ if [ "x$CPP" = "x" ]; then
CPP="`./helpers/PrintPath -p/lib:/usr/lib:/usr/local/lib cpp`"
fi
- if [ ".$CPP" != . ]; then
+ if [ "x$CPP" != "x" ]; then
(eval "$CPP conftest.c >/dev/null") 2>conftest.out
my_error=`grep -v '^ *+' conftest.out`
- if [ ".$my_error" != . ]; then
+ if [ "x$my_error" != "x" ]; then
# ok, we gave up...
CPP=''
fi
@@ -64,7 +65,7 @@ fi
rm -f conftest.*
# Ok, empty CPP variable now means it's not available
-if [ ".$CPP" = . ]; then
+if [ "x$CPP" = "x" ]; then
CPP='NOT-AVAILABLE'
fi
diff --git a/usr.sbin/httpd/src/helpers/findprg.sh b/usr.sbin/httpd/src/helpers/findprg.sh
deleted file mode 100644
index 8b2f391c976..00000000000
--- a/usr.sbin/httpd/src/helpers/findprg.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-#
-# Usage: findprg.sh <program-name>
-# Return value is the absolute path of the program if it was found.
-# Initially written by Lars Eilebrecht <lars@apache.org>.
-#
-# This script falls under the Apache License.
-# See http://www.apache.org/docs/LICENSE
-
-
-if [ ".`which $1`" != . ]
-then
- echo `which $1`
- exit 0
-else
- PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
- if [ ".`which $1`" != . ]
- then
- echo `which $1`
- exit 0
- else
- exit 1
- fi
-fi
diff --git a/usr.sbin/httpd/src/helpers/fmn.sh b/usr.sbin/httpd/src/helpers/fmn.sh
index b8fd39ede45..0f17b55a08b 100644
--- a/usr.sbin/httpd/src/helpers/fmn.sh
+++ b/usr.sbin/httpd/src/helpers/fmn.sh
@@ -2,8 +2,7 @@
##
## fmn.sh -- find a modules (structure) name
##
-## Extracted from the Configure script by
-## Ralf S. Engelschall <rse@apache.org> for use with
+## Extracted from the Configure script for use with
## Apache's Autoconf-style Interface (APACI).
##
#
@@ -20,9 +19,9 @@ rm -f $tmpfile
modname=''
ext=`echo $modfile | sed 's/^.*\.//'`
modbase=`echo $modfile | sed 's/\.[^.]*$//'`
-if [ x$ext = x$modfile ]; then ext=o; modbase=$modfile; modfile=$modbase.o; fi
-if [ x$ext = x ] ; then ext=o; modbase=$modfile; fi
-if [ x$ext = xc ] ; then ext=o; fi
+if [ "x$ext" = "x$modfile" ]; then ext=o; modbase=$modfile; modfile=$modbase.o; fi
+if [ "x$ext" = "x" ] ; then ext=o; modbase=$modfile; fi
+if [ "x$ext" = "xc" ] ; then ext=o; fi
if [ -r $modbase.module ] ; then
cat $modbase.module >$tmpfile
else
diff --git a/usr.sbin/httpd/src/helpers/fp2rp b/usr.sbin/httpd/src/helpers/fp2rp
index 6c594ba7234..68d5adb6d19 100644
--- a/usr.sbin/httpd/src/helpers/fp2rp
+++ b/usr.sbin/httpd/src/helpers/fp2rp
@@ -2,7 +2,7 @@
##
## fp2rp -- convert a standard forward path to a reverse dotted path
##
-if [ "x$1" = x. ]; then
+if [ "x$1" = "x." ]; then
rp="."
else
rp=""
diff --git a/usr.sbin/httpd/src/helpers/getuid.sh b/usr.sbin/httpd/src/helpers/getuid.sh
new file mode 100644
index 00000000000..42cdf0d6e5d
--- /dev/null
+++ b/usr.sbin/httpd/src/helpers/getuid.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+# Return the uid of the process being run. If we cannot
+# determine what it is, return '?'.
+#
+# Initially written by Jim Jagielski for the Apache configuration mechanism
+#
+# This script falls under the Apache License.
+# See http://www.apache.org/docs/LICENSE
+
+# First we try 'id'
+if `./src/helpers/PrintPath -s id` ; then
+ AP_IDPATH=`./src/helpers/PrintPath id`
+ # See if it's a POSIX 'id'
+ if `$AP_IDPATH -u >/dev/null 2>&1` ; then
+ AP_RETVAL=`$AP_IDPATH -u`
+ echo $AP_RETVAL
+ exit 0
+ else
+ AP_RETVAL=`$AP_IDPATH | \
+ sed -e 's/^.*uid[ ]*=[ ]*[^0123456789]*//' | \
+ sed -e 's/[ ]*(.*$//'`
+ echo $AP_RETVAL
+ exit 0
+ fi
+fi
+
+#
+# Ugg. Now we have to grab the login name of the process, and
+# scan /etc/passwd.
+#
+# Try 'whoami' first, then 'who am i' (making sure to strip away
+# the who crud) and finally just copy $LOGNAME
+#
+if `./src/helpers/PrintPath -s whoami` ; then
+ AP_WAIPATH=`./src/helpers/PrintPath whoami`
+ AP_LOGNAME=`$AP_WAIPATH`
+else
+ AP_LOGNAME=`who am i | tail -1 | sed -e 's/[ ][ ]*.*$//'`
+fi
+
+#
+# See if we have a valid login name.
+#
+if [ "x$AP_LOGNAME" = "x" ]; then
+ AP_LOGNAME=$LOGNAME
+ if [ "x$AP_LOGNAME" = "x" ]; then
+ echo "?"
+ exit 1
+ fi
+fi
+
+#
+# Ok, now we scan through /etc/passwd
+#
+AP_RETVAL=`egrep \^${AP_LOGNAME}: /etc/passwd | \
+ sed -e 's/[^:]*:[^:]*://' | \
+ sed -e 's/:.*$//'`
+
+if [ "x$AP_RETVAL" = "x" ]; then
+ echo "?"
+ exit 1
+else
+ echo $AP_RETVAL
+ exit 0
+fi
diff --git a/usr.sbin/httpd/src/helpers/install.sh b/usr.sbin/httpd/src/helpers/install.sh
index 19e8badad6e..9a8821fa290 100644
--- a/usr.sbin/httpd/src/helpers/install.sh
+++ b/usr.sbin/httpd/src/helpers/install.sh
@@ -34,9 +34,10 @@ chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
+ext=""
src=""
dst=""
-while [ ".$1" != . ]; do
+while [ "x$1" != "x" ]; do
case $1 in
-c) instcmd="$cpprog"
shift; continue
@@ -51,8 +52,15 @@ while [ ".$1" != . ]; do
shift; shift; continue
;;
-s) stripcmd="$stripprog"
- shift; continue;;
- *) if [ ".$src" = . ]; then
+ shift; continue
+ ;;
+ -S) stripcmd="$stripprog $2"
+ shift; shift; continue
+ ;;
+ -e) ext="$2"
+ shift; shift; continue
+ ;;
+ *) if [ "x$src" = "x" ]; then
src=$1
else
dst=$1
@@ -61,11 +69,11 @@ while [ ".$1" != . ]; do
;;
esac
done
-if [ ".$src" = . ]; then
+if [ "x$src" = "x" ]; then
echo "install.sh: no input file specified"
exit 1
fi
-if [ ".$dst" = . ]; then
+if [ "x$dst" = "x" ]; then
echo "install.sh: no destination specified"
exit 1
fi
@@ -79,6 +87,10 @@ if [ -d $dst ]; then
dst="$dst/`basename $src`"
fi
+# Add a possible extension (such as ".exe") to src and dst
+src="$src$ext"
+dst="$dst$ext"
+
# Make a temp file name in the proper directory.
dstdir=`dirname $dst`
dsttmp=$dstdir/#inst.$$#
@@ -87,10 +99,10 @@ dsttmp=$dstdir/#inst.$$#
$instcmd $src $dsttmp
# And set any options; do chmod last to preserve setuid bits
-if [ ".$chowncmd" != . ]; then $chowncmd $dsttmp; fi
-if [ ".$chgrpcmd" != . ]; then $chgrpcmd $dsttmp; fi
-if [ ".$stripcmd" != . ]; then $stripcmd $dsttmp; fi
-if [ ".$chmodcmd" != . ]; then $chmodcmd $dsttmp; fi
+if [ "x$chowncmd" != "x" ]; then $chowncmd $dsttmp; fi
+if [ "x$chgrpcmd" != "x" ]; then $chgrpcmd $dsttmp; fi
+if [ "x$stripcmd" != "x" ]; then $stripcmd $dsttmp; fi
+if [ "x$chmodcmd" != "x" ]; then $chmodcmd $dsttmp; fi
# Now rename the file to the real destination.
$rmcmd $dst
diff --git a/usr.sbin/httpd/src/helpers/mkshadow.sh b/usr.sbin/httpd/src/helpers/mkshadow.sh
index 448a09455cf..00b0e3a2a41 100644
--- a/usr.sbin/httpd/src/helpers/mkshadow.sh
+++ b/usr.sbin/httpd/src/helpers/mkshadow.sh
@@ -2,7 +2,7 @@
##
## mkshadow.sh -- create a shadow tree
##
-## Written by Ralf S. Engelschall <rse@apache.org>
+## Initially written by Ralf S. Engelschall <rse@apache.org>
## for the shadow tree generation option (--shadow) of
## Apache's Autoconf-style Interface (APACI)
##
@@ -37,7 +37,7 @@ esac
# determine reverse directory for destination directory
dstrevdir=''
-if [ $oneisabs = 0 ]; then
+if [ "x$oneisabs" = "x0" ]; then
# (inlined fp2rp)
OIFS2="$IFS"; IFS='/'
for pe in $dst; do
@@ -52,7 +52,7 @@ fi
if [ ! -d $dst ]; then
mkdir $dst
fi
-DIRS="`cd $src
+DIRS="`cd $src; \
find . -type d -print |\
sed -e '/\/CVS/d' \
-e '/^\.$/d' \
@@ -64,7 +64,7 @@ done
IFS="$OIFS"
# fill directory tree with symlinks to files
-FILES="`cd $src
+FILES="`cd $src; \
find . -depth -print |\
sed -e '/\.o$/d' \
-e '/\.a$/d' \
@@ -81,15 +81,15 @@ FILES="`cd $src
OIFS="$IFS" IFS="$DIFS"
for file in $FILES; do
# don't use `-type f' above for find because of symlinks
- if [ -d $file ]; then
+ if [ -d "$src/$file" ]; then
continue
fi
basename=`echo $file | sed -e 's:^.*/::'`
dir=`echo $file | sed -e 's:[^/]*$::' -e 's:/$::' -e 's:$:/:' -e 's:^/$::'`
from="$src/$file"
to="$dst/$dir$basename"
- if [ $oneisabs = 0 ]; then
- if [ ".$dir" != . ]; then
+ if [ "x$oneisabs" = "x0" ]; then
+ if [ "x$dir" != "x" ]; then
subdir=`echo $dir | sed -e 's:/$::'`
# (inlined fp2rp)
revdir=''
diff --git a/usr.sbin/httpd/src/helpers/ppl.sh b/usr.sbin/httpd/src/helpers/ppl.sh
index a53b0c45558..e83ab4793fc 100644
--- a/usr.sbin/httpd/src/helpers/ppl.sh
+++ b/usr.sbin/httpd/src/helpers/ppl.sh
@@ -4,7 +4,7 @@
## `tr' and `fmt' because these tools are different
## between Unix platforms
##
-## Written by Ralf S. Engelschall <rse@apache.org>
+## Initially written by Ralf S. Engelschall <rse@apache.org>
## for pretty printing lists in the --help option of
## Apache's Autoconf-style Interface (APACI)
##
@@ -16,7 +16,7 @@
list=`
IFS=:
for entry in $*; do
- if [ ".$entry" != . ]; then
+ if [ "x$entry" != "x" ]; then
echo $entry
fi
done |\
diff --git a/usr.sbin/httpd/src/helpers/slo.sh b/usr.sbin/httpd/src/helpers/slo.sh
index 10820f5f1cb..e9d0e588134 100644
--- a/usr.sbin/httpd/src/helpers/slo.sh
+++ b/usr.sbin/httpd/src/helpers/slo.sh
@@ -1,7 +1,7 @@
#!/bin/sh
##
## slo.h -- (S)eparate (L)inker (O)ptions by library class
-## Written by Ralf S. Engelschall <rse@apache.org>
+## Initially written by Ralf S. Engelschall <rse@apache.org>
##
#
# This script falls under the Apache License.
@@ -22,12 +22,12 @@ OIFS="$IFS" IFS="$DIFS"
for opt
do
# concatenate with previous option if exists
- if [ ".$optprev" != . ]; then
+ if [ "x$optprev" != "x" ]; then
opt="${optprev}${opt}";
optprev=''
fi
# remember options for arg when used stand-alone
- if [ ".$opt" = ".-L" -o ".$opt" = ".-l" ]; then
+ if [ "x$opt" = "x-L" -o "x$opt" = "x-l" ]; then
optprev="$opt"
continue;
fi
@@ -47,7 +47,7 @@ IFS="$OIFS"
# set linker default directories
#
DIRS_DEFAULT='/lib:/usr/lib'
-if [ ".$LD_LIBRARY_PATH" != . ]; then
+if [ "x$LD_LIBRARY_PATH" != "x" ]; then
DIRS_DEFAULT="$DIRS_DEFAULT:$LD_LIBRARY_PATH"
fi
@@ -64,7 +64,7 @@ LIBS_DSO=''
# for each library...
OIFS="$IFS" IFS=':'
for lib in $LIBS; do
- [ ".$lib" = . ] && continue
+ [ "x$lib" = "x" ] && continue
found='no'
found_indefdir='no'
@@ -74,14 +74,14 @@ for lib in $LIBS; do
# for each directory...
OIFS2="$IFS" IFS=":$DIFS"
for dir in ${DIRS} switch-to-defdirs ${DIRS_DEFAULT}; do
- [ ".$dir" = . ] && continue
- [ ".$dir" = .switch-to-defdirs ] && found_indefdir=yes
+ [ "x$dir" = "x" ] && continue
+ [ "x$dir" = "xswitch-to-defdirs" ] && found_indefdir=yes
[ ! -d $dir ] && continue
# search the file
OIFS3="$IFS" IFS="$DIFS"
for file in '' `cd $dir && ls lib${lib}.* 2>/dev/null`; do
- [ ".$file" = . ] && continue
+ [ "x$file" = "x" ] && continue
case $file in
*.so|*.so.[0-9]*|*.sl|*.sl.[0-9]* )
found=yes;
@@ -93,7 +93,7 @@ for lib in $LIBS; do
found_type=PIC
;;
*.a )
- if [ ".$found_type" = . ]; then
+ if [ "x$found_type" = "x" ]; then
found=yes
found_type=OBJ
fi
@@ -101,15 +101,15 @@ for lib in $LIBS; do
esac
done
IFS="$OIFS3"
- if [ ".$found" = .yes ]; then
+ if [ "x$found" = "xyes" ]; then
found_dir="$dir"
break
fi
done
IFS="$OIFS2"
- if [ ".$found" = .yes ]; then
- if [ ".$found_indefdir" != .yes ]; then
+ if [ "x$found" = "xyes" ]; then
+ if [ "x$found_indefdir" != "xyes" ]; then
eval "dirlist=\"\${DIRS_${found_type}}:\""
if [ ".`echo \"$dirlist\" | fgrep :$found_dir:`" = . ]; then
eval "DIRS_${found_type}=\"\$DIRS_${found_type}:${found_dir}\""
@@ -148,7 +148,7 @@ for type in OBJ PIC DSO; do
eval "libs=\"\$LIBS_${type}\""
opts=''
for lib in $libs; do
- [ ".$lib" = . ] && continue
+ [ "x$lib" = "x" ] && continue
opts="$opts -l$lib"
done
eval "LIBS_${type}=\"$opts\""
@@ -156,7 +156,7 @@ for type in OBJ PIC DSO; do
eval "dirs=\"\$DIRS_${type}\""
opts=''
for dir in $dirs; do
- [ ".$dir" = . ] && continue
+ [ "x$dir" = "x" ] && continue
opts="$opts -L$dir"
done
eval "DIRS_${type}=\"$opts\""
diff --git a/usr.sbin/httpd/src/include/alloc.h b/usr.sbin/httpd/src/include/alloc.h
index b68a89dc192..bc2777acd8d 100644
--- a/usr.sbin/httpd/src/include/alloc.h
+++ b/usr.sbin/httpd/src/include/alloc.h
@@ -93,10 +93,53 @@ typedef struct pool ap_pool;
pool * ap_init_alloc(void); /* Set up everything */
API_EXPORT(pool *) ap_make_sub_pool(pool *); /* All pools are subpools of permanent_pool */
+#if defined(EAPI)
+typedef enum { AP_POOL_RD, AP_POOL_RW } ap_pool_lock_mode;
+int ap_shared_pool_possible(void);
+void ap_init_alloc_shared(int);
+void ap_kill_alloc_shared(void);
+API_EXPORT(pool *) ap_make_shared_sub_pool(pool *);
+API_EXPORT(int) ap_acquire_pool(pool *, ap_pool_lock_mode);
+API_EXPORT(int) ap_release_pool(pool *);
+#endif
API_EXPORT(void) ap_destroy_pool(pool *);
-/* used to guarantee to the pool debugging code that the sub pool will not be
- * destroyed before the parent pool
+/* pools have nested lifetimes -- sub_pools are destroyed when the
+ * parent pool is cleared. We allow certain liberties with operations
+ * on things such as tables (and on other structures in a more general
+ * sense) where we allow the caller to insert values into a table which
+ * were not allocated from the table's pool. The table's data will
+ * remain valid as long as all the pools from which its values are
+ * allocated remain valid.
+ *
+ * For example, if B is a sub pool of A, and you build a table T in
+ * pool B, then it's safe to insert data allocated in A or B into T
+ * (because B lives at most as long as A does, and T is destroyed when
+ * B is cleared/destroyed). On the other hand, if S is a table in
+ * pool A, it is safe to insert data allocated in A into S, but it
+ * is *not safe* to insert data allocated from B into S... because
+ * B can be cleared/destroyed before A is (which would leave dangling
+ * pointers in T's data structures).
+ *
+ * In general we say that it is safe to insert data into a table T
+ * if the data is allocated in any ancestor of T's pool. This is the
+ * basis on which the POOL_DEBUG code works -- it tests these ancestor
+ * relationships for all data inserted into tables. POOL_DEBUG also
+ * provides tools (ap_find_pool, and ap_pool_is_ancestor) for other
+ * folks to implement similar restrictions for their own data
+ * structures.
+ *
+ * However, sometimes this ancestor requirement is inconvenient --
+ * sometimes we're forced to create a sub pool (such as through
+ * ap_sub_req_lookup_uri), and the sub pool is guaranteed to have
+ * the same lifetime as the parent pool. This is a guarantee implemented
+ * by the *caller*, not by the pool code. That is, the caller guarantees
+ * they won't destroy the sub pool individually prior to destroying the
+ * parent pool.
+ *
+ * In this case the caller must call ap_pool_join() to indicate this
+ * guarantee to the POOL_DEBUG code. There are a few examples spread
+ * through the standard modules.
*/
#ifndef POOL_DEBUG
#ifdef ap_pool_join
@@ -342,7 +385,7 @@ enum kill_conditions {
};
typedef struct child_info child_info;
-API_EXPORT(void) ap_note_subprocess(pool *a, int pid,
+API_EXPORT(void) ap_note_subprocess(pool *a, pid_t pid,
enum kill_conditions how);
API_EXPORT(int) ap_spawn_child(pool *, int (*)(void *, child_info *),
void *, enum kill_conditions,
diff --git a/usr.sbin/httpd/src/include/ap.h b/usr.sbin/httpd/src/include/ap.h
index ed18dbd002c..a04c90596a7 100644
--- a/usr.sbin/httpd/src/include/ap.h
+++ b/usr.sbin/httpd/src/include/ap.h
@@ -69,6 +69,7 @@ API_EXPORT(char *) ap_cpystrn(char *, const char *, size_t);
int ap_slack(int, int);
int ap_execle(const char *, const char *, ...);
int ap_execve(const char *, const char *argv[], const char *envp[]);
+API_EXPORT(int) ap_getpass(const char *prompt, char *pwbuf, size_t bufsiz);
/* small utility macros to make things easier to read */
@@ -158,6 +159,31 @@ API_EXPORT(int) ap_snprintf(char *buf, size_t len, const char *format,...)
__attribute__((format(printf,3,4)));
API_EXPORT(int) ap_vsnprintf(char *buf, size_t len, const char *format,
va_list ap);
+/* Simple BASE64 encode/decode functions.
+ *
+ * As we might encode binary strings, hence we require the length of
+ * the incoming plain source. And return the length of what we decoded.
+ *
+ * The decoding function takes any non valid char (i.e. whitespace, \0
+ * or anything non A-Z,0-9 etc as terminal.
+ *
+ * plain strings/binary sequences are not assumed '\0' terminated. Encoded
+ * strings are neither. But propably should.
+ *
+ */
+API_EXPORT(int) ap_base64encode_len(int len);
+API_EXPORT(int) ap_base64encode(char * coded_dst, const char *plain_src,int len_plain_src);
+API_EXPORT(int) ap_base64encode_binary(char * coded_dst, const unsigned char *plain_src,int len_plain_src);
+
+API_EXPORT(int) ap_base64decode_len(const char * coded_src);
+API_EXPORT(int) ap_base64decode(char * plain_dst, const char *coded_src);
+API_EXPORT(int) ap_base64decode_binary(unsigned char * plain_dst, const char *coded_src);
+
+/* Password validation, as used in AuthType Basic which is able to cope
+ * (based on the prexix) with the SHA1, Apache's internal MD5 and (depending
+ * on your platform either plain or crypt(3) passwords.
+ */
+API_EXPORT(char *) ap_validate_password(const char *passwd, const char *hash);
#ifdef __cplusplus
}
diff --git a/usr.sbin/httpd/src/include/ap_compat.h b/usr.sbin/httpd/src/include/ap_compat.h
index 4da74a61d07..ec0c753bca5 100644
--- a/usr.sbin/httpd/src/include/ap_compat.h
+++ b/usr.sbin/httpd/src/include/ap_compat.h
@@ -23,6 +23,7 @@ extern "C" {
#define acquire_mutex ap_acquire_mutex
#define add_cgi_vars ap_add_cgi_vars
#define add_common_vars ap_add_common_vars
+#define add_file_conf ap_add_file_conf
#define add_module ap_add_module
#define add_named_module ap_add_named_module
#define add_per_dir_conf ap_add_per_dir_conf
@@ -118,6 +119,7 @@ extern "C" {
#define escape_html ap_escape_html
#define escape_path_segment ap_escape_path_segment
#define escape_shell_cmd ap_escape_shell_cmd
+#define escape_uri ap_escape_uri
#define excess_requests_per_child ap_excess_requests_per_child
#define exists_scoreboard_image ap_exists_scoreboard_image
#define finalize_request_protocol ap_finalize_request_protocol
@@ -303,6 +305,8 @@ extern "C" {
#define rationalize_mtime ap_rationalize_mtime
#define read_config ap_read_config
#define read_request ap_read_request
+#define regexec ap_regexec
+#define regerror ap_regerror
#define register_cleanup ap_register_cleanup
#define register_other_child ap_register_other_child
#define release_mutex ap_release_mutex
@@ -349,6 +353,7 @@ extern "C" {
#define server_root_relative ap_server_root_relative
#define set_byterange ap_set_byterange
#define set_callback_and_alarm ap_set_callback_and_alarm
+#define set_config_vectors ap_set_config_vectors
#define set_content_length ap_set_content_length
#define set_etag ap_set_etag
#define set_file_slot ap_set_file_slot
diff --git a/usr.sbin/httpd/src/include/ap_config.h b/usr.sbin/httpd/src/include/ap_config.h
index 1b98de0a394..e7219cf892e 100644
--- a/usr.sbin/httpd/src/include/ap_config.h
+++ b/usr.sbin/httpd/src/include/ap_config.h
@@ -95,7 +95,9 @@ stat() properly */
* means. In particular it's missing inline and the __attribute__
* stuff. So we hack around it. PR#1613. -djg
*/
-#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 7 || defined(NEXT)
+#if !defined(__GNUC__) || __GNUC__ < 2 || \
+ (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ||\
+ defined(NEXT)
#define ap_inline
#define __attribute__(__x)
#define ENUM_BITFIELD(e,n,w) signed int n : w
@@ -316,11 +318,34 @@ typedef int rlim_t;
typedef int rlim_t;
#elif defined(SEQUENT)
-#define HAVE_GMTOFF 1
-#undef NO_KILLPG
-#define NO_SETSID
-#define NEED_STRDUP
+#define DEFAULT_USER "nobody"
+#define DEFAULT_GROUP "nobody"
+#define NO_SHMGET 1
+#define HAVE_MMAP 1
#define HAVE_SYSLOG 1
+#define USE_MMAP_FILES 1
+#define USE_MMAP_SCOREBOARD 1
+#define USE_FCNTL_SERIALIZED_ACCEPT 1
+#define JMP_BUF sigjmp_buf
+#undef NO_SETSID
+#if SEQUENT < 40
+typedef int rlim_t;
+#define NO_GETTIMEOFDAY
+#undef HAVE_SYS_RESOURCE_H /* exists but does not provide *rlimit funcs */
+#include <sys/times.h>
+#endif
+#if SEQUENT < 42
+#define NEED_STRCASECMP
+#define NEED_STRNCASECMP
+#endif
+#if SEQUENT < 44
+#define NO_KILLPG 1
+#define NET_SIZE_T int
+#endif
+#if SEQUENT >= 44
+#undef NO_KILLPG
+#define NET_SIZE_T size_t
+#endif
#elif defined(NEXT)
typedef unsigned short mode_t;
@@ -365,10 +390,6 @@ typedef unsigned short mode_t;
#endif
#ifndef S_IWOTH
#define S_IWOTH 000002
-#ifndef rlim_t
-typedef int rlim_t;
-#endif
-typedef u_long n_long;
#endif
#define STDIN_FILENO 0
@@ -386,12 +407,29 @@ typedef int pid_t;
#define NO_USE_SIGACTION
#define HAVE_SYSLOG 1
-#elif defined(RHAPSODY) /* Mac OS X Server */
+#if defined(__DYNAMIC__)
+#define HAVE_DYLD
+#define DYLD_CANT_UNLOAD
+#endif
+
+#elif defined(MAC_OS) || defined(MAC_OS_X_SERVER) /* Mac OS (>= 10.0) and Mac OS X Server (<= 5.x) */
+#undef PLATFORM
+#ifdef MAC_OS_X_SERVER
+#define PLATFORM "Mac OS X Server"
+#else
+#define PLATFORM "Mac OS"
+#endif
+#define HAVE_DYLD
+#ifdef MAC_OS_X_SERVER
+#define DYLD_CANT_UNLOAD
+#endif /* MAC_OS_X_SERVER */
#define HAVE_GMTOFF
#define HAVE_MMAP
#define USE_MMAP_FILES
#define USE_MMAP_SCOREBOARD
+#ifdef MAC_OS_X_SERVER
#define MAP_TMPFILE
+#endif /* MAC_OS_X_SERVER */
#define HAVE_RESOURCE
#define HAVE_SNPRINTF
#define JMP_BUF jmp_buf
@@ -399,26 +437,52 @@ typedef int pid_t;
#define USE_FLOCK_SERIALIZED_ACCEPT
#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
/*
- * If you are using APACI, (you should be on Rhapsody) these
- * values are set at configure time. These are here as reference;
- * the apache that is built into Rhapsody is configured with
- * these values.
+ * If you are using APACI, (you probably should be on Mac OS) these
+ * values are set at configure time.
*/
-#if 0
+#ifndef HTTPD_ROOT
#define HTTPD_ROOT "/Local/Library/WebServer"
+#endif
+#ifndef DOCUMENT_LOCATION
#define DOCUMENT_LOCATION HTTPD_ROOT "/Documents"
+#endif
+#ifndef DEFAULT_XFERLOG
#define DEFAULT_XFERLOG "Logs/Access"
+#endif
+#ifndef DEFAULT_ERRORLOG
#define DEFAULT_ERRORLOG "Logs/Errors"
+#endif
+#ifndef DEFAULT_PIDLOG
#define DEFAULT_PIDLOG "Logs/Process"
+#endif
+#ifndef DEFAULT_SCOREBOARD
#define DEFAULT_SCOREBOARD "Logs/Status"
+#endif
+#ifndef DEFAULT_LOCKFILE
#define DEFAULT_LOCKFILE "Logs/Lock"
+#endif
+#ifndef SERVER_CONFIG_FILE
#define SERVER_CONFIG_FILE "Configuration/Server"
+#endif
+#ifndef RESOURCE_CONFIG_FILE
#define RESOURCE_CONFIG_FILE "Configuration/Resources"
+#endif
+#ifndef TYPES_CONFIG_FILE
#define TYPES_CONFIG_FILE "Configuration/MIME"
+#endif
+#ifndef ACCESS_CONFIG_FILE
#define ACCESS_CONFIG_FILE "Configuration/Access"
+#endif
+#ifndef DEFAULT_USER_DIR
#define DEFAULT_USER_DIR "Library/Web Documents"
-#define DEFAULT_USER "nobody"
-#define DEFAULT_GROUP "nogroup"
+#endif
+#ifndef DEFAULT_USER
+#define DEFAULT_USER "www"
+#endif
+#ifndef DEFAULT_GROUP
+#define DEFAULT_GROUP "www"
+#endif
+#ifndef DEFAULT_PATH
#define DEFAULT_PATH "/bin:/usr/bin:/usr/local/bin"
#endif
@@ -458,7 +522,13 @@ typedef int pid_t;
#define USE_MMAP_FILES
/* flock is faster ... but hasn't been tested on 1.x systems */
-#define USE_FLOCK_SERIALIZED_ACCEPT
+/* PR#3531 indicates flock() may not be stable, probably depends on
+ * kernel version. Go back to using fcntl, but provide a way for
+ * folks to tweak their Configuration to get flock.
+ */
+#ifndef USE_FLOCK_SERIALIZED_ACCEPT
+#define USE_FCNTL_SERIALIZED_ACCEPT
+#endif
#define SYS_SIGLIST _sys_siglist
@@ -559,12 +629,10 @@ extern char *crypt();
#define HAVE_SHMGET 1
#define USE_SHMGET_SCOREBOARD
#ifdef _OSD_POSIX /* BS2000-POSIX mainframe needs initgroups */
-#define NEED_INITGROUPS
#define NEED_HASHBANG_EMUL /* execve() doesn't start shell scripts by default */
-#undef HAVE_SHMGET
+#define _KMEMUSER /* Enable SHM_R/SHM_W defines in <shm.h> */
#undef NEED_STRCASECMP
#undef NEED_STRNCASECMP
-#undef USE_SHMGET_SCOREBOARD
#undef bzero
#endif /*_OSD_POSIX*/
@@ -738,13 +806,14 @@ typedef int rlim_t;
#define NO_KILLPG
#define NEED_STRCASECMP
#define NEED_STRNCASECMP
+#define NEED_PROCESS_H
#define NO_SETSID
#define NO_TIMES
#define CASE_BLIND_FILESYSTEM
/* Add some drive name support */
#define chdir _chdir2
#include <sys/time.h>
-#define MAXSOCKETS 4096
+#define MAXSOCKETS 2048
#define USE_OS2_SCOREBOARD
#define NO_RELIABLE_PIPED_LOGS
#define USE_OS2SEM_SERIALIZED_ACCEPT
@@ -844,10 +913,16 @@ typedef int rlim_t;
#include <sysgtime.h>
#define PRIMECRAS 0x010000
#define JMP_BUF jmp_buf
+#define HAVE_SHMGET
+#undef HAVE_SYS_RESOURCE_H
#define NEED_INITGROUPS
+#define NEED_SIGNAL_INTERRUPT
+#include <strings.h>
+#ifndef __strings_h
#define NEED_STRCASECMP
-#define NEED_STRDUP
#define NEED_STRNCASECMP
+#endif
+#define NEED_STRDUP
#define NO_DBM_REWRITEMAP
#define NO_GETTIMEOFDAY
#define NO_KILLPG
@@ -856,16 +931,26 @@ typedef int rlim_t;
#define NO_OTHER_CHILD
#define NO_RELIABLE_PIPED_LOGS
#define NO_SETSID
-#define NO_SHMGET
#define NO_SLACK
#define NO_TIMES
#define NO_USE_SIGACTION
#define NO_WRITEV
#define USE_LONGJMP
+/*#define USE_SHMGET_SCOREBOARD*/
+#define USE_TPF_ACCEPT
+#define USE_TPF_CORE_SERIALIZED_ACCEPT
+/*#define USE_TPF_DAEMON*/
+#define USE_TPF_SCOREBOARD
#define USE_TPF_SELECT
#undef offsetof
#define offsetof(s_type,field) ((size_t)&(((s_type*)0)->field))
+#elif defined(__TANDEM)
+#define NO_WRITEV
+#define NO_KILLPG
+#define NEED_INITGROUPS
+#define NO_SLACK
+
#else
/* Unknown system - Edit these to match */
#ifdef BSD
@@ -919,7 +1004,7 @@ typedef int rlim_t;
* __private_extern__.
* For other systems, make that a no-op.
*/
-#if defined(RHAPSODY)
+#if (defined(MAC_OS) || defined(MAC_OS_X_SERVER)) && defined(__DYNAMIC__)
#define ap_private_extern __private_extern__
#else
#define ap_private_extern
@@ -949,8 +1034,11 @@ typedef int rlim_t;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifdef __TANDEM
+#include <strings.h>
+#endif
#include "ap_ctype.h"
-#if !defined(MPE) && !defined(WIN32) && !defined(TPF)
+#if !defined(MPE) && !defined(WIN32) && !defined(TPF) && !defined(__TANDEM)
#include <sys/file.h>
#endif
#ifndef WIN32
@@ -970,24 +1058,26 @@ typedef int rlim_t;
#include <pwd.h>
#include <grp.h>
#include <fcntl.h>
-#include <limits.h>
#define closesocket(s) close(s)
#ifndef O_BINARY
#define O_BINARY (0)
#endif
#else /* WIN32 */
-#include <winsock.h>
+#include <winsock2.h>
#include <malloc.h>
#include <io.h>
#include <fcntl.h>
#endif /* ndef WIN32 */
-
+#include <limits.h>
#include <time.h> /* for ctime */
#ifdef WIN32
#define strftime(s,max,format,tm) os_strftime(s,max,format,tm)
#endif
#include <signal.h>
+#if defined(TPF) && defined(NSIG)
+#undef NSIG
+#endif
#include <errno.h>
#if !defined(QNX) && !defined(CONVEXOS11) && !defined(NEXT) && !defined(TPF)
#include <memory.h>
@@ -1090,13 +1180,32 @@ Sigfunc *signal(int signo, Sigfunc * func);
#endif
#endif
-#ifdef SELECT_NEEDS_CAST
+/* Majority of os's want to verify FD_SETSIZE */
+#if !defined(WIN32) && !defined(TPF)
+#define CHECK_FD_SETSIZE
+#endif
+
+#ifdef USE_TPF_SELECT
#define ap_select(_a, _b, _c, _d, _e) \
+ tpf_select(_a, _b, _c, _d, _e)
+#elif defined(SELECT_NEEDS_CAST)
+#define ap_select(_a, _b, _c, _d, _e) \
select((_a), (int *)(_b), (int *)(_c), (int *)(_d), (_e))
-#elif defined(USE_TPF_SELECT)
-#define ap_select tpf_select
#else
-#define ap_select select
+#define ap_select(_a, _b, _c, _d, _e) \
+ select(_a, _b, _c, _d, _e)
+#endif
+
+#ifdef USE_TPF_ACCEPT
+#define ap_accept(_fd, _sa, _ln) tpf_accept(_fd, _sa, _ln)
+#else
+#define ap_accept(_fd, _sa, _ln) accept(_fd, _sa, _ln)
+#endif
+
+#ifdef NEED_SIGNAL_INTERRUPT
+#define ap_check_signals() tpf_process_signals()
+#else
+#define ap_check_signals()
#endif
#ifdef ULTRIX_BRAIN_DEATH
diff --git a/usr.sbin/httpd/src/include/ap_ctx.h b/usr.sbin/httpd/src/include/ap_ctx.h
index 85a8ae93322..18f0f334e7f 100644
--- a/usr.sbin/httpd/src/include/ap_ctx.h
+++ b/usr.sbin/httpd/src/include/ap_ctx.h
@@ -60,6 +60,8 @@
** Written by Ralf S. Engelschall <rse@engelschall.com>
*/
+#ifdef EAPI
+
#ifndef AP_CTX_H
#define AP_CTX_H
@@ -87,11 +89,22 @@ typedef struct {
typedef ap_ctx_rec ap_ctx;
/*
+ * Some convinience macros for storing _numbers_ 0...n in contexts, i.e.
+ * treating numbers as pointers but keeping track of the NULL return code of
+ * ap_ctx_get.
+ */
+#define AP_CTX_NUM2PTR(n) (void *)((unsigned int)(n)+1)
+#define AP_CTX_PTR2NUM(p) (unsigned int)(((char *)(p))-1)
+
+/*
* Prototypes for Context Handling Functions
*/
API_EXPORT(ap_ctx *)ap_ctx_new(pool *p);
API_EXPORT(void) ap_ctx_set(ap_ctx *ctx, char *key, void *val);
API_EXPORT(void *) ap_ctx_get(ap_ctx *ctx, char *key);
+API_EXPORT(ap_ctx *)ap_ctx_overlay(pool *p, ap_ctx *over, ap_ctx *base);
#endif /* AP_CTX_H */
+
+#endif /* EAPI */
diff --git a/usr.sbin/httpd/src/include/ap_ctype.h b/usr.sbin/httpd/src/include/ap_ctype.h
index c4ff812d5ee..e0a6abcaa07 100644
--- a/usr.sbin/httpd/src/include/ap_ctype.h
+++ b/usr.sbin/httpd/src/include/ap_ctype.h
@@ -79,6 +79,7 @@ extern "C" {
#define ap_ispunct(c) (ispunct(((unsigned char)(c))))
#define ap_isspace(c) (isspace(((unsigned char)(c))))
#define ap_isupper(c) (isupper(((unsigned char)(c))))
+#define ap_isxdigit(c) (isxdigit(((unsigned char)(c))))
#define ap_tolower(c) (tolower(((unsigned char)(c))))
#define ap_toupper(c) (toupper(((unsigned char)(c))))
diff --git a/usr.sbin/httpd/src/include/ap_hook.h b/usr.sbin/httpd/src/include/ap_hook.h
index 532dec8bc8d..d00bfec924b 100644
--- a/usr.sbin/httpd/src/include/ap_hook.h
+++ b/usr.sbin/httpd/src/include/ap_hook.h
@@ -1,3 +1,6 @@
+#if 0
+=cut
+#endif
/* ====================================================================
* Copyright (c) 1998 The Apache Group. All rights reserved.
*
@@ -56,183 +59,21 @@
*/
/*
-** Generic Hook Interface for Apache
+** Implementation of a Generic Hook Interface for Apache
** Written by Ralf S. Engelschall <rse@engelschall.com>
**
-** SYNOPSIS
-**
-** Main Setup:
-** void ap_hook_init (void);
-** void ap_hook_kill (void);
-**
-** Hook Configuration and Registration:
-** int ap_hook_configure (char *hook, int sig, int modeid, ap_hook_value modeval);
-** int ap_hook_register (char *hook, void *func, void *ctx);
-** int ap_hook_unregister(char *hook, void *func);
-**
-** Hook Usage:
-** int ap_hook_configured(char *hook);
-** int ap_hook_registered(char *hook);
-** int ap_hook_call (char *hook, ...);
-**
-** DESCRIPTION
-**
-** This implements a generic hook interface for Apache which can be used
-** for loosely couple code through arbitrary hooks. There are two use cases
-** for this mechanism:
-**
-** 1. Inside a specific code section you want to perform a specific
-** function call. But you want to allow one or even more modules to
-** override this function call by registering hook functions. Those
-** functions are registered on a stack and can be configured to have a
-** `decline' return value. As long as there are functions which return
-** the `decline' value the next function on the stack is tried. When a
-** function doesn't return the `decline' value the hook call stops. The
-** intent of this usage is to not hard-code function calls.
-**
-** 2. Inside a specific code you have a function you want to export.
-** But you first want to allow other code to override this function.
-** And second you want to export this function without real linker
-** symbol references. Instead you want to register the function and let
-** the users call this function via name. The intent of this usage is to
-** allow inter-module communication without direct symbol references,
-** which are a big NO-NO for the DSO situation.
-**
-** And we have one major design goal: The hook call should be very similar
-** to the corresponding direct function call while still providing maximum
-** flexiblity, i.e. any function signature (the set of types for the return
-** value and the arguments) should be supported. And it should be possible
-** to register always a context (ctx) variable with a function which is
-** passed to the corresponding function when the hook call is performed.
-**
-** Using this hook interface is always a four-step process:
-**
-** 1. Initialize or destroy the hook mechanism inside your main program:
-**
-** ap_hook_init();
-** :
-** ap_hook_kill();
-**
-** 2. Configure a particular hook by specifing its name, signature
-** and return type semantic:
-**
-** ap_hook_configure("lookup", AP_HOOK_SIG2(ptr,ptr,ctx), AP_HOOK_DECLINE(NULL));
-** ap_hook_configure("echo", AP_HOOK_SIG2(int,ptr), AP_HOOK_TOPMOST);
-**
-** This configures two hooks:
-** - A hook named "lookup" with the signature "void *lookup(void *)"
-** and a return code semantic which says: As long as a registered hook
-** function returns NULL and more registered functions exists we we
-** proceed.
-** - A hook named "echo" with the signature "int echo(void *)" and a
-** return code semantic which says: Only the top most function on the
-** registered function stack is tried, independed what value it
-** returns.
-**
-** 3. Register the actual functions which should be used by the hook:
-**
-** ap_hook_register("lookup", mylookup, mycontext);
-** ap_hook_register("echo", myecho);
-**
-** This registers the function mylookup() under the "lookup" hook with
-** the context given by the variable mycontext. And it registers the
-** function myecho() under the "echo" hook without any context.
-**
-** 4. Finally use the hook, i.e. instead of using direct function calls
-** like
-**
-** vp = mylookup("foo", mycontext);
-** n = myecho("bar");
-**
-** you now can use:
-**
-** ap_hook_call("lookup", &vp, "foo");
-** ap_hook_call("echo", &n, "bar");
-**
-** Notice two things: First the context for the mylookup() function is
-** automatically added by the hook mechanism. And it is a different and
-** not fixed context for each registered function, of course. Second,
-** return values always have to be pushed into variables and they a
-** pointer to them has to be given as the second argument (except for
-** functions which have a void return type, of course).
-**
-** BTW, the return value of ap_hook_call() is TRUE or FALSE. TRUE when
-** at least one function call was successful (always the case for
-** AP_HOOK_TOPMOST). FALSE when all functions returned the decline
-** value or no functions are registered at all.
-**
-** RESTRICTIONS
-**
-** To make the hook implementation efficient and to not bloat up the code a
-** few restrictions have to make:
-**
-** 1. Only function calls with up to 4 arguments are supported.
-** When more are needed you can either extend the hook implementation by
-** using more bits for the signature configuration or you can do a
-** workaround when the functions is your own one: Put the remaining
-** (N-5) arguments into a structure and pass only a pointer (one
-** argument) as the forth argument.
-**
-** 2. Only the following types are supported:
-** - For the return value:
-** void (= none), char, int, float, double, ptr (= void*)
-** - For the arguments:
-** ctx (= context), char, int, float, double, ptr (= void*)
-** This means in theory there are 6^5 (=7776) signature combinations are
-** possible. But because we don't need all of them inside Apache and it
-** would bloat up the code dramatically we implement only a subset of
-** those combinations. The to be implemented signatures can be specified
-** inside ap_hook.c and the corresponding code can be automatically
-** generated by running `perl ap_hook.c' (yeah, no joke ;-). So when
-** you need a hook with a different still not implemented signature you
-** either have to again use a workaround as above (i.e. use a structure)
-** or just add the signature to the ap_hook.c file.
-**
-** EXAMPLE
-**
-** We want to call `ssize_t read(int, void *, size_t)' through hooks in
-** order to allow modules to override this call. So, somewhere we have a
-** replacement function for read() defined:
-**
-** ssize_t my_read(int, void *, size_t);
-**
-** We now configure a `read' hook. Here the AP_HOOK_SIGx() macro defines
-** the signature of the read()-like callback functions and has to match the
-** prototype of read(). But we have to replace typedefs with the physical
-** types. And AP_HOOK_DECLINE() sets the return value of the read()-like
-** functions which forces the next hook to be called (here -1). And we
-** register the original read function.
-**
-** ap_hook_configure("read", AP_HOOK_SIG4(int,int,ptr,int),
-** AP_HOOK_DECLINE(-1));
-** ap_hook_register("read", read);
-**
-** Now a module wants to override the read() call and registers one more
-** function (which has to match the same prototype as read() of course):
-**
-** ap_hook_register("read", my_read);
+** See POD document at end of this file for description.
+** View it with the command ``pod2man ap_hook.h | nroff -man | more''
**
-** The function logically gets pushed onto a stack, so the execution order
-** is the reverse register order, i.e. last registered - first called. Now
-** we can replace the standard read() call
-**
-** bytes = read(fd, buf, bufsize);
-** if (bytes == -1)
-** ...error...
-**
-** with the hook-call:
-**
-** rc = ap_hook_call("read", &bytes, fd, buf, bufsize);
-** if (rc == FALSE)
-** ...error...
-**
-** Now internally the following is done: The call "bytes = my_read(fd, buf,
-** bufsize)" is done. When it returns not -1 (the decline value) nothing
-** more is done. But when my_read() returned -1 the next function is tried:
-** "bytes = read(fd, buf, bufsize)". When this one returns -1 again you get
-** rc == FALSE. When it finally returns not -1 you get rc == TRUE.
+** Attention: This header file is a little bit tricky.
+** It's a combination of a C source and an embedded POD document
+** The purpose of this is to have both things together at one
+** place. So you can both pass this file to the C compiler and
+** the pod2man translater.
*/
+#ifdef EAPI
+
#ifndef AP_HOOK_H
#define AP_HOOK_H
@@ -414,11 +255,13 @@ typedef unsigned int ap_hook_mode;
#define AP_HOOK_MODE_UNKNOWN 0
#define AP_HOOK_MODE_TOPMOST 1
#define AP_HOOK_MODE_DECLINE 2
-#define AP_HOOK_MODE_ALL 3
+#define AP_HOOK_MODE_DECLTMP 3
+#define AP_HOOK_MODE_ALL 4
/* the constructors for the return value modes */
#define AP_HOOK_TOPMOST AP_HOOK_MODE_TOPMOST
#define AP_HOOK_DECLINE(val) AP_HOOK_MODE_DECLINE, (val)
+#define AP_HOOK_DECLTMP(val) AP_HOOK_MODE_DECLTMP, (val)
#define AP_HOOK_ALL AP_HOOK_MODE_ALL
/*
@@ -543,3 +386,325 @@ API_EXPORT(int) ap_hook_use (char *hook, ap_hook_sig sig, ap_
API_EXPORT(int) ap_hook_call (char *hook, ...);
#endif /* AP_HOOK_H */
+
+#endif /* EAPI */
+/*
+=pod
+##
+## Embedded POD document
+##
+
+=head1 NAME
+
+B<ap_hook> - B<Generic Hook Interface for Apache>
+
+=head1 SYNOPSIS
+
+B<Hook Library Setup:>
+
+ void ap_hook_init(void);
+ void ap_hook_kill(void);
+
+B<Hook Configuration and Registration:>
+
+ int ap_hook_configure(char *hook, ap_hook_sig sig, ap_hook_mode mode);
+ int ap_hook_register(char *hook, void *func, void *ctx);
+ int ap_hook_unregister(char *hook, void *func);
+
+B<Hook Usage:>
+
+ ap_hook_state ap_hook_status(char *hook);
+ int ap_hook_use(char *hook, ap_hook_sig sig, ap_hook_mode mode, ...);
+ int ap_hook_call(char *hook, ...);
+
+B<Hook Signature Constructors> (ap_hook_sig):
+
+ AP_HOOK_SIG1(rc)
+ AP_HOOK_SIG2(rc,a1)
+ AP_HOOK_SIG3(rc,a1,a2)
+ AP_HOOK_SIG4(rc,a1,a2,a3)
+ AP_HOOK_SIG5(rc,a1,a2,a3,a4)
+ AP_HOOK_SIG6(rc,a1,a2,a3,a4,a5)
+ AP_HOOK_SIG7(rc,a1,a2,a3,a4,a5,a6)
+ AP_HOOK_SIG8(rc,a1,a2,a3,a4,a5,a6,a7)
+
+B<Hook Modes Constructors> (ap_hook_mode):
+
+ AP_HOOK_TOPMOST
+ AP_HOOK_DECLINE(value)
+ AP_HOOK_DECLTMP(value)
+ AP_HOOK_ALL
+
+B<Hook States> (ap_hook_state):
+
+ AP_HOOK_STATE_UNDEF
+ AP_HOOK_STATE_NOTEXISTANT
+ AP_HOOK_STATE_ESTABLISHED
+ AP_HOOK_STATE_CONFIGURED
+ AP_HOOK_STATE_REGISTERED
+
+=head1 DESCRIPTION
+
+This library implements a generic hook interface for Apache which can be used
+to loosely couple code through arbitrary hooks. There are two use cases for
+this mechanism:
+
+=over 3
+
+=item B<1. Extension and Overrides>
+
+Inside a specific code section you want to perform a specific function call
+for extension reasons. But you want to allow one or more modules to implement
+this function by registering hooks. Those hooks are registered on a stack and
+can be even configured to have a I<decline> return value. As long as there are
+functions which return the decline value the next function on the stack is
+tried. When the first function doesn't return the decline value the hook call
+stops.
+
+The original intent of this use case is to provide a flexible extension
+mechanism where modules can override functionality.
+
+=item B<2. Intercommunication>
+
+Inside a specific code you have a function you want to export. But you first
+want to allow other code to override this function. And second you want to
+export this function without real object file symbol references. Instead you
+want to register the function and let the users call this function by name.
+
+The original intent of this use case is to allow inter-module communication
+without direct symbol references, which are a big I<no-no> for the I<Dynamic
+Shared Object> (DSO) situation.
+
+=back
+
+And the following design goals existed:
+
+=over 3
+
+=item B<1. Minimum code changes>
+
+The hook calls should look very similar to the corresponding direct function
+call to allow one to easily translate it. And the total amount of changes for
+the hook registration, hook configuration and hook usage should be as small as
+possible to minimize the total code changes. Additionally a shorthand API
+function (ap_hook_use) should be provided which lets one trivially add a hook
+by just changing the code at a single location.
+
+=item B<2. The hook call has to be maximum flexible>
+
+In order to avoid nasty hacks, maximum flexiblity for the hook calls is
+needed, i.e. any function signature (the set of types for the return value and
+the arguments) should be supported. And it should be possible to
+register always a context (ctx) variable with a function which is passed to
+the corresponding function when the hook call is performed.
+
+=back
+
+The implementation of this library directly followed these two design goals.
+
+=head1 USAGE
+
+Using this hook API is a four-step process:
+
+=over 3
+
+=item B<1. Initialization>
+
+Initialize or destroy the hook mechanism inside your application program:
+
+ ap_hook_init();
+ :
+ ap_hook_kill();
+
+=item B<2. Configuration>
+
+Configure a particular hook by specifing its name, signature and return type
+semantic:
+
+ ap_hook_configure("lookup", AP_HOOK_SIG2(ptr,ptr,ctx), AP_HOOK_DECLINE(NULL));
+ ap_hook_configure("setup", AP_HOOK_SIG2(int,ptr,char), AP_HOOK_DECLTMP(FALSE));
+ ap_hook_configure("read", AP_HOOK_SIG2(void,ptr), AP_HOOK_TOPMOST);
+ ap_hook_configure("logit", AP_HOOK_SIG2(void,ptr), AP_HOOK_ALL);
+
+This configures four hooks:
+
+A hook named C<lookup> with the signature C<void *lookup(void *, void *)>
+(where the second argument is C<NULL> or the private context pointer of the
+hook function which can be optionally provided at the registration step
+later) and a return code semantic which says: Proceed as long as the
+registered lookup functions return C<NULL> or no more registered functions
+exists. A call for this hook has to provide 2 argument only (a pointer to the
+return variable and the first argument), because the context is
+implicitly provided by the hook mechanism. Sample idea: I<The first function
+who was successful in looking up a variable provides the value>.
+
+A hook named C<setup> with the signature C<int setup(void *, char)" and a
+return code semantic equal to the one of the C<lookup> hook. But the decline
+return value is implemented by a temporay variable of the hook mechanism and
+only used for the decline decision. So a call to this hook has to provide 2
+arguments only (the first and second argument, but no address to a return
+value). Sample idea: I<Any function can handle the setup and when one
+function handled it stops the processing by indicating this with the return
+value>.
+
+A hook named C<read> with the signature C<void read(void *)> and a return code
+semantic which says: Only the top most function on the registered function
+stack is tried (and independet of a possible return value in non-void
+context). A call to this hook has to provide exactly 1 argument (the
+single argument to the hook function). Sample idea: I<We want to
+use a read function and allow others to override it, but independent how much
+registered functions exists, only top most (= last registered) function
+overrides and is used>.
+
+A hook named C<logit> with the signature C<void logit(void *)> and a return
+code semantic which says: All registered functions on the hook functioin stack
+are tried. Sample idea: I<We pass a FILE pointer to the logging functions and
+any function can log whatever it wants>.
+
+=item B<3. Registration>
+
+Register the actual functions which should be used by the hook:
+
+ ap_hook_register("lookup", mylookup, mycontext);
+ ap_hook_register("setup", mysetup);
+ ap_hook_register("read", myread);
+ ap_hook_register("logit", mylogit);
+
+This registers the function C<mylookup()> under the C<lookup> hook with the
+private context given by the variable C<mycontext>. And it registers the
+function C<mysetup()> under the C<setup> hook without any context. Same for
+C<myread> and C<mylogit>.
+
+=item B<4. Usage>
+
+Finally use the hooks, i.e. instead of using direct function calls like
+
+ rc = mylookup(a1, a2);
+ rc = mysetup(a1, a2);
+ myread(a1);
+ mylogit(a1);
+
+you now use:
+
+ ap_hook_call("lookup", &rc, a1, a2);
+ ap_hook_call("setup", &rc, a1, a2);
+ ap_hook_call("read", a1);
+ ap_hook_call("logit", a1);
+
+which are internally translated to:
+
+ rc = mylookup(a1, a2, mycontext);
+ rc = mysetup(a1, a2);
+ myread(a1);
+ mylogit(a1);
+
+Notice two things here: First the context (C<mycontext>) for the C<mylookup()>
+function is automatically added by the hook mechanism. And it is a different
+(and not fixed) context for each registered function, of course. Second,
+return values always have to be pushed into variables and a pointer to them
+has to be given as the second argument to C<ap_hook_call> (except for
+functions which have a void return type, of course).
+
+BTW, the return value of C<ap_hook_call()> is always C<TRUE> or C<FALSE>.
+C<TRUE> when at least one function call was successful (always the case for
+C<AP_HOOK_TOPMOST> and C<AP_HOOK_ALL>). C<FALSE> when all functions
+returned the decline value or no functions are registered at all.
+
+=back
+
+=head1 RESTRICTIONS
+
+To make the hook implementation efficient and to not bloat up the code too
+much a few restrictions have to make:
+
+=over 3
+
+=item 1.
+
+Only function calls with up to 4 arguments are implemented. When more are
+needed you can either extend the hook implementation by using more bits for
+the signature configuration or you can do a workaround when the function is
+your own one: Put the remaining (N-4-1) arguments into a structure and pass
+only a pointer (one argument) as the forth argument.
+
+=item 2.
+
+Only the following ANSI C variable types are supported:
+
+ - For the return value:
+ void (= none), char, int, float, double, ptr (= void *)
+ - For the arguments:
+ ctx (= context), char, int, float, double, ptr (= void *)
+
+This means in theory that 6^5 (=7776) signature combinations are possible. But
+because we don't need all of them inside Apache and it would bloat up the code
+too dramatically we implement only a subset of those combinations. The
+implemented signatures can be specified inside C<ap_hook.c> and the
+corresponding code can be automatically generated by running ``C<perl
+ap_hook.c>'' (yeah, no joke ;-). So when you need a hook with a different
+still not implemented signature you either have to again use a workaround as
+above (i.e. use a structure) or just add the signature to the C<ap_hook.c>
+file.
+
+=head1 EXAMPLE
+
+We want to call `C<ssize_t read(int, void *, size_t)>' through hooks in order
+to allow modules to override this call. So, somewhere we have a replacement
+function for C<read()> defined (same signature, of course):
+
+ ssize_t my_read(int, void *, size_t);
+
+We now configure a C<read> hook. Here the C<AP_HOOK_SIGx()> macro defines the
+signature of the C<read()>-like callback functions and has to match the
+prototype of C<read()>. But we have to replace typedefs with the physical
+underlaying ANSI C types. And C<AP_HOOK_DECLINE()> sets the return value of
+the read()-like functions which forces the next hook to be called (here -1).
+And we register the original C<read()> function as the default hook.
+
+ ap_hook_configure("read",
+ AP_HOOK_SIG4(int,int,ptr,int),
+ AP_HOOK_DECLINE(-1));
+ ap_hook_register("read", read);
+
+Now a module wants to override the C<read()> call and registers the
+C<my_read()> function:
+
+ ap_hook_register("read", my_read);
+
+The function logically gets pushed onto a stack, so the execution order is the
+reverse registering order, i.e. I<last registered - first called>. Now we can
+replace the standard C<read()> call
+
+ bytes = read(fd, buf, bufsize);
+ if (bytes == -1)
+ ...error...
+
+with the hook based call:
+
+ rc = ap_hook_call("read", &bytes, fd, buf, bufsize);
+ if (rc == FALSE)
+ ...error...
+
+Now internally the following is done: The call `C<bytes = my_read(fd, buf,
+bufsize)>' is done. When it returns not -1 (the decline value) nothing
+more is done. But when C<my_read()> returns -1 the next function is tried:
+`C<bytes = read(fd, buf, bufsize)>'. When this one also returns -1 you get
+`rc == FALSE'. When it finally returns not -1 you get `rc == TRUE'.
+
+=head1 SEE ALSO
+
+ap_ctx(3)
+
+=head1 HISTORY
+
+The ap_hook(3) interface was originally designed and implemented in October
+1998 by Ralf S. Engelschall as part of the mod_ssl project.
+
+=head1 AUTHOR
+
+ Ralf S. Engelschall
+ rse@engelschall.com
+ www.engelschall.com
+
+=cut
+*/
diff --git a/usr.sbin/httpd/src/include/ap_md5.h b/usr.sbin/httpd/src/include/ap_md5.h
index 0da983c62fd..1e5b9cdaa8a 100644
--- a/usr.sbin/httpd/src/include/ap_md5.h
+++ b/usr.sbin/httpd/src/include/ap_md5.h
@@ -104,10 +104,21 @@ typedef struct {
unsigned char buffer[64]; /* input buffer */
} AP_MD5_CTX;
-API_EXPORT(void) ap_MD5Init(AP_MD5_CTX * context);
-API_EXPORT(void) ap_MD5Update(AP_MD5_CTX * context, const unsigned char *input,
- unsigned int inputLen);
-API_EXPORT(void) ap_MD5Final(unsigned char digest[16], AP_MD5_CTX * context);
+/*
+ * Define the Magic String prefix that identifies a password as being
+ * hashed using our algorithm.
+ */
+#define AP_MD5PW_ID "$apr1$"
+#define AP_MD5PW_IDLEN 6
+
+API_EXPORT(void) ap_MD5Init(AP_MD5_CTX *context);
+API_EXPORT(void) ap_MD5Update(AP_MD5_CTX *context, const unsigned char *input,
+ unsigned int inputLen);
+API_EXPORT(void) ap_MD5Final(unsigned char digest[16], AP_MD5_CTX *context);
+API_EXPORT(void) ap_MD5Encode(const unsigned char *password,
+ const unsigned char *salt,
+ char *result, size_t nbytes);
+API_EXPORT(void) ap_to64(char *s, unsigned long v, int n);
#ifdef __cplusplus
}
diff --git a/usr.sbin/httpd/src/include/ap_mm.h b/usr.sbin/httpd/src/include/ap_mm.h
new file mode 100644
index 00000000000..5e85c53ffbe
--- /dev/null
+++ b/usr.sbin/httpd/src/include/ap_mm.h
@@ -0,0 +1,130 @@
+/* ====================================================================
+ * Copyright (c) 1999 The Apache Group. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ */
+
+/*
+**
+** ap_mm.h -- wrapper code for MM shared memory library
+**
+*/
+
+#ifdef EAPI
+
+#ifndef AP_MM_H
+#define AP_MM_H 1
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+API_EXPORT(int) ap_mm_useable(void);
+
+typedef void AP_MM;
+typedef enum { AP_MM_LOCK_RD, AP_MM_LOCK_RW } ap_mm_lock_mode;
+
+/* Global Malloc-Replacement API */
+API_EXPORT(int) ap_MM_create(size_t size, char *file);
+API_EXPORT(int) ap_MM_permission(mode_t mode, uid_t owner, gid_t group);
+API_EXPORT(void) ap_MM_destroy(void);
+API_EXPORT(int) ap_MM_lock(ap_mm_lock_mode mode);
+API_EXPORT(int) ap_MM_unlock(void);
+API_EXPORT(void *) ap_MM_malloc(size_t size);
+API_EXPORT(void *) ap_MM_realloc(void *ptr, size_t size);
+API_EXPORT(void) ap_MM_free(void *ptr);
+API_EXPORT(void *) ap_MM_calloc(size_t number, size_t size);
+API_EXPORT(char *) ap_MM_strdup(const char *str);
+API_EXPORT(size_t) ap_MM_sizeof(void *ptr);
+API_EXPORT(size_t) ap_MM_maxsize(void);
+API_EXPORT(size_t) ap_MM_available(void);
+API_EXPORT(char *) ap_MM_error(void);
+
+/* Standard Malloc-Style API */
+API_EXPORT(AP_MM *) ap_mm_create(size_t size, char *file);
+API_EXPORT(int) ap_mm_permission(AP_MM *mm, mode_t mode, uid_t owner, gid_t group);
+API_EXPORT(void) ap_mm_destroy(AP_MM *mm);
+API_EXPORT(int) ap_mm_lock(AP_MM *mm, ap_mm_lock_mode mode);
+API_EXPORT(int) ap_mm_unlock(AP_MM *mm);
+API_EXPORT(void *) ap_mm_malloc(AP_MM *mm, size_t size);
+API_EXPORT(void *) ap_mm_realloc(AP_MM *mm, void *ptr, size_t size);
+API_EXPORT(void) ap_mm_free(AP_MM *mm, void *ptr);
+API_EXPORT(void *) ap_mm_calloc(AP_MM *mm, size_t number, size_t size);
+API_EXPORT(char *) ap_mm_strdup(AP_MM *mm, const char *str);
+API_EXPORT(size_t) ap_mm_sizeof(AP_MM *mm, void *ptr);
+API_EXPORT(size_t) ap_mm_maxsize(void);
+API_EXPORT(size_t) ap_mm_available(AP_MM *mm);
+API_EXPORT(char *) ap_mm_error(void);
+API_EXPORT(void) ap_mm_display_info(AP_MM *mm);
+
+/* Low-Level Shared Memory API */
+API_EXPORT(void *) ap_mm_core_create(size_t size, char *file);
+API_EXPORT(int) ap_mm_core_permission(void *core, mode_t mode, uid_t owner, gid_t group);
+API_EXPORT(void) ap_mm_core_delete(void *core);
+API_EXPORT(size_t) ap_mm_core_size(void *core);
+API_EXPORT(int) ap_mm_core_lock(void *core, ap_mm_lock_mode mode);
+API_EXPORT(int) ap_mm_core_unlock(void *core);
+API_EXPORT(size_t) ap_mm_core_maxsegsize(void);
+API_EXPORT(size_t) ap_mm_core_align2page(size_t size);
+API_EXPORT(size_t) ap_mm_core_align2word(size_t size);
+
+/* Internal Library API */
+API_EXPORT(void) ap_mm_lib_error_set(unsigned int, const char *str);
+API_EXPORT(char *) ap_mm_lib_error_get(void);
+API_EXPORT(int) ap_mm_lib_version(void);
+
+#endif /* AP_MM_H */
+
+#endif /* EAPI */
+
diff --git a/usr.sbin/httpd/src/include/ap_mmn.h b/usr.sbin/httpd/src/include/ap_mmn.h
index 4a4316027d1..e34607926f6 100644
--- a/usr.sbin/httpd/src/include/ap_mmn.h
+++ b/usr.sbin/httpd/src/include/ap_mmn.h
@@ -203,6 +203,29 @@
* scan_script_header -> ap_scan_script_header_err
* - reordered entries in request_rec that were waiting
* for a non-binary-compatible release.
+ * (1.3.5-dev)
+ * 19990108.1 - add ap_MD5Encode() for MD5 password handling.
+ * 19990108.2 - add ap_validate_password() and change ap_MD5Encode()
+ * to use a stronger algorithm.
+ * 19990108.4 - add ap_size_list_item(), ap_get_list_item(), and
+ * ap_find_list_item()
+ * 19990108.5 - added ap_sub_req_method_uri() and added const to the
+ * definition of method in request_rec.
+ * 19990108.6 - SIGPIPE is now ignored by the core server.
+ * 19990108.7 - ap_isxdigit added
+ * 19990320 - METHODS and M_INVALID symbol values modified
+ * 19990320.1 - add ap_vrprintf()
+ * 19990320.2 - add cmd_parms.context, ap_set_config_vectors,
+ * export ap_add_file_conf
+ * 19990320.3 - add ap_regexec() and ap_regerror()
+ * 19990320.4 - add ap_field_noparam()
+ * 19990320.5 - add local_ip/host to conn_rec for mass-vhost
+ * 19990320.6 - add ap_SHA1Final(), ap_SHA1Init(),
+ * ap_SHA1Update_binary(), ap_SHA1Update(),
+ * ap_base64encode(), ap_base64encode_binary(),
+ * ap_base64encode_len(), ap_base64decode(),
+ * ap_base64decode_binary(), ap_base64decode_len(),
+ * ap_pbase64decode(), ap_pbase64encode()
*/
/*
@@ -224,9 +247,9 @@
#endif
#ifndef MODULE_MAGIC_NUMBER_MAJOR
-#define MODULE_MAGIC_NUMBER_MAJOR 19990108
+#define MODULE_MAGIC_NUMBER_MAJOR 19990320
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 6 /* 0...n */
#define MODULE_MAGIC_NUMBER MODULE_MAGIC_NUMBER_MAJOR /* backward compat */
/* Useful for testing for features. */
diff --git a/usr.sbin/httpd/src/include/ap_sha1.h b/usr.sbin/httpd/src/include/ap_sha1.h
new file mode 100644
index 00000000000..42a4f5788b2
--- /dev/null
+++ b/usr.sbin/httpd/src/include/ap_sha1.h
@@ -0,0 +1,102 @@
+/* ====================================================================
+ * Copyright (c) 1996-1999 The Apache Group. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ * NIST Secure Hash Algorithm
+ * heavily modified by Uwe Hollerbach uh@alumni.caltech edu
+ * from Peter C. Gutmann's implementation as found in
+ * Applied Cryptography by Bruce Schneier
+ * This code is hereby placed in the public domain
+ */
+
+#ifndef APACHE_SHA1_H
+#define APACHE_SHA1_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SHA_DIGESTSIZE 20
+
+/*
+ * Define the Magic String prefix that identifies a password as being
+ * hashed using our algorithm.
+ */
+#define AP_SHA1PW_ID "{SHA}"
+#define AP_SHA1PW_IDLEN 5
+
+typedef unsigned long AP_LONG; /* a 32-bit quantity */
+
+typedef struct {
+ AP_LONG digest[5]; /* message digest */
+ AP_LONG count_lo, count_hi; /* 64-bit bit count */
+ AP_LONG data[16]; /* SHA data buffer */
+ int local; /* unprocessed amount in data */
+} AP_SHA1_CTX;
+
+API_EXPORT(void) ap_sha1_base64(const char *clear, int len, char *out);
+API_EXPORT(void) ap_SHA1Init(AP_SHA1_CTX *context);
+API_EXPORT(void) ap_SHA1Update(AP_SHA1_CTX *context, const char *input,
+ unsigned int inputLen);
+API_EXPORT(void) ap_SHA1Update_binary(AP_SHA1_CTX *context,
+ const unsigned char *input,
+ unsigned int inputLen);
+API_EXPORT(void) ap_SHA1Final(unsigned char digest[SHA_DIGESTSIZE],
+ AP_SHA1_CTX *context);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APACHE_SHA1_H */
diff --git a/usr.sbin/httpd/src/include/buff.h b/usr.sbin/httpd/src/include/buff.h
index e2e00a5f126..229f2c615d4 100644
--- a/usr.sbin/httpd/src/include/buff.h
+++ b/usr.sbin/httpd/src/include/buff.h
@@ -180,6 +180,10 @@ API_EXPORT(int) ap_vbprintf(BUFF *fb, const char *fmt, va_list vlist);
API_EXPORT(int) ap_bflsbuf(int c, BUFF *fb);
API_EXPORT(int) ap_bfilbuf(BUFF *fb);
+#ifdef EAPI
+#define ap_bpeekc(fb) ( ((fb)->incnt == 0) ? EOF : *((fb)->inptr) )
+#endif
+
#ifndef CHARSET_EBCDIC
#define ap_bgetc(fb) ( ((fb)->incnt == 0) ? ap_bfilbuf(fb) : \
diff --git a/usr.sbin/httpd/src/include/hsregex.h b/usr.sbin/httpd/src/include/hsregex.h
index e5b24e60f77..1d76e5b41d3 100644
--- a/usr.sbin/httpd/src/include/hsregex.h
+++ b/usr.sbin/httpd/src/include/hsregex.h
@@ -16,7 +16,7 @@ extern "C" {
#endif
#endif
-#if defined(RHAPSODY)
+#if defined(MAC_OS) || defined(MAC_OS_X_SERVER)
#define ap_private_extern __private_extern__
#else
#define ap_private_extern
diff --git a/usr.sbin/httpd/src/include/http_conf_globals.h b/usr.sbin/httpd/src/include/http_conf_globals.h
index 53c429421be..7ba0abed370 100644
--- a/usr.sbin/httpd/src/include/http_conf_globals.h
+++ b/usr.sbin/httpd/src/include/http_conf_globals.h
@@ -67,6 +67,8 @@ extern "C" {
*/
extern int ap_standalone;
+extern int ap_configtestonly;
+extern int ap_docrootcheck;
extern uid_t ap_user_id;
extern char *ap_user_name;
extern gid_t ap_group_id;
diff --git a/usr.sbin/httpd/src/include/http_config.h b/usr.sbin/httpd/src/include/http_config.h
index 21b51ddf8bc..271eff1d7eb 100644
--- a/usr.sbin/httpd/src/include/http_config.h
+++ b/usr.sbin/httpd/src/include/http_config.h
@@ -170,6 +170,8 @@ typedef struct {
*/
const command_rec *cmd; /* configuration command */
const char *end_token; /* end token required to end a nested section */
+ void *context; /* per_dir_config vector passed
+ * to handle_command */
} cmd_parms;
/* This structure records the existence of handlers in a module... */
@@ -309,17 +311,27 @@ typedef struct module_struct {
* ap_read_request(). It is mainly intended to be used to setup/run
* connection dependent things like sending start headers for
* on-the-fly compression, etc.
+ *
+ * close_connection:
+ * Called from within the Apache dispatching loop just before any
+ * ap_bclose() is performed on the socket connection, but a long time
+ * before any pool cleanups are done for the connection (which can be
+ * too late for some applications). It is mainly intended to be used
+ * to close/finalize connection dependent things like sending end
+ * headers for on-the-fly compression, etc.
*/
#ifdef ULTRIX_BRAIN_DEATH
void (*add_module) ();
void (*remove_module) ();
char *(*rewrite_command) ();
void (*new_connection) ();
+ void (*close_connection) ();
#else
void (*add_module) (struct module_struct *);
void (*remove_module) (struct module_struct *);
char *(*rewrite_command) (cmd_parms *, void *config, const char *);
void (*new_connection) (conn_rec *);
+ void (*close_connection) (conn_rec *);
#endif
#endif /* EAPI */
} module;
@@ -393,7 +405,6 @@ extern API_VAR_EXPORT module **ap_loaded_modules;
/* For mod_so.c... */
void ap_single_module_configure(pool *p, server_rec *s, module *m);
-void ap_single_module_init(pool *p, server_rec *s, module *m);
/* For http_main.c... */
@@ -450,6 +461,7 @@ int ap_run_post_read_request(request_rec *);
CORE_EXPORT(const command_rec *) ap_find_command(const char *name, const command_rec *cmds);
CORE_EXPORT(const command_rec *) ap_find_command_in_modules(const char *cmd_name, module **mod);
+CORE_EXPORT(void *) ap_set_config_vectors(cmd_parms *parms, void *config, module *mod);
CORE_EXPORT(const char *) ap_handle_command(cmd_parms *parms, void *config, const char *l);
#endif
diff --git a/usr.sbin/httpd/src/include/http_core.h b/usr.sbin/httpd/src/include/http_core.h
index 3eeda2e8fde..459fd248f35 100644
--- a/usr.sbin/httpd/src/include/http_core.h
+++ b/usr.sbin/httpd/src/include/http_core.h
@@ -128,8 +128,8 @@ API_EXPORT(const char *) ap_get_remote_logname(request_rec *r);
/* Used for constructing self-referencing URLs, and things like SERVER_PORT,
* and SERVER_NAME.
*/
-API_EXPORT(char *) ap_construct_url(pool *p, const char *uri, const request_rec *r);
-API_EXPORT(const char *) ap_get_server_name(const request_rec *r);
+API_EXPORT(char *) ap_construct_url(pool *p, const char *uri, request_rec *r);
+API_EXPORT(const char *) ap_get_server_name(request_rec *r);
API_EXPORT(unsigned) ap_get_server_port(const request_rec *r);
API_EXPORT(unsigned long) ap_get_limit_req_body(const request_rec *r);
API_EXPORT(void) ap_custom_response(request_rec *r, int status, char *string);
@@ -152,6 +152,17 @@ API_EXPORT(const char *) ap_auth_name (request_rec *);
API_EXPORT(int) ap_satisfies (request_rec *r);
API_EXPORT(const array_header *) ap_requires (request_rec *);
+#ifdef WIN32
+/*
+ * CGI Script stuff for Win32...
+ */
+typedef enum { eFileTypeUNKNOWN, eFileTypeBIN, eFileTypeEXE16, eFileTypeEXE32,
+ eFileTypeSCRIPT } file_type_e;
+typedef enum { INTERPRETER_SOURCE_UNSET, INTERPRETER_SOURCE_REGISTRY,
+ INTERPRETER_SOURCE_SHEBANG } interpreter_source_e;
+API_EXPORT(file_type_e) ap_get_win32_interpreter(const request_rec *, char **);
+#endif
+
#ifdef CORE_PRIVATE
/*
@@ -220,7 +231,11 @@ typedef struct {
signed int content_md5 : 2; /* calculate Content-MD5? */
- unsigned use_canonical_name : 2; /* bit 0 = on/off, bit 1 = unset/set */
+#define USE_CANONICAL_NAME_OFF (0)
+#define USE_CANONICAL_NAME_ON (1)
+#define USE_CANONICAL_NAME_DNS (2)
+#define USE_CANONICAL_NAME_UNSET (3)
+ unsigned use_canonical_name : 2;
/* since is_fnmatch(conf->d) was being called so frequently in
* directory_walk() and its relatives, this field was created and
@@ -241,13 +256,19 @@ typedef struct {
unsigned long limit_req_body; /* limit on bytes in request msg body */
/* logging options */
- enum { srv_sig_off, srv_sig_on, srv_sig_withmail } server_signature;
+ enum { srv_sig_unset, srv_sig_off, srv_sig_on,
+ srv_sig_withmail } server_signature;
int loglevel;
/* Access control */
array_header *sec;
regex_t *r;
+#ifdef WIN32
+ /* Where to find interpreter to run scripts */
+ interpreter_source_e script_interpreter_source;
+#endif
+
} core_dir_config;
/* Per-server core configuration */
@@ -277,6 +298,7 @@ void ap_core_reorder_directories(pool *, server_rec *);
/* for mod_perl */
CORE_EXPORT(void) ap_add_per_dir_conf (server_rec *s, void *dir_config);
CORE_EXPORT(void) ap_add_per_url_conf (server_rec *s, void *url_config);
+CORE_EXPORT(void) ap_add_file_conf(core_dir_config *conf, void *url_config);
CORE_EXPORT_NONSTD(const char *) ap_limit_section (cmd_parms *cmd, void *dummy, const char *arg);
#endif
diff --git a/usr.sbin/httpd/src/include/http_protocol.h b/usr.sbin/httpd/src/include/http_protocol.h
index bd57fd813c6..3824c1aba06 100644
--- a/usr.sbin/httpd/src/include/http_protocol.h
+++ b/usr.sbin/httpd/src/include/http_protocol.h
@@ -148,6 +148,7 @@ API_EXPORT(int) ap_rputc(int c, request_rec *r);
API_EXPORT(int) ap_rputs(const char *str, request_rec *r);
API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r);
API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r,...);
+API_EXPORT(int) ap_vrprintf(request_rec *r, const char *fmt, va_list vlist);
API_EXPORT_NONSTD(int) ap_rprintf(request_rec *r, const char *fmt,...)
__attribute__((format(printf,2,3)));
API_EXPORT(int) ap_rflush(request_rec *r);
diff --git a/usr.sbin/httpd/src/include/http_request.h b/usr.sbin/httpd/src/include/http_request.h
index bc3e938a983..4d83c543d6a 100644
--- a/usr.sbin/httpd/src/include/http_request.h
+++ b/usr.sbin/httpd/src/include/http_request.h
@@ -86,6 +86,9 @@ API_EXPORT(request_rec *) ap_sub_req_lookup_uri(const char *new_file,
const request_rec *r);
API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file,
const request_rec *r);
+API_EXPORT(request_rec *) ap_sub_req_method_uri(const char *method,
+ const char *new_file,
+ const request_rec *r);
API_EXPORT(int) ap_run_sub_req(request_rec *r);
API_EXPORT(void) ap_destroy_sub_req(request_rec *r);
diff --git a/usr.sbin/httpd/src/include/httpd.h b/usr.sbin/httpd/src/include/httpd.h
index 581836ec522..fdf93d3c8a2 100644
--- a/usr.sbin/httpd/src/include/httpd.h
+++ b/usr.sbin/httpd/src/include/httpd.h
@@ -69,6 +69,9 @@ extern "C" {
/* Headers in which EVERYONE has an interest... */
#include "ap_config.h"
+#ifdef EAPI
+#include "ap_mm.h"
+#endif
#include "alloc.h"
/*
* Include the Extended API headers.
@@ -94,8 +97,10 @@ extern "C" {
#elif defined(WIN32)
/* Set default for Windows file system */
#define HTTPD_ROOT "/apache"
+#elif defined(BEOS)
+#define HTTPD_ROOT "/boot/home/apache"
#else
-#define HTTPD_ROOT "/var/www"
+#define HTTPD_ROOT "/usr/local/apache"
#endif
#endif /* HTTPD_ROOT */
@@ -165,8 +170,7 @@ extern "C" {
/* The name of the log files */
#ifndef DEFAULT_XFERLOG
-#ifdef OS2
-/* Set default for OS/2 file system */
+#if defined(OS2) || defined(WIN32)
#define DEFAULT_XFERLOG "logs/access.log"
#else
#define DEFAULT_XFERLOG "logs/access_log"
@@ -174,8 +178,7 @@ extern "C" {
#endif /* DEFAULT_XFERLOG */
#ifndef DEFAULT_ERRORLOG
-#ifdef OS2
-/* Set default for OS/2 file system */
+#if defined(OS2) || defined(WIN32)
#define DEFAULT_ERRORLOG "logs/error.log"
#else
#define DEFAULT_ERRORLOG "logs/error_log"
@@ -322,8 +325,12 @@ extern "C" {
* the overhead.
*/
#ifndef HARD_SERVER_LIMIT
+#ifdef WIN32
+#define HARD_SERVER_LIMIT 1024
+#else
#define HARD_SERVER_LIMIT 256
#endif
+#endif
/*
* Special Apache error codes. These are basically used
@@ -361,6 +368,19 @@ extern "C" {
#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
#endif
+/*
+ * Unix only:
+ * Path to Shared Memory Files
+ */
+#ifdef EAPI
+#ifndef EAPI_MM_CORE_PATH
+#define EAPI_MM_CORE_PATH "logs/mm"
+#endif
+#ifndef EAPI_MM_CORE_MAXSIZE
+#define EAPI_MM_CORE_MAXSIZE 1024*1024*1 /* max. 1MB */
+#endif
+#endif
+
/* Number of requests to try to handle in a single process. If <= 0,
* the children don't die off. That's the default here, since I'm still
* interested in finding and stanching leaks.
@@ -429,7 +449,7 @@ extern "C" {
* Example: "Apache/1.1.0 MrWidget/0.1-alpha"
*/
-#define SERVER_BASEVERSION "Apache/1.3.4" /* SEE COMMENTS ABOVE */
+#define SERVER_BASEVERSION "Apache/1.3.9" /* SEE COMMENTS ABOVE */
#define SERVER_VERSION SERVER_BASEVERSION
enum server_token_type {
SrvTk_MIN, /* eg: Apache/1.3.0 */
@@ -448,7 +468,7 @@ API_EXPORT(void) ap_add_config_define(const char *define);
* Always increases along the same track as the source branch.
* For example, Apache 1.4.2 would be '10402100', 2.5b7 would be '20500007'.
*/
-#define APACHE_RELEASE 10304100
+#define APACHE_RELEASE 10309100
#define SERVER_PROTOCOL "HTTP/1.1"
#ifndef SERVER_SUPPORT
@@ -574,9 +594,9 @@ API_EXPORT(void) ap_add_config_define(const char *define);
#define M_MOVE 12
#define M_LOCK 13
#define M_UNLOCK 14
+#define M_INVALID 15
-#define METHODS 15
-#define M_INVALID 31
+#define METHODS 16
#define CGI_MAGIC_TYPE "application/x-httpd-cgi"
#define INCLUDES_MAGIC_TYPE "text/x-server-parsed-html"
@@ -589,6 +609,23 @@ API_EXPORT(void) ap_add_config_define(const char *define);
#define DIR_MAGIC_TYPE "httpd/unix-directory"
#define STATUS_MAGIC_TYPE "application/x-httpd-status"
+/*
+ * Define the HTML doctype strings centrally.
+ */
+#define DOCTYPE_HTML_2_0 "<!DOCTYPE HTML PUBLIC \"-//IETF//" \
+ "DTD HTML 2.0//EN\">\n"
+#define DOCTYPE_HTML_3_2 "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
+ "DTD HTML 3.2 Final//EN\">\n"
+#define DOCTYPE_HTML_4_0S "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
+ "DTD HTML 4.0//EN\"\n" \
+ "\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
+#define DOCTYPE_HTML_4_0T "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
+ "DTD HTML 4.0 Transitional//EN\"\n" \
+ "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n"
+#define DOCTYPE_HTML_4_0F "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
+ "DTD HTML 4.0 Frameset//EN\"\n" \
+ "\"http://www.w3.org/TR/REC-html40/frameset.dtd\">\n"
+
/* Just in case your linefeed isn't the one the other end is expecting. */
#ifndef CHARSET_EBCDIC
#define LF 10
@@ -680,14 +717,14 @@ struct request_rec {
time_t request_time; /* When the request started */
- char *status_line; /* Status line, if set by script */
+ const char *status_line; /* Status line, if set by script */
int status; /* In any case */
/* Request method, two ways; also, protocol, etc.. Outside of protocol.c,
* look, but don't touch.
*/
- char *method; /* GET, HEAD, POST, etc. */
+ const char *method; /* GET, HEAD, POST, etc. */
int method_number; /* M_GET, M_POST, etc. */
/*
@@ -845,7 +882,10 @@ struct conn_rec {
signed int double_reverse:2;/* have we done double-reverse DNS?
* -1 yes/failure, 0 not yet, 1 yes/success */
int keepalives; /* How many times have we used it? */
-
+ char *local_ip; /* server IP address */
+ char *local_host; /* used for ap_get_server_name when
+ * UseCanonicalName is set to DNS
+ * (ignores setting of HostnameLookups) */
#ifdef EAPI
ap_ctx *ctx;
#endif /* EAPI */
@@ -947,6 +987,7 @@ extern API_VAR_EXPORT const char ap_day_snames[7][4];
API_EXPORT(struct tm *) ap_get_gmtoff(int *tz);
API_EXPORT(char *) ap_get_time(void);
+API_EXPORT(char *) ap_field_noparam(pool *p, const char *intype);
API_EXPORT(char *) ap_ht_time(pool *p, time_t t, const char *fmt, int gmt);
API_EXPORT(char *) ap_gm_timestr_822(pool *p, time_t t);
@@ -963,6 +1004,10 @@ API_EXPORT(char *) ap_getword_nulls_nc(pool *p, char **line, char stop);
API_EXPORT(char *) ap_getword_conf(pool *p, const char **line);
API_EXPORT(char *) ap_getword_conf_nc(pool *p, char **line);
+API_EXPORT(const char *) ap_size_list_item(const char **field, int *len);
+API_EXPORT(char *) ap_get_list_item(pool *p, const char **field);
+API_EXPORT(int) ap_find_list_item(pool *p, const char *line, const char *tok);
+
API_EXPORT(char *) ap_get_token(pool *p, const char **accept_line, int accept_white);
API_EXPORT(int) ap_find_token(pool *p, const char *line, const char *tok);
API_EXPORT(int) ap_find_last_token(pool *p, const char *line, const char *tok);
@@ -989,14 +1034,22 @@ API_EXPORT(char *) ap_make_full_path(pool *a, const char *dir, const char *f);
API_EXPORT(int) ap_is_matchexp(const char *str);
API_EXPORT(int) ap_strcmp_match(const char *str, const char *exp);
API_EXPORT(int) ap_strcasecmp_match(const char *str, const char *exp);
-API_EXPORT(char *) ap_uudecode(pool *, const char *);
+API_EXPORT(char *) ap_pbase64decode(pool *p, const char *bufcoded);
+API_EXPORT(char *) ap_pbase64encode(pool *p, char *string);
+API_EXPORT(char *) ap_uudecode(pool *p, const char *bufcoded);
API_EXPORT(char *) ap_uuencode(pool *p, char *string);
+
#ifdef OS2
void os2pathname(char *path);
+char *ap_double_quotes(pool *p, char *str);
#endif
+API_EXPORT(int) ap_regexec(const regex_t *preg, const char *string,
+ size_t nmatch, regmatch_t pmatch[], int eflags);
+API_EXPORT(size_t) ap_regerror(int errcode, const regex_t *preg,
+ char *errbuf, size_t errbuf_size);
API_EXPORT(char *) ap_pregsub(pool *p, const char *input, const char *source,
- size_t nmatch, regmatch_t pmatch[]);
+ size_t nmatch, regmatch_t pmatch[]);
API_EXPORT(void) ap_content_type_tolower(char *);
API_EXPORT(void) ap_str_tolower(char *);
diff --git a/usr.sbin/httpd/src/include/scoreboard.h b/usr.sbin/httpd/src/include/scoreboard.h
index 177b3bde4b8..a8f88e3f394 100644
--- a/usr.sbin/httpd/src/include/scoreboard.h
+++ b/usr.sbin/httpd/src/include/scoreboard.h
@@ -183,6 +183,10 @@ typedef struct {
} scoreboard;
#define SCOREBOARD_SIZE sizeof(scoreboard)
+#ifdef TPF
+#define SCOREBOARD_NAME "SCOREBRD"
+#define SCOREBOARD_FRAMES SCOREBOARD_SIZE/4095 + 1
+#endif
API_EXPORT(void) ap_sync_scoreboard_image(void);
API_EXPORT(int) ap_exists_scoreboard_image(void);
diff --git a/usr.sbin/httpd/src/include/util_md5.h b/usr.sbin/httpd/src/include/util_md5.h
index 3fc35dc7e0f..0a0dc9c9b3c 100644
--- a/usr.sbin/httpd/src/include/util_md5.h
+++ b/usr.sbin/httpd/src/include/util_md5.h
@@ -67,7 +67,11 @@ extern "C" {
API_EXPORT(char *) ap_md5(pool *a, const unsigned char *string);
API_EXPORT(char *) ap_md5_binary(pool *a, const unsigned char *buf, int len);
API_EXPORT(char *) ap_md5contextTo64(pool *p, AP_MD5_CTX * context);
+#ifdef CHARSET_EBCDIC
+API_EXPORT(char *) ap_md5digest(pool *p, FILE *infile, int convert);
+#else
API_EXPORT(char *) ap_md5digest(pool *p, FILE *infile);
+#endif /* CHARSET_EBCDIC */
#ifdef __cplusplus
}
diff --git a/usr.sbin/httpd/src/lib/expat-lite/CHANGES b/usr.sbin/httpd/src/lib/expat-lite/CHANGES
new file mode 100644
index 00000000000..e424068ed91
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/CHANGES
@@ -0,0 +1,41 @@
+=== PURPOSE ===
+
+This file documents the changes made by the Apache Group to James
+Clark's Expat parser. The original Expat distribution can be found at
+http://www.jclark.com/xml/expat.html.
+
+
+=== SUBSET INFORMATION ===
+
+Apache does not choose (or need) to use the entire Expat parser
+distribution. The subset that Apache will use will be referred to as
+"expat-lite". In particular, this directory contains the files from
+the following Expat distribution subdirectories:
+
+ expat/xmltok/*
+ expat/xmlparse/*
+
+We also retain expat/expat.html for attribution to James Clark and
+licensing information.
+
+In addition, we remove expat/xmltok/dllmain.c from our version since
+we statically link expat-lite into the executable (rather than
+building a DLL on the Win32 platform). The *.dsp files are also
+removed, since we place those elsewhere in the Apache source
+distribution and they will have a very different structure.
+
+Makefile.tmpl has been created from scratch to provide build
+instructions to the Apache build system.
+
+This file (CHANGES) has been added to document changes from the
+original Expat distribution.
+
+
+=== CHANGES TO ORIGINAL ===
+
+There have been no changes made to any Expat file at this point in
+time (May 31, 1999).
+
+The files, in their original state from the Expat distribution, have
+been tagged within CVS with the "EXPAT_1_1" tag. That tag may be used
+as a reference for changes made by the Apache Group.
diff --git a/usr.sbin/httpd/src/lib/expat-lite/Makefile.tmpl b/usr.sbin/httpd/src/lib/expat-lite/Makefile.tmpl
new file mode 100644
index 00000000000..646af3b9810
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/Makefile.tmpl
@@ -0,0 +1,26 @@
+#
+# default definition of these two. dunno how to get it prepended when the
+# Makefile is built, so we do it manually
+#
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS) -DAPACHE
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+
+OBJS=xmltok.o xmlrole.o xmlparse.o hashtable.o
+
+all lib: libexpat.a
+
+libexpat.a: $(OBJS)
+ rm -f libexpat.a
+ ar cr libexpat.a $(OBJS)
+ $(RANLIB) libexpat.a
+
+clean:
+ rm -f $(OBJS) libexpat.a
+
+distclean: clean
+ -rm -f Makefile
+
+.SUFFIXES: .o
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
diff --git a/usr.sbin/httpd/src/lib/expat-lite/asciitab.h b/usr.sbin/httpd/src/lib/expat-lite/asciitab.h
new file mode 100644
index 00000000000..8a8a2dd388d
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/asciitab.h
@@ -0,0 +1,62 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
+/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
diff --git a/usr.sbin/httpd/src/lib/expat-lite/expat.html b/usr.sbin/httpd/src/lib/expat-lite/expat.html
new file mode 100644
index 00000000000..3806ca8d0e2
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/expat.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
+"http://www.w3.org/TR/REC-html40/loose.dtd">
+
+<HTML>
+
+<TITLE>expat</TITLE>
+
+<BODY>
+
+<H1>expat - XML Parser Toolkit</H1>
+
+<H3>Version 1.1</H3>
+
+<P>Copyright (c) 1998, 1999 James Clark. Expat is subject to the <A
+HREF="http://www.mozilla.org/NPL/NPL-1_1Final.html">Mozilla Public
+License Version 1.1</A>. Alternatively you may use expat under the <A
+href="http://www.gnu.org/copyleft/gpl.html">GNU General Public
+License</A> instead. Please contact me if you wish to negotiate an
+alternative license.</P>
+
+<P>Expat is an <A
+HREF="http://www.w3.org/TR/1998/REC-xml-19980210">XML 1.0</A> parser
+written in C. It aims to be fully conforming. It is currently not a
+validating XML processor. The current production version of expat can
+be downloaded from <A href = "ftp://ftp.jclark.com/pub/xml/expat.zip"
+>ftp://ftp.jclark.com/pub/xml/expat.zip</A>.</P>
+
+<P>The directory <SAMP>xmltok</SAMP> contains a low-level library for
+tokenizing XML. The interface is documented in
+<SAMP>xmltok/xmltok.h</SAMP>.</P>
+
+<P>The directory <SAMP>xmlparse</SAMP> contains an XML parser library
+which is built on top of the <SAMP>xmltok</SAMP> library. The
+interface is documented in <SAMP>xmlparse/xmlparse.h</SAMP>. The
+directory <SAMP>sample</SAMP> contains a simple example program using
+this interface; <SAMP>sample/build.bat</SAMP> is a batch file to build
+the example using Visual C++.</P>
+
+<P>The directory <SAMP>xmlwf</SAMP> contains the <SAMP>xmlwf</SAMP>
+application, which uses the <SAMP>xmlparse</SAMP> library. The
+arguments to <SAMP>xmlwf</SAMP> are one or more files which are each
+to be checked for well-formedness. An option <SAMP>-d
+<VAR>dir</VAR></SAMP> can be specified; for each well-formed input
+file the corresponding <A
+href="http://www.jclark.com/xml/canonxml.html">canonical XML</A> will
+be written to <SAMP>dir/<VAR>f</VAR></SAMP>, where
+<SAMP><VAR>f</VAR></SAMP> is the filename (without any path) of the
+input file. A <CODE>-x</CODE> option will cause references to
+external general entities to be processed. A <CODE>-s</CODE> option
+will make documents that are not standalone cause an error (a document
+is considered standalone if either it is intrinsically standalone
+because it has no external subset and no references to parameter
+entities in the internal subset or it is declared as standalone in the
+XML declaration).</P>
+
+<P>The <SAMP>bin</SAMP> directory contains Win32 executables. The
+<SAMP>lib</SAMP> directory contains Win32 import libraries.</P>
+
+<P>Answers to some frequently asked questions about expat can be found
+in the <A HREF="http://www.jclark.com/xml/expatfaq.html">expat
+FAQ</A>.</P>
+
+<P></P>
+
+<ADDRESS>
+
+<A HREF="mailto:jjc@jclark.com">James Clark</A>
+
+</ADDRESS>
+
+</BODY>
+
+</HTML>
diff --git a/usr.sbin/httpd/src/lib/expat-lite/hashtable.c b/usr.sbin/httpd/src/lib/expat-lite/hashtable.c
new file mode 100644
index 00000000000..780a0610414
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/hashtable.c
@@ -0,0 +1,151 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in
+csompliance with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#include "xmldef.h"
+
+#ifdef XML_UNICODE_WCHAR_T
+#ifndef XML_UNICODE
+#define XML_UNICODE
+#endif
+#endif
+
+#include "hashtable.h"
+
+#define INIT_SIZE 64
+
+static
+int keyeq(KEY s1, KEY s2)
+{
+ for (; *s1 == *s2; s1++, s2++)
+ if (*s1 == 0)
+ return 1;
+ return 0;
+}
+
+static
+unsigned long hash(KEY s)
+{
+ unsigned long h = 0;
+ while (*s)
+ h = (h << 5) + h + (unsigned char)*s++;
+ return h;
+}
+
+NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize)
+{
+ size_t i;
+ if (table->size == 0) {
+ if (!createSize)
+ return 0;
+ table->v = calloc(INIT_SIZE, sizeof(NAMED *));
+ if (!table->v)
+ return 0;
+ table->size = INIT_SIZE;
+ table->usedLim = INIT_SIZE / 2;
+ i = hash(name) & (table->size - 1);
+ }
+ else {
+ unsigned long h = hash(name);
+ for (i = h & (table->size - 1);
+ table->v[i];
+ i == 0 ? i = table->size - 1 : --i) {
+ if (keyeq(name, table->v[i]->name))
+ return table->v[i];
+ }
+ if (!createSize)
+ return 0;
+ if (table->used == table->usedLim) {
+ /* check for overflow */
+ size_t newSize = table->size * 2;
+ NAMED **newV = calloc(newSize, sizeof(NAMED *));
+ if (!newV)
+ return 0;
+ for (i = 0; i < table->size; i++)
+ if (table->v[i]) {
+ size_t j;
+ for (j = hash(table->v[i]->name) & (newSize - 1);
+ newV[j];
+ j == 0 ? j = newSize - 1 : --j)
+ ;
+ newV[j] = table->v[i];
+ }
+ free(table->v);
+ table->v = newV;
+ table->size = newSize;
+ table->usedLim = newSize/2;
+ for (i = h & (table->size - 1);
+ table->v[i];
+ i == 0 ? i = table->size - 1 : --i)
+ ;
+ }
+ }
+ table->v[i] = calloc(1, createSize);
+ if (!table->v[i])
+ return 0;
+ table->v[i]->name = name;
+ (table->used)++;
+ return table->v[i];
+}
+
+void hashTableDestroy(HASH_TABLE *table)
+{
+ size_t i;
+ for (i = 0; i < table->size; i++) {
+ NAMED *p = table->v[i];
+ if (p)
+ free(p);
+ }
+ free(table->v);
+}
+
+void hashTableInit(HASH_TABLE *p)
+{
+ p->size = 0;
+ p->usedLim = 0;
+ p->used = 0;
+ p->v = 0;
+}
+
+void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
+{
+ iter->p = table->v;
+ iter->end = iter->p + table->size;
+}
+
+NAMED *hashTableIterNext(HASH_TABLE_ITER *iter)
+{
+ while (iter->p != iter->end) {
+ NAMED *tem = *(iter->p)++;
+ if (tem)
+ return tem;
+ }
+ return 0;
+}
+
diff --git a/usr.sbin/httpd/src/lib/expat-lite/hashtable.h b/usr.sbin/httpd/src/lib/expat-lite/hashtable.h
new file mode 100644
index 00000000000..df8ab8a4c83
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/hashtable.h
@@ -0,0 +1,69 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+
+#include <stddef.h>
+
+#ifdef XML_UNICODE
+
+#ifdef XML_UNICODE_WCHAR_T
+typedef const wchar_t *KEY;
+#else /* not XML_UNICODE_WCHAR_T */
+typedef const unsigned short *KEY;
+#endif /* not XML_UNICODE_WCHAR_T */
+
+#else /* not XML_UNICODE */
+
+typedef const char *KEY;
+
+#endif /* not XML_UNICODE */
+
+typedef struct {
+ KEY name;
+} NAMED;
+
+typedef struct {
+ NAMED **v;
+ size_t size;
+ size_t used;
+ size_t usedLim;
+} HASH_TABLE;
+
+NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize);
+void hashTableInit(HASH_TABLE *);
+void hashTableDestroy(HASH_TABLE *);
+
+typedef struct {
+ NAMED **p;
+ NAMED **end;
+} HASH_TABLE_ITER;
+
+void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
+NAMED *hashTableIterNext(HASH_TABLE_ITER *);
diff --git a/usr.sbin/httpd/src/lib/expat-lite/iasciitab.h b/usr.sbin/httpd/src/lib/expat-lite/iasciitab.h
new file mode 100644
index 00000000000..333d6bb779d
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/iasciitab.h
@@ -0,0 +1,63 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */
+/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML,
+/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
diff --git a/usr.sbin/httpd/src/lib/expat-lite/latin1tab.h b/usr.sbin/httpd/src/lib/expat-lite/latin1tab.h
new file mode 100644
index 00000000000..48609aa8f9f
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/latin1tab.h
@@ -0,0 +1,62 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME,
+/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
diff --git a/usr.sbin/httpd/src/lib/expat-lite/nametab.h b/usr.sbin/httpd/src/lib/expat-lite/nametab.h
new file mode 100644
index 00000000000..b05e62c77a6
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/nametab.h
@@ -0,0 +1,150 @@
+static const unsigned namingBitmap[] = {
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE,
+0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF,
+0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF,
+0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
+0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
+0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
+0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
+0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
+0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF,
+0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000,
+0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060,
+0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003,
+0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003,
+0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000,
+0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001,
+0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003,
+0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000,
+0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003,
+0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003,
+0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000,
+0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000,
+0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF,
+0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB,
+0x40000000, 0xF580C900, 0x00000007, 0x02010800,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF,
+0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF,
+0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF,
+0x00000000, 0x00004C40, 0x00000000, 0x00000000,
+0x00000007, 0x00000000, 0x00000000, 0x00000000,
+0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF,
+0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF,
+0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000,
+0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE,
+0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF,
+0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
+0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003,
+0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
+0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
+0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
+0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
+0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF,
+0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF,
+0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF,
+0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF,
+0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF,
+0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0,
+0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1,
+0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3,
+0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80,
+0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3,
+0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3,
+0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000,
+0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000,
+0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF,
+0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x1FFF0000, 0x00000002,
+0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF,
+0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF,
+};
+static const unsigned char nmstrtPages[] = {
+0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00,
+0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
+0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+static const unsigned char namePages[] = {
+0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00,
+0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
+0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
+0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
diff --git a/usr.sbin/httpd/src/lib/expat-lite/utf8tab.h b/usr.sbin/httpd/src/lib/expat-lite/utf8tab.h
new file mode 100644
index 00000000000..a38fe624e88
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/utf8tab.h
@@ -0,0 +1,63 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+
+/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4,
+/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM,
diff --git a/usr.sbin/httpd/src/lib/expat-lite/xmldef.h b/usr.sbin/httpd/src/lib/expat-lite/xmldef.h
new file mode 100644
index 00000000000..20c31844d8b
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/xmldef.h
@@ -0,0 +1,70 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#include <string.h>
+
+#ifdef XML_WINLIB
+
+#define WIN32_LEAN_AND_MEAN
+#define STRICT
+#include <windows.h>
+
+#define malloc(x) HeapAlloc(GetProcessHeap(), 0, (x))
+#define calloc(x, y) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (x)*(y))
+#define free(x) HeapFree(GetProcessHeap(), 0, (x))
+#define realloc(x, y) HeapReAlloc(GetProcessHeap(), 0, x, y)
+#define abort() /* as nothing */
+
+#else /* not XML_WINLIB */
+
+#include <stdlib.h>
+
+#endif /* not XML_WINLIB */
+
+/* This file can be used for any definitions needed in
+particular environments. */
+
+#ifdef MOZILLA
+
+#include "nspr.h"
+#define malloc(x) PR_Malloc(x)
+#define realloc(x, y) PR_Realloc((x), (y))
+#define calloc(x, y) PR_Calloc((x),(y))
+#define free(x) PR_Free(x)
+#define int int32
+
+#endif /* MOZILLA */
+
+#ifdef APACHE
+
+#include "ap_config.h"
+#define XML_BYTE_ORDER AP_BYTE_ORDER
+
+#endif /* APACHE */
diff --git a/usr.sbin/httpd/src/lib/expat-lite/xmlparse.c b/usr.sbin/httpd/src/lib/expat-lite/xmlparse.c
new file mode 100644
index 00000000000..8f9d09c86ee
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/xmlparse.c
@@ -0,0 +1,3256 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#include "xmldef.h"
+#include "xmlparse.h"
+
+#ifdef XML_UNICODE
+#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
+#define XmlConvert XmlUtf16Convert
+#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
+#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
+#define XmlEncode XmlUtf16Encode
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
+typedef unsigned short ICHAR;
+#else
+#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
+#define XmlConvert XmlUtf8Convert
+#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
+#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
+#define XmlEncode XmlUtf8Encode
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
+typedef char ICHAR;
+#endif
+
+
+#ifndef XML_NS
+
+#define XmlInitEncodingNS XmlInitEncoding
+#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
+#undef XmlGetInternalEncodingNS
+#define XmlGetInternalEncodingNS XmlGetInternalEncoding
+#define XmlParseXmlDeclNS XmlParseXmlDecl
+
+#endif
+
+
+#ifdef XML_UNICODE_WCHAR_T
+#define XML_T(x) L ## x
+#else
+#define XML_T(x) x
+#endif
+
+/* Round up n to be a multiple of sz, where sz is a power of 2. */
+#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
+
+#include "xmltok.h"
+#include "xmlrole.h"
+#include "hashtable.h"
+
+#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
+#define INIT_DATA_BUF_SIZE 1024
+#define INIT_ATTS_SIZE 16
+#define INIT_BLOCK_SIZE 1024
+#define INIT_BUFFER_SIZE 1024
+
+#define EXPAND_SPARE 24
+
+typedef struct binding {
+ struct prefix *prefix;
+ struct binding *nextTagBinding;
+ struct binding *prevPrefixBinding;
+ const struct attribute_id *attId;
+ XML_Char *uri;
+ int uriLen;
+ int uriAlloc;
+} BINDING;
+
+typedef struct prefix {
+ const XML_Char *name;
+ BINDING *binding;
+} PREFIX;
+
+typedef struct {
+ const XML_Char *str;
+ const XML_Char *localPart;
+ int uriLen;
+} TAG_NAME;
+
+typedef struct tag {
+ struct tag *parent;
+ const char *rawName;
+ int rawNameLength;
+ TAG_NAME name;
+ char *buf;
+ char *bufEnd;
+ BINDING *bindings;
+} TAG;
+
+typedef struct {
+ const XML_Char *name;
+ const XML_Char *textPtr;
+ int textLen;
+ const XML_Char *systemId;
+ const XML_Char *base;
+ const XML_Char *publicId;
+ const XML_Char *notation;
+ char open;
+} ENTITY;
+
+typedef struct block {
+ struct block *next;
+ int size;
+ XML_Char s[1];
+} BLOCK;
+
+typedef struct {
+ BLOCK *blocks;
+ BLOCK *freeBlocks;
+ const XML_Char *end;
+ XML_Char *ptr;
+ XML_Char *start;
+} STRING_POOL;
+
+/* The XML_Char before the name is used to determine whether
+an attribute has been specified. */
+typedef struct attribute_id {
+ XML_Char *name;
+ PREFIX *prefix;
+ char maybeTokenized;
+ char xmlns;
+} ATTRIBUTE_ID;
+
+typedef struct {
+ const ATTRIBUTE_ID *id;
+ char isCdata;
+ const XML_Char *value;
+} DEFAULT_ATTRIBUTE;
+
+typedef struct {
+ const XML_Char *name;
+ PREFIX *prefix;
+ int nDefaultAtts;
+ int allocDefaultAtts;
+ DEFAULT_ATTRIBUTE *defaultAtts;
+} ELEMENT_TYPE;
+
+typedef struct {
+ HASH_TABLE generalEntities;
+ HASH_TABLE elementTypes;
+ HASH_TABLE attributeIds;
+ HASH_TABLE prefixes;
+ STRING_POOL pool;
+ int complete;
+ int standalone;
+ const XML_Char *base;
+ PREFIX defaultPrefix;
+} DTD;
+
+typedef struct open_internal_entity {
+ const char *internalEventPtr;
+ const char *internalEventEndPtr;
+ struct open_internal_entity *next;
+ ENTITY *entity;
+} OPEN_INTERNAL_ENTITY;
+
+typedef enum XML_Error Processor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr);
+
+static Processor prologProcessor;
+static Processor prologInitProcessor;
+static Processor contentProcessor;
+static Processor cdataSectionProcessor;
+static Processor epilogProcessor;
+#if 0
+static Processor errorProcessor;
+#endif
+static Processor externalEntityInitProcessor;
+static Processor externalEntityInitProcessor2;
+static Processor externalEntityInitProcessor3;
+static Processor externalEntityContentProcessor;
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
+static enum XML_Error
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *);
+static enum XML_Error
+initializeEncoding(XML_Parser parser);
+static enum XML_Error
+doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
+ const char *start, const char *end, const char **endPtr);
+static enum XML_Error
+doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
+static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s,
+ TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
+static
+int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr);
+static int
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, int isCdata, const XML_Char *dfltValue);
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
+ STRING_POOL *);
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
+ STRING_POOL *);
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
+static enum XML_Error
+storeEntityValue(XML_Parser parser, const char *start, const char *end);
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static int
+reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static void
+reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+
+static const XML_Char *getContext(XML_Parser parser);
+static int setContext(XML_Parser parser, const XML_Char *context);
+static void normalizePublicId(XML_Char *s);
+static int dtdInit(DTD *);
+static void dtdDestroy(DTD *);
+static int dtdCopy(DTD *newDtd, const DTD *oldDtd);
+static void poolInit(STRING_POOL *);
+static void poolClear(STRING_POOL *);
+static void poolDestroy(STRING_POOL *);
+static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end);
+static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end);
+static int poolGrow(STRING_POOL *pool);
+static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s);
+static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
+
+#define poolStart(pool) ((pool)->start)
+#define poolEnd(pool) ((pool)->ptr)
+#define poolLength(pool) ((pool)->ptr - (pool)->start)
+#define poolChop(pool) ((void)--(pool->ptr))
+#define poolLastChar(pool) (((pool)->ptr)[-1])
+#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
+#define poolFinish(pool) ((pool)->start = (pool)->ptr)
+#define poolAppendChar(pool, c) \
+ (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
+ ? 0 \
+ : ((*((pool)->ptr)++ = c), 1))
+
+typedef struct {
+ /* The first member must be userData so that the XML_GetUserData macro works. */
+ void *m_userData;
+ void *m_handlerArg;
+ char *m_buffer;
+ /* first character to be parsed */
+ const char *m_bufferPtr;
+ /* past last character to be parsed */
+ char *m_bufferEnd;
+ /* allocated end of buffer */
+ const char *m_bufferLim;
+ long m_parseEndByteIndex;
+ const char *m_parseEndPtr;
+ XML_Char *m_dataBuf;
+ XML_Char *m_dataBufEnd;
+ XML_StartElementHandler m_startElementHandler;
+ XML_EndElementHandler m_endElementHandler;
+ XML_CharacterDataHandler m_characterDataHandler;
+ XML_ProcessingInstructionHandler m_processingInstructionHandler;
+ XML_CommentHandler m_commentHandler;
+ XML_StartCdataSectionHandler m_startCdataSectionHandler;
+ XML_EndCdataSectionHandler m_endCdataSectionHandler;
+ XML_DefaultHandler m_defaultHandler;
+ XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
+ XML_NotationDeclHandler m_notationDeclHandler;
+ XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
+ XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
+ XML_NotStandaloneHandler m_notStandaloneHandler;
+ XML_ExternalEntityRefHandler m_externalEntityRefHandler;
+ void *m_externalEntityRefHandlerArg;
+ XML_UnknownEncodingHandler m_unknownEncodingHandler;
+ const ENCODING *m_encoding;
+ INIT_ENCODING m_initEncoding;
+ const XML_Char *m_protocolEncodingName;
+ int m_ns;
+ void *m_unknownEncodingMem;
+ void *m_unknownEncodingData;
+ void *m_unknownEncodingHandlerData;
+ void (*m_unknownEncodingRelease)(void *);
+ PROLOG_STATE m_prologState;
+ Processor *m_processor;
+ enum XML_Error m_errorCode;
+ const char *m_eventPtr;
+ const char *m_eventEndPtr;
+ const char *m_positionPtr;
+ OPEN_INTERNAL_ENTITY *m_openInternalEntities;
+ int m_defaultExpandInternalEntities;
+ int m_tagLevel;
+ ENTITY *m_declEntity;
+ const XML_Char *m_declNotationName;
+ const XML_Char *m_declNotationPublicId;
+ ELEMENT_TYPE *m_declElementType;
+ ATTRIBUTE_ID *m_declAttributeId;
+ char m_declAttributeIsCdata;
+ DTD m_dtd;
+ TAG *m_tagStack;
+ TAG *m_freeTagList;
+ BINDING *m_inheritedBindings;
+ BINDING *m_freeBindingList;
+ int m_attsSize;
+ int m_nSpecifiedAtts;
+ ATTRIBUTE *m_atts;
+ POSITION m_position;
+ STRING_POOL m_tempPool;
+ STRING_POOL m_temp2Pool;
+ char *m_groupConnector;
+ unsigned m_groupSize;
+ int m_hadExternalDoctype;
+ XML_Char m_namespaceSeparator;
+} Parser;
+
+#define userData (((Parser *)parser)->m_userData)
+#define handlerArg (((Parser *)parser)->m_handlerArg)
+#define startElementHandler (((Parser *)parser)->m_startElementHandler)
+#define endElementHandler (((Parser *)parser)->m_endElementHandler)
+#define characterDataHandler (((Parser *)parser)->m_characterDataHandler)
+#define processingInstructionHandler (((Parser *)parser)->m_processingInstructionHandler)
+#define commentHandler (((Parser *)parser)->m_commentHandler)
+#define startCdataSectionHandler (((Parser *)parser)->m_startCdataSectionHandler)
+#define endCdataSectionHandler (((Parser *)parser)->m_endCdataSectionHandler)
+#define defaultHandler (((Parser *)parser)->m_defaultHandler)
+#define unparsedEntityDeclHandler (((Parser *)parser)->m_unparsedEntityDeclHandler)
+#define notationDeclHandler (((Parser *)parser)->m_notationDeclHandler)
+#define startNamespaceDeclHandler (((Parser *)parser)->m_startNamespaceDeclHandler)
+#define endNamespaceDeclHandler (((Parser *)parser)->m_endNamespaceDeclHandler)
+#define notStandaloneHandler (((Parser *)parser)->m_notStandaloneHandler)
+#define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler)
+#define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg)
+#define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler)
+#define encoding (((Parser *)parser)->m_encoding)
+#define initEncoding (((Parser *)parser)->m_initEncoding)
+#define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem)
+#define unknownEncodingData (((Parser *)parser)->m_unknownEncodingData)
+#define unknownEncodingHandlerData \
+ (((Parser *)parser)->m_unknownEncodingHandlerData)
+#define unknownEncodingRelease (((Parser *)parser)->m_unknownEncodingRelease)
+#define protocolEncodingName (((Parser *)parser)->m_protocolEncodingName)
+#define ns (((Parser *)parser)->m_ns)
+#define prologState (((Parser *)parser)->m_prologState)
+#define processor (((Parser *)parser)->m_processor)
+#define errorCode (((Parser *)parser)->m_errorCode)
+#define eventPtr (((Parser *)parser)->m_eventPtr)
+#define eventEndPtr (((Parser *)parser)->m_eventEndPtr)
+#define positionPtr (((Parser *)parser)->m_positionPtr)
+#define position (((Parser *)parser)->m_position)
+#define openInternalEntities (((Parser *)parser)->m_openInternalEntities)
+#define defaultExpandInternalEntities (((Parser *)parser)->m_defaultExpandInternalEntities)
+#define tagLevel (((Parser *)parser)->m_tagLevel)
+#define buffer (((Parser *)parser)->m_buffer)
+#define bufferPtr (((Parser *)parser)->m_bufferPtr)
+#define bufferEnd (((Parser *)parser)->m_bufferEnd)
+#define parseEndByteIndex (((Parser *)parser)->m_parseEndByteIndex)
+#define parseEndPtr (((Parser *)parser)->m_parseEndPtr)
+#define bufferLim (((Parser *)parser)->m_bufferLim)
+#define dataBuf (((Parser *)parser)->m_dataBuf)
+#define dataBufEnd (((Parser *)parser)->m_dataBufEnd)
+#define dtd (((Parser *)parser)->m_dtd)
+#define declEntity (((Parser *)parser)->m_declEntity)
+#define declNotationName (((Parser *)parser)->m_declNotationName)
+#define declNotationPublicId (((Parser *)parser)->m_declNotationPublicId)
+#define declElementType (((Parser *)parser)->m_declElementType)
+#define declAttributeId (((Parser *)parser)->m_declAttributeId)
+#define declAttributeIsCdata (((Parser *)parser)->m_declAttributeIsCdata)
+#define freeTagList (((Parser *)parser)->m_freeTagList)
+#define freeBindingList (((Parser *)parser)->m_freeBindingList)
+#define inheritedBindings (((Parser *)parser)->m_inheritedBindings)
+#define tagStack (((Parser *)parser)->m_tagStack)
+#define atts (((Parser *)parser)->m_atts)
+#define attsSize (((Parser *)parser)->m_attsSize)
+#define nSpecifiedAtts (((Parser *)parser)->m_nSpecifiedAtts)
+#define tempPool (((Parser *)parser)->m_tempPool)
+#define temp2Pool (((Parser *)parser)->m_temp2Pool)
+#define groupConnector (((Parser *)parser)->m_groupConnector)
+#define groupSize (((Parser *)parser)->m_groupSize)
+#define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype)
+#define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator)
+
+#ifdef _MSC_VER
+#ifdef _DEBUG
+Parser *asParser(XML_Parser parser)
+{
+ return parser;
+}
+#endif
+#endif
+
+XML_Parser XML_ParserCreate(const XML_Char *encodingName)
+{
+ XML_Parser parser = malloc(sizeof(Parser));
+ if (!parser)
+ return parser;
+ processor = prologInitProcessor;
+ XmlPrologStateInit(&prologState);
+ userData = 0;
+ handlerArg = 0;
+ startElementHandler = 0;
+ endElementHandler = 0;
+ characterDataHandler = 0;
+ processingInstructionHandler = 0;
+ commentHandler = 0;
+ startCdataSectionHandler = 0;
+ endCdataSectionHandler = 0;
+ defaultHandler = 0;
+ unparsedEntityDeclHandler = 0;
+ notationDeclHandler = 0;
+ startNamespaceDeclHandler = 0;
+ endNamespaceDeclHandler = 0;
+ notStandaloneHandler = 0;
+ externalEntityRefHandler = 0;
+ externalEntityRefHandlerArg = parser;
+ unknownEncodingHandler = 0;
+ buffer = 0;
+ bufferPtr = 0;
+ bufferEnd = 0;
+ parseEndByteIndex = 0;
+ parseEndPtr = 0;
+ bufferLim = 0;
+ declElementType = 0;
+ declAttributeId = 0;
+ declEntity = 0;
+ declNotationName = 0;
+ declNotationPublicId = 0;
+ memset(&position, 0, sizeof(POSITION));
+ errorCode = XML_ERROR_NONE;
+ eventPtr = 0;
+ eventEndPtr = 0;
+ positionPtr = 0;
+ openInternalEntities = 0;
+ tagLevel = 0;
+ tagStack = 0;
+ freeTagList = 0;
+ freeBindingList = 0;
+ inheritedBindings = 0;
+ attsSize = INIT_ATTS_SIZE;
+ atts = malloc(attsSize * sizeof(ATTRIBUTE));
+ nSpecifiedAtts = 0;
+ dataBuf = malloc(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
+ groupSize = 0;
+ groupConnector = 0;
+ hadExternalDoctype = 0;
+ unknownEncodingMem = 0;
+ unknownEncodingRelease = 0;
+ unknownEncodingData = 0;
+ unknownEncodingHandlerData = 0;
+ namespaceSeparator = '!';
+ ns = 0;
+ poolInit(&tempPool);
+ poolInit(&temp2Pool);
+ protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0;
+ if (!dtdInit(&dtd) || !atts || !dataBuf
+ || (encodingName && !protocolEncodingName)) {
+ XML_ParserFree(parser);
+ return 0;
+ }
+ dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
+ XmlInitEncoding(&initEncoding, &encoding, 0);
+ return parser;
+}
+
+XML_Parser XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
+{
+ static
+ const XML_Char implicitContext[] = {
+ XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='),
+ XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'),
+ XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'),
+ XML_T('.'), XML_T('w'), XML_T('3'),
+ XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'),
+ XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'),
+ XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'),
+ XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'),
+ XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'),
+ XML_T('\0')
+ };
+
+ XML_Parser parser = XML_ParserCreate(encodingName);
+ if (parser) {
+ XmlInitEncodingNS(&initEncoding, &encoding, 0);
+ ns = 1;
+ namespaceSeparator = nsSep;
+ }
+ if (!setContext(parser, implicitContext)) {
+ XML_ParserFree(parser);
+ return 0;
+ }
+ return parser;
+}
+
+int XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
+{
+ if (!encodingName)
+ protocolEncodingName = 0;
+ else {
+ protocolEncodingName = poolCopyString(&tempPool, encodingName);
+ if (!protocolEncodingName)
+ return 0;
+ }
+ return 1;
+}
+
+XML_Parser XML_ExternalEntityParserCreate(XML_Parser oldParser,
+ const XML_Char *context,
+ const XML_Char *encodingName)
+{
+ XML_Parser parser = oldParser;
+ DTD *oldDtd = &dtd;
+ XML_StartElementHandler oldStartElementHandler = startElementHandler;
+ XML_EndElementHandler oldEndElementHandler = endElementHandler;
+ XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
+ XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler;
+ XML_CommentHandler oldCommentHandler = commentHandler;
+ XML_StartCdataSectionHandler oldStartCdataSectionHandler = startCdataSectionHandler;
+ XML_EndCdataSectionHandler oldEndCdataSectionHandler = endCdataSectionHandler;
+ XML_DefaultHandler oldDefaultHandler = defaultHandler;
+ XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler = startNamespaceDeclHandler;
+ XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler = endNamespaceDeclHandler;
+ XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
+ XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler;
+ XML_UnknownEncodingHandler oldUnknownEncodingHandler = unknownEncodingHandler;
+ void *oldUserData = userData;
+ void *oldHandlerArg = handlerArg;
+ int oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
+ void *oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
+
+ parser = (ns
+ ? XML_ParserCreateNS(encodingName, namespaceSeparator)
+ : XML_ParserCreate(encodingName));
+ if (!parser)
+ return 0;
+ startElementHandler = oldStartElementHandler;
+ endElementHandler = oldEndElementHandler;
+ characterDataHandler = oldCharacterDataHandler;
+ processingInstructionHandler = oldProcessingInstructionHandler;
+ commentHandler = oldCommentHandler;
+ startCdataSectionHandler = oldStartCdataSectionHandler;
+ endCdataSectionHandler = oldEndCdataSectionHandler;
+ defaultHandler = oldDefaultHandler;
+ startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
+ endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
+ notStandaloneHandler = oldNotStandaloneHandler;
+ externalEntityRefHandler = oldExternalEntityRefHandler;
+ unknownEncodingHandler = oldUnknownEncodingHandler;
+ userData = oldUserData;
+ if (oldUserData == oldHandlerArg)
+ handlerArg = userData;
+ else
+ handlerArg = parser;
+ if (oldExternalEntityRefHandlerArg != oldParser)
+ externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
+ defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
+ if (!dtdCopy(&dtd, oldDtd) || !setContext(parser, context)) {
+ XML_ParserFree(parser);
+ return 0;
+ }
+ processor = externalEntityInitProcessor;
+ return parser;
+}
+
+static
+void destroyBindings(BINDING *bindings)
+{
+ for (;;) {
+ BINDING *b = bindings;
+ if (!b)
+ break;
+ bindings = b->nextTagBinding;
+ free(b->uri);
+ free(b);
+ }
+}
+
+void XML_ParserFree(XML_Parser parser)
+{
+ for (;;) {
+ TAG *p;
+ if (tagStack == 0) {
+ if (freeTagList == 0)
+ break;
+ tagStack = freeTagList;
+ freeTagList = 0;
+ }
+ p = tagStack;
+ tagStack = tagStack->parent;
+ free(p->buf);
+ destroyBindings(p->bindings);
+ free(p);
+ }
+ destroyBindings(freeBindingList);
+ destroyBindings(inheritedBindings);
+ poolDestroy(&tempPool);
+ poolDestroy(&temp2Pool);
+ dtdDestroy(&dtd);
+ free((void *)atts);
+ free(groupConnector);
+ free(buffer);
+ free(dataBuf);
+ free(unknownEncodingMem);
+ if (unknownEncodingRelease)
+ unknownEncodingRelease(unknownEncodingData);
+ free(parser);
+}
+
+void XML_UseParserAsHandlerArg(XML_Parser parser)
+{
+ handlerArg = parser;
+}
+
+void XML_SetUserData(XML_Parser parser, void *p)
+{
+ if (handlerArg == userData)
+ handlerArg = userData = p;
+ else
+ userData = p;
+}
+
+int XML_SetBase(XML_Parser parser, const XML_Char *p)
+{
+ if (p) {
+ p = poolCopyString(&dtd.pool, p);
+ if (!p)
+ return 0;
+ dtd.base = p;
+ }
+ else
+ dtd.base = 0;
+ return 1;
+}
+
+const XML_Char *XML_GetBase(XML_Parser parser)
+{
+ return dtd.base;
+}
+
+int XML_GetSpecifiedAttributeCount(XML_Parser parser)
+{
+ return nSpecifiedAtts;
+}
+
+void XML_SetElementHandler(XML_Parser parser,
+ XML_StartElementHandler start,
+ XML_EndElementHandler end)
+{
+ startElementHandler = start;
+ endElementHandler = end;
+}
+
+void XML_SetCharacterDataHandler(XML_Parser parser,
+ XML_CharacterDataHandler handler)
+{
+ characterDataHandler = handler;
+}
+
+void XML_SetProcessingInstructionHandler(XML_Parser parser,
+ XML_ProcessingInstructionHandler handler)
+{
+ processingInstructionHandler = handler;
+}
+
+void XML_SetCommentHandler(XML_Parser parser,
+ XML_CommentHandler handler)
+{
+ commentHandler = handler;
+}
+
+void XML_SetCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start,
+ XML_EndCdataSectionHandler end)
+{
+ startCdataSectionHandler = start;
+ endCdataSectionHandler = end;
+}
+
+void XML_SetDefaultHandler(XML_Parser parser,
+ XML_DefaultHandler handler)
+{
+ defaultHandler = handler;
+ defaultExpandInternalEntities = 0;
+}
+
+void XML_SetDefaultHandlerExpand(XML_Parser parser,
+ XML_DefaultHandler handler)
+{
+ defaultHandler = handler;
+ defaultExpandInternalEntities = 1;
+}
+
+void XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+ XML_UnparsedEntityDeclHandler handler)
+{
+ unparsedEntityDeclHandler = handler;
+}
+
+void XML_SetNotationDeclHandler(XML_Parser parser,
+ XML_NotationDeclHandler handler)
+{
+ notationDeclHandler = handler;
+}
+
+void XML_SetNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start,
+ XML_EndNamespaceDeclHandler end)
+{
+ startNamespaceDeclHandler = start;
+ endNamespaceDeclHandler = end;
+}
+
+void XML_SetNotStandaloneHandler(XML_Parser parser,
+ XML_NotStandaloneHandler handler)
+{
+ notStandaloneHandler = handler;
+}
+
+void XML_SetExternalEntityRefHandler(XML_Parser parser,
+ XML_ExternalEntityRefHandler handler)
+{
+ externalEntityRefHandler = handler;
+}
+
+void XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
+{
+ if (arg)
+ externalEntityRefHandlerArg = arg;
+ else
+ externalEntityRefHandlerArg = parser;
+}
+
+void XML_SetUnknownEncodingHandler(XML_Parser parser,
+ XML_UnknownEncodingHandler handler,
+ void *data)
+{
+ unknownEncodingHandler = handler;
+ unknownEncodingHandlerData = data;
+}
+
+int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
+{
+ if (len == 0) {
+ if (!isFinal)
+ return 1;
+ positionPtr = bufferPtr;
+ errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0);
+ if (errorCode == XML_ERROR_NONE)
+ return 1;
+ eventEndPtr = eventPtr;
+ return 0;
+ }
+ else if (bufferPtr == bufferEnd) {
+ const char *end;
+ int nLeftOver;
+ parseEndByteIndex += len;
+ positionPtr = s;
+ if (isFinal) {
+ errorCode = processor(parser, s, parseEndPtr = s + len, 0);
+ if (errorCode == XML_ERROR_NONE)
+ return 1;
+ eventEndPtr = eventPtr;
+ return 0;
+ }
+ errorCode = processor(parser, s, parseEndPtr = s + len, &end);
+ if (errorCode != XML_ERROR_NONE) {
+ eventEndPtr = eventPtr;
+ return 0;
+ }
+ XmlUpdatePosition(encoding, positionPtr, end, &position);
+ nLeftOver = s + len - end;
+ if (nLeftOver) {
+ if (buffer == 0 || nLeftOver > bufferLim - buffer) {
+ /* FIXME avoid integer overflow */
+ buffer = buffer == 0 ? malloc(len * 2) : realloc(buffer, len * 2);
+ if (!buffer) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ eventPtr = eventEndPtr = 0;
+ return 0;
+ }
+ bufferLim = buffer + len * 2;
+ }
+ memcpy(buffer, end, nLeftOver);
+ bufferPtr = buffer;
+ bufferEnd = buffer + nLeftOver;
+ }
+ return 1;
+ }
+ else {
+ memcpy(XML_GetBuffer(parser, len), s, len);
+ return XML_ParseBuffer(parser, len, isFinal);
+ }
+}
+
+int XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
+{
+ const char *start = bufferPtr;
+ positionPtr = start;
+ bufferEnd += len;
+ parseEndByteIndex += len;
+ errorCode = processor(parser, start, parseEndPtr = bufferEnd,
+ isFinal ? (const char **)0 : &bufferPtr);
+ if (errorCode == XML_ERROR_NONE) {
+ if (!isFinal)
+ XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
+ return 1;
+ }
+ else {
+ eventEndPtr = eventPtr;
+ return 0;
+ }
+}
+
+void *XML_GetBuffer(XML_Parser parser, int len)
+{
+ if (len > bufferLim - bufferEnd) {
+ /* FIXME avoid integer overflow */
+ int neededSize = len + (bufferEnd - bufferPtr);
+ if (neededSize <= bufferLim - buffer) {
+ memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
+ bufferEnd = buffer + (bufferEnd - bufferPtr);
+ bufferPtr = buffer;
+ }
+ else {
+ char *newBuf;
+ int bufferSize = bufferLim - bufferPtr;
+ if (bufferSize == 0)
+ bufferSize = INIT_BUFFER_SIZE;
+ do {
+ bufferSize *= 2;
+ } while (bufferSize < neededSize);
+ newBuf = malloc(bufferSize);
+ if (newBuf == 0) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return 0;
+ }
+ bufferLim = newBuf + bufferSize;
+ if (bufferPtr) {
+ memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
+ free(buffer);
+ }
+ bufferEnd = newBuf + (bufferEnd - bufferPtr);
+ bufferPtr = buffer = newBuf;
+ }
+ }
+ return bufferEnd;
+}
+
+enum XML_Error XML_GetErrorCode(XML_Parser parser)
+{
+ return errorCode;
+}
+
+long XML_GetCurrentByteIndex(XML_Parser parser)
+{
+ if (eventPtr)
+ return parseEndByteIndex - (parseEndPtr - eventPtr);
+ return -1;
+}
+
+int XML_GetCurrentByteCount(XML_Parser parser)
+{
+ if (eventEndPtr && eventPtr)
+ return eventEndPtr - eventPtr;
+ return 0;
+}
+
+int XML_GetCurrentLineNumber(XML_Parser parser)
+{
+ if (eventPtr) {
+ XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
+ positionPtr = eventPtr;
+ }
+ return position.lineNumber + 1;
+}
+
+int XML_GetCurrentColumnNumber(XML_Parser parser)
+{
+ if (eventPtr) {
+ XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
+ positionPtr = eventPtr;
+ }
+ return position.columnNumber;
+}
+
+void XML_DefaultCurrent(XML_Parser parser)
+{
+ if (defaultHandler) {
+ if (openInternalEntities)
+ reportDefault(parser,
+ ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding(),
+ openInternalEntities->internalEventPtr,
+ openInternalEntities->internalEventEndPtr);
+ else
+ reportDefault(parser, encoding, eventPtr, eventEndPtr);
+ }
+}
+
+const XML_LChar *XML_ErrorString(int code)
+{
+ static const XML_LChar *message[] = {
+ 0,
+ XML_T("out of memory"),
+ XML_T("syntax error"),
+ XML_T("no element found"),
+ XML_T("not well-formed"),
+ XML_T("unclosed token"),
+ XML_T("unclosed token"),
+ XML_T("mismatched tag"),
+ XML_T("duplicate attribute"),
+ XML_T("junk after document element"),
+ XML_T("illegal parameter entity reference"),
+ XML_T("undefined entity"),
+ XML_T("recursive entity reference"),
+ XML_T("asynchronous entity"),
+ XML_T("reference to invalid character number"),
+ XML_T("reference to binary entity"),
+ XML_T("reference to external entity in attribute"),
+ XML_T("xml processing instruction not at start of external entity"),
+ XML_T("unknown encoding"),
+ XML_T("encoding specified in XML declaration is incorrect"),
+ XML_T("unclosed CDATA section"),
+ XML_T("error in processing external entity reference"),
+ XML_T("document is not standalone")
+ };
+ if (code > 0 && code < sizeof(message)/sizeof(message[0]))
+ return message[code];
+ return 0;
+}
+
+static
+enum XML_Error contentProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ return doContent(parser, 0, encoding, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = initializeEncoding(parser);
+ if (result != XML_ERROR_NONE)
+ return result;
+ processor = externalEntityInitProcessor2;
+ return externalEntityInitProcessor2(parser, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor2(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ const char *next;
+ int tok = XmlContentTok(encoding, start, end, &next);
+ switch (tok) {
+ case XML_TOK_BOM:
+ start = next;
+ break;
+ case XML_TOK_PARTIAL:
+ if (endPtr) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (endPtr) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_PARTIAL_CHAR;
+ }
+ processor = externalEntityInitProcessor3;
+ return externalEntityInitProcessor3(parser, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor3(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ const char *next;
+ int tok = XmlContentTok(encoding, start, end, &next);
+ switch (tok) {
+ case XML_TOK_XML_DECL:
+ {
+ enum XML_Error result = processXmlDecl(parser, 1, start, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ start = next;
+ }
+ break;
+ case XML_TOK_PARTIAL:
+ if (endPtr) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (endPtr) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_PARTIAL_CHAR;
+ }
+ processor = externalEntityContentProcessor;
+ tagLevel = 1;
+ return doContent(parser, 1, encoding, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityContentProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ return doContent(parser, 1, encoding, start, end, endPtr);
+}
+
+static enum XML_Error
+doContent(XML_Parser parser,
+ int startTagLevel,
+ const ENCODING *enc,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding();
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ *eventPP = s;
+ for (;;) {
+ const char *next = s; /* XmlContentTok doesn't always set the last arg */
+ int tok = XmlContentTok(enc, s, end, &next);
+ *eventEndPP = next;
+ switch (tok) {
+ case XML_TOK_TRAILING_CR:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ *eventEndPP = end;
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, end);
+ if (startTagLevel == 0)
+ return XML_ERROR_NO_ELEMENTS;
+ if (tagLevel != startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ return XML_ERROR_NONE;
+ case XML_TOK_NONE:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ if (startTagLevel > 0) {
+ if (tagLevel != startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_NO_ELEMENTS;
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_ENTITY_REF:
+ {
+ const XML_Char *name;
+ ENTITY *entity;
+ XML_Char ch = XmlPredefinedEntityName(enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (ch) {
+ if (characterDataHandler)
+ characterDataHandler(handlerArg, &ch, 1);
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ name = poolStoreString(&dtd.pool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
+ poolDiscard(&dtd.pool);
+ if (!entity) {
+ if (dtd.complete || dtd.standalone)
+ return XML_ERROR_UNDEFINED_ENTITY;
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ if (entity->open)
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ if (entity->notation)
+ return XML_ERROR_BINARY_ENTITY_REF;
+ if (entity) {
+ if (entity->textPtr) {
+ enum XML_Error result;
+ OPEN_INTERNAL_ENTITY openEntity;
+ if (defaultHandler && !defaultExpandInternalEntities) {
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ entity->open = 1;
+ openEntity.next = openInternalEntities;
+ openInternalEntities = &openEntity;
+ openEntity.entity = entity;
+ openEntity.internalEventPtr = 0;
+ openEntity.internalEventEndPtr = 0;
+ result = doContent(parser,
+ tagLevel,
+ internalEnc,
+ (char *)entity->textPtr,
+ (char *)(entity->textPtr + entity->textLen),
+ 0);
+ entity->open = 0;
+ openInternalEntities = openEntity.next;
+ if (result)
+ return result;
+ }
+ else if (externalEntityRefHandler) {
+ const XML_Char *context;
+ entity->open = 1;
+ context = getContext(parser);
+ entity->open = 0;
+ if (!context)
+ return XML_ERROR_NO_MEMORY;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ context,
+ dtd.base,
+ entity->systemId,
+ entity->publicId))
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ poolDiscard(&tempPool);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ }
+ case XML_TOK_START_TAG_WITH_ATTS:
+ if (!startElementHandler) {
+ enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
+ if (result)
+ return result;
+ }
+ /* fall through */
+ case XML_TOK_START_TAG_NO_ATTS:
+ {
+ TAG *tag;
+ if (freeTagList) {
+ tag = freeTagList;
+ freeTagList = freeTagList->parent;
+ }
+ else {
+ tag = malloc(sizeof(TAG));
+ if (!tag)
+ return XML_ERROR_NO_MEMORY;
+ tag->buf = malloc(INIT_TAG_BUF_SIZE);
+ if (!tag->buf)
+ return XML_ERROR_NO_MEMORY;
+ tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
+ }
+ tag->bindings = 0;
+ tag->parent = tagStack;
+ tagStack = tag;
+ tag->name.localPart = 0;
+ tag->rawName = s + enc->minBytesPerChar;
+ tag->rawNameLength = XmlNameLength(enc, tag->rawName);
+ if (nextPtr) {
+ /* Need to guarantee that:
+ tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */
+ if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) {
+ int bufSize = tag->rawNameLength * 4;
+ bufSize = ROUND_UP(bufSize, sizeof(XML_Char));
+ tag->buf = realloc(tag->buf, bufSize);
+ if (!tag->buf)
+ return XML_ERROR_NO_MEMORY;
+ tag->bufEnd = tag->buf + bufSize;
+ }
+ memcpy(tag->buf, tag->rawName, tag->rawNameLength);
+ tag->rawName = tag->buf;
+ }
+ ++tagLevel;
+ if (startElementHandler) {
+ enum XML_Error result;
+ XML_Char *toPtr;
+ for (;;) {
+ const char *rawNameEnd = tag->rawName + tag->rawNameLength;
+ const char *fromPtr = tag->rawName;
+ int bufSize;
+ if (nextPtr)
+ toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)));
+ else
+ toPtr = (XML_Char *)tag->buf;
+ tag->name.str = toPtr;
+ XmlConvert(enc,
+ &fromPtr, rawNameEnd,
+ (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
+ if (fromPtr == rawNameEnd)
+ break;
+ bufSize = (tag->bufEnd - tag->buf) << 1;
+ tag->buf = realloc(tag->buf, bufSize);
+ if (!tag->buf)
+ return XML_ERROR_NO_MEMORY;
+ tag->bufEnd = tag->buf + bufSize;
+ if (nextPtr)
+ tag->rawName = tag->buf;
+ }
+ *toPtr = XML_T('\0');
+ result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
+ if (result)
+ return result;
+ startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts);
+ poolClear(&tempPool);
+ }
+ else {
+ tag->name.str = 0;
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ }
+ case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
+ if (!startElementHandler) {
+ enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
+ if (result)
+ return result;
+ }
+ /* fall through */
+ case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
+ if (startElementHandler || endElementHandler) {
+ const char *rawName = s + enc->minBytesPerChar;
+ enum XML_Error result;
+ BINDING *bindings = 0;
+ TAG_NAME name;
+ name.str = poolStoreString(&tempPool, enc, rawName,
+ rawName + XmlNameLength(enc, rawName));
+ if (!name.str)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ result = storeAtts(parser, enc, s, &name, &bindings);
+ if (result)
+ return result;
+ poolFinish(&tempPool);
+ if (startElementHandler)
+ startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
+ if (endElementHandler) {
+ if (startElementHandler)
+ *eventPP = *eventEndPP;
+ endElementHandler(handlerArg, name.str);
+ }
+ poolClear(&tempPool);
+ while (bindings) {
+ BINDING *b = bindings;
+ if (endNamespaceDeclHandler)
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);
+ bindings = bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ if (tagLevel == 0)
+ return epilogProcessor(parser, next, end, nextPtr);
+ break;
+ case XML_TOK_END_TAG:
+ if (tagLevel == startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ else {
+ int len;
+ const char *rawName;
+ TAG *tag = tagStack;
+ tagStack = tag->parent;
+ tag->parent = freeTagList;
+ freeTagList = tag;
+ rawName = s + enc->minBytesPerChar*2;
+ len = XmlNameLength(enc, rawName);
+ if (len != tag->rawNameLength
+ || memcmp(tag->rawName, rawName, len) != 0) {
+ *eventPP = rawName;
+ return XML_ERROR_TAG_MISMATCH;
+ }
+ --tagLevel;
+ if (endElementHandler && tag->name.str) {
+ if (tag->name.localPart) {
+ XML_Char *to = (XML_Char *)tag->name.str + tag->name.uriLen;
+ const XML_Char *from = tag->name.localPart;
+ while ((*to++ = *from++) != 0)
+ ;
+ }
+ endElementHandler(handlerArg, tag->name.str);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ while (tag->bindings) {
+ BINDING *b = tag->bindings;
+ if (endNamespaceDeclHandler)
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);
+ tag->bindings = tag->bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
+ if (tagLevel == 0)
+ return epilogProcessor(parser, next, end, nextPtr);
+ }
+ break;
+ case XML_TOK_CHAR_REF:
+ {
+ int n = XmlCharRefNumber(enc, s);
+ if (n < 0)
+ return XML_ERROR_BAD_CHAR_REF;
+ if (characterDataHandler) {
+ XML_Char buf[XML_ENCODE_MAX];
+ characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ case XML_TOK_XML_DECL:
+ return XML_ERROR_MISPLACED_XML_PI;
+ case XML_TOK_DATA_NEWLINE:
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_CDATA_SECT_OPEN:
+ {
+ enum XML_Error result;
+ if (startCdataSectionHandler)
+ startCdataSectionHandler(handlerArg);
+#if 0
+ /* Suppose you doing a transformation on a document that involves
+ changing only the character data. You set up a defaultHandler
+ and a characterDataHandler. The defaultHandler simply copies
+ characters through. The characterDataHandler does the transformation
+ and writes the characters out escaping them as necessary. This case
+ will fail to work if we leave out the following two lines (because &
+ and < inside CDATA sections will be incorrectly escaped).
+
+ However, now we have a start/endCdataSectionHandler, so it seems
+ easier to let the user deal with this. */
+
+ else if (characterDataHandler)
+ characterDataHandler(handlerArg, dataBuf, 0);
+#endif
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ result = doCdataSection(parser, enc, &next, end, nextPtr);
+ if (!next) {
+ processor = cdataSectionProcessor;
+ return result;
+ }
+ }
+ break;
+ case XML_TOK_TRAILING_RSQB:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ if (characterDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+ characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+ }
+ else
+ characterDataHandler(handlerArg,
+ (XML_Char *)s,
+ (XML_Char *)end - (XML_Char *)s);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, end);
+ if (startTagLevel == 0) {
+ *eventPP = end;
+ return XML_ERROR_NO_ELEMENTS;
+ }
+ if (tagLevel != startTagLevel) {
+ *eventPP = end;
+ return XML_ERROR_ASYNC_ENTITY;
+ }
+ return XML_ERROR_NONE;
+ case XML_TOK_DATA_CHARS:
+ if (characterDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ for (;;) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = s;
+ characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+ if (s == next)
+ break;
+ *eventPP = s;
+ }
+ }
+ else
+ characterDataHandler(handlerArg,
+ (XML_Char *)s,
+ (XML_Char *)next - (XML_Char *)s);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_PI:
+ if (!reportProcessingInstruction(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_COMMENT:
+ if (!reportComment(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ default:
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ *eventPP = s = next;
+ }
+ /* not reached */
+}
+
+/* If tagNamePtr is non-null, build a real list of attributes,
+otherwise just check the attributes for well-formedness. */
+
+static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,
+ const char *s, TAG_NAME *tagNamePtr,
+ BINDING **bindingsPtr)
+{
+ ELEMENT_TYPE *elementType = 0;
+ int nDefaultAtts = 0;
+ const XML_Char **appAtts;
+ int attIndex = 0;
+ int i;
+ int n;
+ int nPrefixes = 0;
+ BINDING *binding;
+ const XML_Char *localPart;
+
+ if (tagNamePtr) {
+ elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, 0);
+ if (!elementType) {
+ tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str);
+ if (!tagNamePtr->str)
+ return XML_ERROR_NO_MEMORY;
+ elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE));
+ if (!elementType)
+ return XML_ERROR_NO_MEMORY;
+ if (ns && !setElementTypePrefix(parser, elementType))
+ return XML_ERROR_NO_MEMORY;
+ }
+ nDefaultAtts = elementType->nDefaultAtts;
+ }
+ n = XmlGetAttributes(enc, s, attsSize, atts);
+ if (n + nDefaultAtts > attsSize) {
+ int oldAttsSize = attsSize;
+ attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
+ atts = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE));
+ if (!atts)
+ return XML_ERROR_NO_MEMORY;
+ if (n > oldAttsSize)
+ XmlGetAttributes(enc, s, n, atts);
+ }
+ appAtts = (const XML_Char **)atts;
+ for (i = 0; i < n; i++) {
+ ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
+ atts[i].name
+ + XmlNameLength(enc, atts[i].name));
+ if (!attId)
+ return XML_ERROR_NO_MEMORY;
+ if ((attId->name)[-1]) {
+ if (enc == encoding)
+ eventPtr = atts[i].name;
+ return XML_ERROR_DUPLICATE_ATTRIBUTE;
+ }
+ (attId->name)[-1] = 1;
+ appAtts[attIndex++] = attId->name;
+ if (!atts[i].normalized) {
+ enum XML_Error result;
+ int isCdata = 1;
+
+ if (attId->maybeTokenized) {
+ int j;
+ for (j = 0; j < nDefaultAtts; j++) {
+ if (attId == elementType->defaultAtts[j].id) {
+ isCdata = elementType->defaultAtts[j].isCdata;
+ break;
+ }
+ }
+ }
+
+ result = storeAttributeValue(parser, enc, isCdata,
+ atts[i].valuePtr, atts[i].valueEnd,
+ &tempPool);
+ if (result)
+ return result;
+ if (tagNamePtr) {
+ appAtts[attIndex] = poolStart(&tempPool);
+ poolFinish(&tempPool);
+ }
+ else
+ poolDiscard(&tempPool);
+ }
+ else if (tagNamePtr) {
+ appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
+ if (appAtts[attIndex] == 0)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ }
+ if (attId->prefix && tagNamePtr) {
+ if (attId->xmlns) {
+ if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr))
+ return XML_ERROR_NO_MEMORY;
+ --attIndex;
+ }
+ else {
+ attIndex++;
+ nPrefixes++;
+ (attId->name)[-1] = 2;
+ }
+ }
+ else
+ attIndex++;
+ }
+ nSpecifiedAtts = attIndex;
+ if (tagNamePtr) {
+ int j;
+ for (j = 0; j < nDefaultAtts; j++) {
+ const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j;
+ if (!(da->id->name)[-1] && da->value) {
+ if (da->id->prefix) {
+ if (da->id->xmlns) {
+ if (!addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr))
+ return XML_ERROR_NO_MEMORY;
+ }
+ else {
+ (da->id->name)[-1] = 2;
+ nPrefixes++;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+ }
+ }
+ else {
+ (da->id->name)[-1] = 1;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+ }
+ }
+ }
+ appAtts[attIndex] = 0;
+ }
+ i = 0;
+ if (nPrefixes) {
+ for (; i < attIndex; i += 2) {
+ if (appAtts[i][-1] == 2) {
+ ATTRIBUTE_ID *id;
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
+ id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0);
+ if (id->prefix->binding) {
+ int j;
+ const BINDING *b = id->prefix->binding;
+ const XML_Char *ss = appAtts[i];
+ for (j = 0; j < b->uriLen; j++) {
+ if (!poolAppendChar(&tempPool, b->uri[j]))
+ return XML_ERROR_NO_MEMORY;
+ }
+ while (*ss++ != ':')
+ ;
+ do {
+ if (!poolAppendChar(&tempPool, *ss))
+ return XML_ERROR_NO_MEMORY;
+ } while (*ss++);
+ appAtts[i] = poolStart(&tempPool);
+ poolFinish(&tempPool);
+ }
+ if (!--nPrefixes)
+ break;
+ }
+ else
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
+ }
+ }
+ for (; i < attIndex; i += 2)
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
+ if (!tagNamePtr)
+ return XML_ERROR_NONE;
+ for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
+ binding->attId->name[-1] = 0;
+ if (elementType->prefix) {
+ binding = elementType->prefix->binding;
+ if (!binding)
+ return XML_ERROR_NONE;
+ localPart = tagNamePtr->str;
+ while (*localPart++ != XML_T(':'))
+ ;
+ }
+ else if (dtd.defaultPrefix.binding) {
+ binding = dtd.defaultPrefix.binding;
+ localPart = tagNamePtr->str;
+ }
+ else
+ return XML_ERROR_NONE;
+ tagNamePtr->localPart = localPart;
+ tagNamePtr->uriLen = binding->uriLen;
+ i = binding->uriLen;
+ do {
+ if (i == binding->uriAlloc) {
+ binding->uri = realloc(binding->uri, binding->uriAlloc *= 2);
+ if (!binding->uri)
+ return XML_ERROR_NO_MEMORY;
+ }
+ binding->uri[i++] = *localPart;
+ } while (*localPart++);
+ tagNamePtr->str = binding->uri;
+ return XML_ERROR_NONE;
+}
+
+static
+int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr)
+{
+ BINDING *b;
+ int len;
+ for (len = 0; uri[len]; len++)
+ ;
+ if (namespaceSeparator)
+ len++;
+ if (freeBindingList) {
+ b = freeBindingList;
+ if (len > b->uriAlloc) {
+ b->uri = realloc(b->uri, len + EXPAND_SPARE);
+ if (!b->uri)
+ return 0;
+ b->uriAlloc = len + EXPAND_SPARE;
+ }
+ freeBindingList = b->nextTagBinding;
+ }
+ else {
+ b = malloc(sizeof(BINDING));
+ if (!b)
+ return 0;
+ b->uri = malloc(sizeof(XML_Char) * len + EXPAND_SPARE);
+ if (!b->uri) {
+ free(b);
+ return 0;
+ }
+ b->uriAlloc = len;
+ }
+ b->uriLen = len;
+ memcpy(b->uri, uri, len * sizeof(XML_Char));
+ if (namespaceSeparator)
+ b->uri[len - 1] = namespaceSeparator;
+ b->prefix = prefix;
+ b->attId = attId;
+ b->prevPrefixBinding = prefix->binding;
+ if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix)
+ prefix->binding = 0;
+ else
+ prefix->binding = b;
+ b->nextTagBinding = *bindingsPtr;
+ *bindingsPtr = b;
+ if (startNamespaceDeclHandler)
+ startNamespaceDeclHandler(handlerArg, prefix->name,
+ prefix->binding ? uri : 0);
+ return 1;
+}
+
+/* The idea here is to avoid using stack for each CDATA section when
+the whole file is parsed with one call. */
+
+static
+enum XML_Error cdataSectionProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = doCdataSection(parser, encoding, &start, end, endPtr);
+ if (start) {
+ processor = contentProcessor;
+ return contentProcessor(parser, start, end, endPtr);
+ }
+ return result;
+}
+
+/* startPtr gets set to non-null is the section is closed, and to null if
+the section is not yet closed. */
+
+static
+enum XML_Error doCdataSection(XML_Parser parser,
+ const ENCODING *enc,
+ const char **startPtr,
+ const char *end,
+ const char **nextPtr)
+{
+ const char *s = *startPtr;
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ *eventPP = s;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ *eventPP = s;
+ *startPtr = 0;
+ for (;;) {
+ const char *next;
+ int tok = XmlCdataSectionTok(enc, s, end, &next);
+ *eventEndPP = next;
+ switch (tok) {
+ case XML_TOK_CDATA_SECT_CLOSE:
+ if (endCdataSectionHandler)
+ endCdataSectionHandler(handlerArg);
+#if 0
+ /* see comment under XML_TOK_CDATA_SECT_OPEN */
+ else if (characterDataHandler)
+ characterDataHandler(handlerArg, dataBuf, 0);
+#endif
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ *startPtr = next;
+ return XML_ERROR_NONE;
+ case XML_TOK_DATA_NEWLINE:
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_DATA_CHARS:
+ if (characterDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ for (;;) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = next;
+ characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+ if (s == next)
+ break;
+ *eventPP = s;
+ }
+ }
+ else
+ characterDataHandler(handlerArg,
+ (XML_Char *)s,
+ (XML_Char *)next - (XML_Char *)s);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_PARTIAL:
+ case XML_TOK_NONE:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_CDATA_SECTION;
+ default:
+ abort();
+ }
+ *eventPP = s = next;
+ }
+ /* not reached */
+}
+
+static enum XML_Error
+initializeEncoding(XML_Parser parser)
+{
+ const char *s;
+#ifdef XML_UNICODE
+ char encodingBuf[128];
+ if (!protocolEncodingName)
+ s = 0;
+ else {
+ int i;
+ for (i = 0; protocolEncodingName[i]; i++) {
+ if (i == sizeof(encodingBuf) - 1
+ || protocolEncodingName[i] >= 0x80
+ || protocolEncodingName[i] < 0) {
+ encodingBuf[0] = '\0';
+ break;
+ }
+ encodingBuf[i] = (char)protocolEncodingName[i];
+ }
+ encodingBuf[i] = '\0';
+ s = encodingBuf;
+ }
+#else
+ s = protocolEncodingName;
+#endif
+ if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
+ return XML_ERROR_NONE;
+ return handleUnknownEncoding(parser, protocolEncodingName);
+}
+
+static enum XML_Error
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
+ const char *s, const char *next)
+{
+ const char *encodingName = 0;
+ const ENCODING *newEncoding = 0;
+ const char *version;
+ int standalone = -1;
+ if (!(ns
+ ? XmlParseXmlDeclNS
+ : XmlParseXmlDecl)(isGeneralTextEntity,
+ encoding,
+ s,
+ next,
+ &eventPtr,
+ &version,
+ &encodingName,
+ &newEncoding,
+ &standalone))
+ return XML_ERROR_SYNTAX;
+ if (!isGeneralTextEntity && standalone == 1)
+ dtd.standalone = 1;
+ if (defaultHandler)
+ reportDefault(parser, encoding, s, next);
+ if (!protocolEncodingName) {
+ if (newEncoding) {
+ if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
+ eventPtr = encodingName;
+ return XML_ERROR_INCORRECT_ENCODING;
+ }
+ encoding = newEncoding;
+ }
+ else if (encodingName) {
+ enum XML_Error result;
+ const XML_Char *ss = poolStoreString(&tempPool,
+ encoding,
+ encodingName,
+ encodingName
+ + XmlNameLength(encoding, encodingName));
+ if (!ss)
+ return XML_ERROR_NO_MEMORY;
+ result = handleUnknownEncoding(parser, ss);
+ poolDiscard(&tempPool);
+ if (result == XML_ERROR_UNKNOWN_ENCODING)
+ eventPtr = encodingName;
+ return result;
+ }
+ }
+ return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
+{
+ if (unknownEncodingHandler) {
+ XML_Encoding info;
+ int i;
+ for (i = 0; i < 256; i++)
+ info.map[i] = -1;
+ info.convert = 0;
+ info.data = 0;
+ info.release = 0;
+ if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) {
+ ENCODING *enc;
+ unknownEncodingMem = malloc(XmlSizeOfUnknownEncoding());
+ if (!unknownEncodingMem) {
+ if (info.release)
+ info.release(info.data);
+ return XML_ERROR_NO_MEMORY;
+ }
+ enc = (ns
+ ? XmlInitUnknownEncodingNS
+ : XmlInitUnknownEncoding)(unknownEncodingMem,
+ info.map,
+ info.convert,
+ info.data);
+ if (enc) {
+ unknownEncodingData = info.data;
+ unknownEncodingRelease = info.release;
+ encoding = enc;
+ return XML_ERROR_NONE;
+ }
+ }
+ if (info.release)
+ info.release(info.data);
+ }
+ return XML_ERROR_UNKNOWN_ENCODING;
+}
+
+static enum XML_Error
+prologInitProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ enum XML_Error result = initializeEncoding(parser);
+ if (result != XML_ERROR_NONE)
+ return result;
+ processor = prologProcessor;
+ return prologProcessor(parser, s, end, nextPtr);
+}
+
+static enum XML_Error
+prologProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ for (;;) {
+ const char *next;
+ int tok = XmlPrologTok(encoding, s, end, &next);
+ if (tok <= 0) {
+ if (nextPtr != 0 && tok != XML_TOK_INVALID) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ switch (tok) {
+ case XML_TOK_INVALID:
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_NONE:
+ return XML_ERROR_NO_ELEMENTS;
+ case XML_TOK_PARTIAL:
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_TRAILING_CR:
+ eventPtr = s + encoding->minBytesPerChar;
+ return XML_ERROR_NO_ELEMENTS;
+ default:
+ abort();
+ }
+ }
+ switch (XmlTokenRole(&prologState, tok, s, next, encoding)) {
+ case XML_ROLE_XML_DECL:
+ {
+ enum XML_Error result = processXmlDecl(parser, 0, s, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ }
+ break;
+ case XML_ROLE_DOCTYPE_SYSTEM_ID:
+ if (!dtd.standalone
+ && notStandaloneHandler
+ && !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+ hadExternalDoctype = 1;
+ break;
+ case XML_ROLE_DOCTYPE_PUBLIC_ID:
+ case XML_ROLE_ENTITY_PUBLIC_ID:
+ if (!XmlIsPublicId(encoding, s, next, &eventPtr))
+ return XML_ERROR_SYNTAX;
+ if (declEntity) {
+ XML_Char *tem = poolStoreString(&dtd.pool,
+ encoding,
+ s + encoding->minBytesPerChar,
+ next - encoding->minBytesPerChar);
+ if (!tem)
+ return XML_ERROR_NO_MEMORY;
+ normalizePublicId(tem);
+ declEntity->publicId = tem;
+ poolFinish(&dtd.pool);
+ }
+ break;
+ case XML_ROLE_INSTANCE_START:
+ processor = contentProcessor;
+ if (hadExternalDoctype)
+ dtd.complete = 0;
+ return contentProcessor(parser, s, end, nextPtr);
+ case XML_ROLE_ATTLIST_ELEMENT_NAME:
+ {
+ const XML_Char *name = poolStoreString(&dtd.pool, encoding, s, next);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ declElementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE));
+ if (!declElementType)
+ return XML_ERROR_NO_MEMORY;
+ if (declElementType->name != name)
+ poolDiscard(&dtd.pool);
+ else {
+ poolFinish(&dtd.pool);
+ if (!setElementTypePrefix(parser, declElementType))
+ return XML_ERROR_NO_MEMORY;
+ }
+ break;
+ }
+ case XML_ROLE_ATTRIBUTE_NAME:
+ declAttributeId = getAttributeId(parser, encoding, s, next);
+ if (!declAttributeId)
+ return XML_ERROR_NO_MEMORY;
+ declAttributeIsCdata = 0;
+ break;
+ case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
+ declAttributeIsCdata = 1;
+ break;
+ case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
+ case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
+ if (dtd.complete
+ && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, 0))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
+ case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
+ {
+ const XML_Char *attVal;
+ enum XML_Error result
+ = storeAttributeValue(parser, encoding, declAttributeIsCdata,
+ s + encoding->minBytesPerChar,
+ next - encoding->minBytesPerChar,
+ &dtd.pool);
+ if (result)
+ return result;
+ attVal = poolStart(&dtd.pool);
+ poolFinish(&dtd.pool);
+ if (dtd.complete
+ && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, attVal))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ }
+ case XML_ROLE_ENTITY_VALUE:
+ {
+ enum XML_Error result = storeEntityValue(parser, s, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ }
+ break;
+ case XML_ROLE_ENTITY_SYSTEM_ID:
+ if (declEntity) {
+ declEntity->systemId = poolStoreString(&dtd.pool, encoding,
+ s + encoding->minBytesPerChar,
+ next - encoding->minBytesPerChar);
+ if (!declEntity->systemId)
+ return XML_ERROR_NO_MEMORY;
+ declEntity->base = dtd.base;
+ poolFinish(&dtd.pool);
+ }
+ break;
+ case XML_ROLE_ENTITY_NOTATION_NAME:
+ if (declEntity) {
+ declEntity->notation = poolStoreString(&dtd.pool, encoding, s, next);
+ if (!declEntity->notation)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&dtd.pool);
+ if (unparsedEntityDeclHandler) {
+ eventPtr = eventEndPtr = s;
+ unparsedEntityDeclHandler(handlerArg,
+ declEntity->name,
+ declEntity->base,
+ declEntity->systemId,
+ declEntity->publicId,
+ declEntity->notation);
+ }
+
+ }
+ break;
+ case XML_ROLE_GENERAL_ENTITY_NAME:
+ {
+ const XML_Char *name;
+ if (XmlPredefinedEntityName(encoding, s, next)) {
+ declEntity = 0;
+ break;
+ }
+ name = poolStoreString(&dtd.pool, encoding, s, next);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ if (dtd.complete) {
+ declEntity = (ENTITY *)lookup(&dtd.generalEntities, name, sizeof(ENTITY));
+ if (!declEntity)
+ return XML_ERROR_NO_MEMORY;
+ if (declEntity->name != name) {
+ poolDiscard(&dtd.pool);
+ declEntity = 0;
+ }
+ else
+ poolFinish(&dtd.pool);
+ }
+ else {
+ poolDiscard(&dtd.pool);
+ declEntity = 0;
+ }
+ }
+ break;
+ case XML_ROLE_PARAM_ENTITY_NAME:
+ declEntity = 0;
+ break;
+ case XML_ROLE_NOTATION_NAME:
+ declNotationPublicId = 0;
+ declNotationName = 0;
+ if (notationDeclHandler) {
+ declNotationName = poolStoreString(&tempPool, encoding, s, next);
+ if (!declNotationName)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ }
+ break;
+ case XML_ROLE_NOTATION_PUBLIC_ID:
+ if (!XmlIsPublicId(encoding, s, next, &eventPtr))
+ return XML_ERROR_SYNTAX;
+ if (declNotationName) {
+ XML_Char *tem = poolStoreString(&tempPool,
+ encoding,
+ s + encoding->minBytesPerChar,
+ next - encoding->minBytesPerChar);
+ if (!tem)
+ return XML_ERROR_NO_MEMORY;
+ normalizePublicId(tem);
+ declNotationPublicId = tem;
+ poolFinish(&tempPool);
+ }
+ break;
+ case XML_ROLE_NOTATION_SYSTEM_ID:
+ if (declNotationName && notationDeclHandler) {
+ const XML_Char *systemId
+ = poolStoreString(&tempPool, encoding,
+ s + encoding->minBytesPerChar,
+ next - encoding->minBytesPerChar);
+ if (!systemId)
+ return XML_ERROR_NO_MEMORY;
+ eventPtr = eventEndPtr = s;
+ notationDeclHandler(handlerArg,
+ declNotationName,
+ dtd.base,
+ systemId,
+ declNotationPublicId);
+ }
+ poolClear(&tempPool);
+ break;
+ case XML_ROLE_NOTATION_NO_SYSTEM_ID:
+ if (declNotationPublicId && notationDeclHandler) {
+ eventPtr = eventEndPtr = s;
+ notationDeclHandler(handlerArg,
+ declNotationName,
+ dtd.base,
+ 0,
+ declNotationPublicId);
+ }
+ poolClear(&tempPool);
+ break;
+ case XML_ROLE_ERROR:
+ eventPtr = s;
+ switch (tok) {
+ case XML_TOK_PARAM_ENTITY_REF:
+ return XML_ERROR_PARAM_ENTITY_REF;
+ case XML_TOK_XML_DECL:
+ return XML_ERROR_MISPLACED_XML_PI;
+ default:
+ return XML_ERROR_SYNTAX;
+ }
+ case XML_ROLE_GROUP_OPEN:
+ if (prologState.level >= groupSize) {
+ if (groupSize)
+ groupConnector = realloc(groupConnector, groupSize *= 2);
+ else
+ groupConnector = malloc(groupSize = 32);
+ if (!groupConnector)
+ return XML_ERROR_NO_MEMORY;
+ }
+ groupConnector[prologState.level] = 0;
+ break;
+ case XML_ROLE_GROUP_SEQUENCE:
+ if (groupConnector[prologState.level] == '|') {
+ eventPtr = s;
+ return XML_ERROR_SYNTAX;
+ }
+ groupConnector[prologState.level] = ',';
+ break;
+ case XML_ROLE_GROUP_CHOICE:
+ if (groupConnector[prologState.level] == ',') {
+ eventPtr = s;
+ return XML_ERROR_SYNTAX;
+ }
+ groupConnector[prologState.level] = '|';
+ break;
+ case XML_ROLE_PARAM_ENTITY_REF:
+ if (!dtd.standalone
+ && notStandaloneHandler
+ && !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+ dtd.complete = 0;
+ break;
+ case XML_ROLE_NONE:
+ switch (tok) {
+ case XML_TOK_PI:
+ eventPtr = s;
+ eventEndPtr = next;
+ if (!reportProcessingInstruction(parser, encoding, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_COMMENT:
+ eventPtr = s;
+ eventEndPtr = next;
+ if (!reportComment(parser, encoding, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ }
+ break;
+ }
+ if (defaultHandler) {
+ switch (tok) {
+ case XML_TOK_PI:
+ case XML_TOK_COMMENT:
+ case XML_TOK_BOM:
+ case XML_TOK_XML_DECL:
+ break;
+ default:
+ eventPtr = s;
+ eventEndPtr = next;
+ reportDefault(parser, encoding, s, next);
+ }
+ }
+ s = next;
+ }
+ /* not reached */
+}
+
+static
+enum XML_Error epilogProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ processor = epilogProcessor;
+ eventPtr = s;
+ for (;;) {
+ const char *next;
+ int tok = XmlPrologTok(encoding, s, end, &next);
+ eventEndPtr = next;
+ switch (tok) {
+ case XML_TOK_TRAILING_CR:
+ if (defaultHandler) {
+ eventEndPtr = end;
+ reportDefault(parser, encoding, s, end);
+ }
+ /* fall through */
+ case XML_TOK_NONE:
+ if (nextPtr)
+ *nextPtr = end;
+ return XML_ERROR_NONE;
+ case XML_TOK_PROLOG_S:
+ if (defaultHandler)
+ reportDefault(parser, encoding, s, next);
+ break;
+ case XML_TOK_PI:
+ if (!reportProcessingInstruction(parser, encoding, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_COMMENT:
+ if (!reportComment(parser, encoding, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_INVALID:
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ default:
+ return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
+ }
+ eventPtr = s = next;
+ }
+}
+
+#if 0
+static
+enum XML_Error errorProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ return errorCode;
+}
+#endif
+
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
+ const char *ptr, const char *end,
+ STRING_POOL *pool)
+{
+ enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
+ if (result)
+ return result;
+ if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
+ poolChop(pool);
+ if (!poolAppendChar(pool, XML_T('\0')))
+ return XML_ERROR_NO_MEMORY;
+ return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
+ const char *ptr, const char *end,
+ STRING_POOL *pool)
+{
+ const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding();
+ for (;;) {
+ const char *next;
+ int tok = XmlAttributeValueTok(enc, ptr, end, &next);
+ switch (tok) {
+ case XML_TOK_NONE:
+ return XML_ERROR_NONE;
+ case XML_TOK_INVALID:
+ if (enc == encoding)
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_CHAR_REF:
+ {
+ XML_Char buf[XML_ENCODE_MAX];
+ int i;
+ int n = XmlCharRefNumber(enc, ptr);
+ if (n < 0) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ if (!isCdata
+ && n == 0x20 /* space */
+ && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+ break;
+ n = XmlEncode(n, (ICHAR *)buf);
+ if (!n) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ for (i = 0; i < n; i++) {
+ if (!poolAppendChar(pool, buf[i]))
+ return XML_ERROR_NO_MEMORY;
+ }
+ }
+ break;
+ case XML_TOK_DATA_CHARS:
+ if (!poolAppend(pool, enc, ptr, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ break;
+ case XML_TOK_TRAILING_CR:
+ next = ptr + enc->minBytesPerChar;
+ /* fall through */
+ case XML_TOK_ATTRIBUTE_VALUE_S:
+ case XML_TOK_DATA_NEWLINE:
+ if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+ break;
+ if (!poolAppendChar(pool, 0x20))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_ENTITY_REF:
+ {
+ const XML_Char *name;
+ ENTITY *entity;
+ XML_Char ch = XmlPredefinedEntityName(enc,
+ ptr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (ch) {
+ if (!poolAppendChar(pool, ch))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ }
+ name = poolStoreString(&temp2Pool, enc,
+ ptr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
+ poolDiscard(&temp2Pool);
+ if (!entity) {
+ if (dtd.complete) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_UNDEFINED_ENTITY;
+ }
+ }
+ else if (entity->open) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ }
+ else if (entity->notation) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BINARY_ENTITY_REF;
+ }
+ else if (!entity->textPtr) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
+ }
+ else {
+ enum XML_Error result;
+ const XML_Char *textEnd = entity->textPtr + entity->textLen;
+ entity->open = 1;
+ result = appendAttributeValue(parser, internalEnc, isCdata, (char *)entity->textPtr, (char *)textEnd, pool);
+ entity->open = 0;
+ if (result)
+ return result;
+ }
+ }
+ break;
+ default:
+ abort();
+ }
+ ptr = next;
+ }
+ /* not reached */
+}
+
+static
+enum XML_Error storeEntityValue(XML_Parser parser,
+ const char *entityTextPtr,
+ const char *entityTextEnd)
+{
+#if 0
+ const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding();
+#endif
+ STRING_POOL *pool = &(dtd.pool);
+ entityTextPtr += encoding->minBytesPerChar;
+ entityTextEnd -= encoding->minBytesPerChar;
+ for (;;) {
+ const char *next;
+ int tok = XmlEntityValueTok(encoding, entityTextPtr, entityTextEnd, &next);
+ switch (tok) {
+ case XML_TOK_PARAM_ENTITY_REF:
+ eventPtr = entityTextPtr;
+ return XML_ERROR_SYNTAX;
+ case XML_TOK_NONE:
+ if (declEntity) {
+ declEntity->textPtr = pool->start;
+ declEntity->textLen = pool->ptr - pool->start;
+ poolFinish(pool);
+ }
+ else
+ poolDiscard(pool);
+ return XML_ERROR_NONE;
+ case XML_TOK_ENTITY_REF:
+ case XML_TOK_DATA_CHARS:
+ if (!poolAppend(pool, encoding, entityTextPtr, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_TRAILING_CR:
+ next = entityTextPtr + encoding->minBytesPerChar;
+ /* fall through */
+ case XML_TOK_DATA_NEWLINE:
+ if (pool->end == pool->ptr && !poolGrow(pool))
+ return XML_ERROR_NO_MEMORY;
+ *(pool->ptr)++ = 0xA;
+ break;
+ case XML_TOK_CHAR_REF:
+ {
+ XML_Char buf[XML_ENCODE_MAX];
+ int i;
+ int n = XmlCharRefNumber(encoding, entityTextPtr);
+ if (n < 0) {
+ eventPtr = entityTextPtr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ n = XmlEncode(n, (ICHAR *)buf);
+ if (!n) {
+ eventPtr = entityTextPtr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ for (i = 0; i < n; i++) {
+ if (pool->end == pool->ptr && !poolGrow(pool))
+ return XML_ERROR_NO_MEMORY;
+ *(pool->ptr)++ = buf[i];
+ }
+ }
+ break;
+ case XML_TOK_PARTIAL:
+ eventPtr = entityTextPtr;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_INVALID:
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ default:
+ abort();
+ }
+ entityTextPtr = next;
+ }
+ /* not reached */
+}
+
+static void
+normalizeLines(XML_Char *s)
+{
+ XML_Char *p;
+ for (;; s++) {
+ if (*s == XML_T('\0'))
+ return;
+ if (*s == 0xD)
+ break;
+ }
+ p = s;
+ do {
+ if (*s == 0xD) {
+ *p++ = 0xA;
+ if (*++s == 0xA)
+ s++;
+ }
+ else
+ *p++ = *s++;
+ } while (*s);
+ *p = XML_T('\0');
+}
+
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+{
+ const XML_Char *target;
+ XML_Char *data;
+ const char *tem;
+ if (!processingInstructionHandler) {
+ if (defaultHandler)
+ reportDefault(parser, enc, start, end);
+ return 1;
+ }
+ start += enc->minBytesPerChar * 2;
+ tem = start + XmlNameLength(enc, start);
+ target = poolStoreString(&tempPool, enc, start, tem);
+ if (!target)
+ return 0;
+ poolFinish(&tempPool);
+ data = poolStoreString(&tempPool, enc,
+ XmlSkipS(enc, tem),
+ end - enc->minBytesPerChar*2);
+ if (!data)
+ return 0;
+ normalizeLines(data);
+ processingInstructionHandler(handlerArg, target, data);
+ poolClear(&tempPool);
+ return 1;
+}
+
+static int
+reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+{
+ XML_Char *data;
+ if (!commentHandler) {
+ if (defaultHandler)
+ reportDefault(parser, enc, start, end);
+ return 1;
+ }
+ data = poolStoreString(&tempPool,
+ enc,
+ start + enc->minBytesPerChar * 4,
+ end - enc->minBytesPerChar * 3);
+ if (!data)
+ return 0;
+ normalizeLines(data);
+ commentHandler(handlerArg, data);
+ poolClear(&tempPool);
+ return 1;
+}
+
+static void
+reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end)
+{
+ if (MUST_CONVERT(enc, s)) {
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ do {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = s;
+ defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+ *eventPP = s;
+ } while (s != end);
+ }
+ else
+ defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s);
+}
+
+
+static int
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, int isCdata, const XML_Char *value)
+{
+ DEFAULT_ATTRIBUTE *att;
+ if (type->nDefaultAtts == type->allocDefaultAtts) {
+ if (type->allocDefaultAtts == 0) {
+ type->allocDefaultAtts = 8;
+ type->defaultAtts = malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
+ }
+ else {
+ type->allocDefaultAtts *= 2;
+ type->defaultAtts = realloc(type->defaultAtts,
+ type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
+ }
+ if (!type->defaultAtts)
+ return 0;
+ }
+ att = type->defaultAtts + type->nDefaultAtts;
+ att->id = attId;
+ att->value = value;
+ att->isCdata = isCdata;
+ if (!isCdata)
+ attId->maybeTokenized = 1;
+ type->nDefaultAtts += 1;
+ return 1;
+}
+
+static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
+{
+ const XML_Char *name;
+ for (name = elementType->name; *name; name++) {
+ if (*name == XML_T(':')) {
+ PREFIX *prefix;
+ const XML_Char *s;
+ for (s = elementType->name; s != name; s++) {
+ if (!poolAppendChar(&dtd.pool, *s))
+ return 0;
+ }
+ if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+ return 0;
+ prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+ if (!prefix)
+ return 0;
+ if (prefix->name == poolStart(&dtd.pool))
+ poolFinish(&dtd.pool);
+ else
+ poolDiscard(&dtd.pool);
+ elementType->prefix = prefix;
+
+ }
+ }
+ return 1;
+}
+
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+{
+ ATTRIBUTE_ID *id;
+ const XML_Char *name;
+ if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+ return 0;
+ name = poolStoreString(&dtd.pool, enc, start, end);
+ if (!name)
+ return 0;
+ ++name;
+ id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID));
+ if (!id)
+ return 0;
+ if (id->name != name)
+ poolDiscard(&dtd.pool);
+ else {
+ poolFinish(&dtd.pool);
+ if (!ns)
+ ;
+ else if (name[0] == 'x'
+ && name[1] == 'm'
+ && name[2] == 'l'
+ && name[3] == 'n'
+ && name[4] == 's'
+ && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
+ if (name[5] == '\0')
+ id->prefix = &dtd.defaultPrefix;
+ else
+ id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX));
+ id->xmlns = 1;
+ }
+ else {
+ int i;
+ for (i = 0; name[i]; i++) {
+ if (name[i] == XML_T(':')) {
+ int j;
+ for (j = 0; j < i; j++) {
+ if (!poolAppendChar(&dtd.pool, name[j]))
+ return 0;
+ }
+ if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+ return 0;
+ id->prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+ if (id->prefix->name == poolStart(&dtd.pool))
+ poolFinish(&dtd.pool);
+ else
+ poolDiscard(&dtd.pool);
+ break;
+ }
+ }
+ }
+ }
+ return id;
+}
+
+#define CONTEXT_SEP XML_T('\f')
+
+static
+const XML_Char *getContext(XML_Parser parser)
+{
+ HASH_TABLE_ITER iter;
+ int needSep = 0;
+
+ if (dtd.defaultPrefix.binding) {
+ int i;
+ int len;
+ if (!poolAppendChar(&tempPool, XML_T('=')))
+ return 0;
+ len = dtd.defaultPrefix.binding->uriLen;
+ if (namespaceSeparator != XML_T('\0'))
+ len--;
+ for (i = 0; i < len; i++)
+ if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i]))
+ return 0;
+ needSep = 1;
+ }
+
+ hashTableIterInit(&iter, &(dtd.prefixes));
+ for (;;) {
+ int i;
+ int len;
+ const XML_Char *s;
+ PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
+ if (!prefix)
+ break;
+ if (!prefix->binding)
+ continue;
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+ return 0;
+ for (s = prefix->name; *s; s++)
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ if (!poolAppendChar(&tempPool, XML_T('=')))
+ return 0;
+ len = prefix->binding->uriLen;
+ if (namespaceSeparator != XML_T('\0'))
+ len--;
+ for (i = 0; i < len; i++)
+ if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
+ return 0;
+ needSep = 1;
+ }
+
+
+ hashTableIterInit(&iter, &(dtd.generalEntities));
+ for (;;) {
+ const XML_Char *s;
+ ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
+ if (!e)
+ break;
+ if (!e->open)
+ continue;
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+ return 0;
+ for (s = e->name; *s; s++)
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ needSep = 1;
+ }
+
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ return tempPool.start;
+}
+
+static
+int setContext(XML_Parser parser, const XML_Char *context)
+{
+ const XML_Char *s = context;
+
+ while (*context != XML_T('\0')) {
+ if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
+ ENTITY *e;
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0);
+ if (e)
+ e->open = 1;
+ if (*s != XML_T('\0'))
+ s++;
+ context = s;
+ poolDiscard(&tempPool);
+ }
+ else if (*s == '=') {
+ PREFIX *prefix;
+ if (poolLength(&tempPool) == 0)
+ prefix = &dtd.defaultPrefix;
+ else {
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX));
+ if (!prefix)
+ return 0;
+ if (prefix->name == poolStart(&tempPool))
+ poolFinish(&tempPool);
+ else
+ poolDiscard(&tempPool);
+ }
+ for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0'); context++)
+ if (!poolAppendChar(&tempPool, *context))
+ return 0;
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ if (!addBinding(parser, prefix, 0, poolStart(&tempPool), &inheritedBindings))
+ return 0;
+ poolDiscard(&tempPool);
+ if (*context != XML_T('\0'))
+ ++context;
+ s = context;
+ }
+ else {
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ s++;
+ }
+ }
+ return 1;
+}
+
+
+static
+void normalizePublicId(XML_Char *publicId)
+{
+ XML_Char *p = publicId;
+ XML_Char *s;
+ for (s = publicId; *s; s++) {
+ switch (*s) {
+ case 0x20:
+ case 0xD:
+ case 0xA:
+ if (p != publicId && p[-1] != 0x20)
+ *p++ = 0x20;
+ break;
+ default:
+ *p++ = *s;
+ }
+ }
+ if (p != publicId && p[-1] == 0x20)
+ --p;
+ *p = XML_T('\0');
+}
+
+static int dtdInit(DTD *p)
+{
+ poolInit(&(p->pool));
+ hashTableInit(&(p->generalEntities));
+ hashTableInit(&(p->elementTypes));
+ hashTableInit(&(p->attributeIds));
+ hashTableInit(&(p->prefixes));
+ p->complete = 1;
+ p->standalone = 0;
+ p->base = 0;
+ p->defaultPrefix.name = 0;
+ p->defaultPrefix.binding = 0;
+ return 1;
+}
+
+static void dtdDestroy(DTD *p)
+{
+ HASH_TABLE_ITER iter;
+ hashTableIterInit(&iter, &(p->elementTypes));
+ for (;;) {
+ ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (!e)
+ break;
+ if (e->allocDefaultAtts != 0)
+ free(e->defaultAtts);
+ }
+ hashTableDestroy(&(p->generalEntities));
+ hashTableDestroy(&(p->elementTypes));
+ hashTableDestroy(&(p->attributeIds));
+ hashTableDestroy(&(p->prefixes));
+ poolDestroy(&(p->pool));
+}
+
+/* Do a deep copy of the DTD. Return 0 for out of memory; non-zero otherwise.
+The new DTD has already been initialized. */
+
+static int dtdCopy(DTD *newDtd, const DTD *oldDtd)
+{
+ HASH_TABLE_ITER iter;
+
+ if (oldDtd->base) {
+ const XML_Char *tem = poolCopyString(&(newDtd->pool), oldDtd->base);
+ if (!tem)
+ return 0;
+ newDtd->base = tem;
+ }
+
+ /* Copy the prefix table. */
+
+ hashTableIterInit(&iter, &(oldDtd->prefixes));
+ for (;;) {
+ const XML_Char *name;
+ const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
+ if (!oldP)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldP->name);
+ if (!name)
+ return 0;
+ if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
+ return 0;
+ }
+
+ hashTableIterInit(&iter, &(oldDtd->attributeIds));
+
+ /* Copy the attribute id table. */
+
+ for (;;) {
+ ATTRIBUTE_ID *newA;
+ const XML_Char *name;
+ const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
+
+ if (!oldA)
+ break;
+ /* Remember to allocate the scratch byte before the name. */
+ if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
+ return 0;
+ name = poolCopyString(&(newDtd->pool), oldA->name);
+ if (!name)
+ return 0;
+ ++name;
+ newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID));
+ if (!newA)
+ return 0;
+ newA->maybeTokenized = oldA->maybeTokenized;
+ if (oldA->prefix) {
+ newA->xmlns = oldA->xmlns;
+ if (oldA->prefix == &oldDtd->defaultPrefix)
+ newA->prefix = &newDtd->defaultPrefix;
+ else
+ newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldA->prefix->name, 0);
+ }
+ }
+
+ /* Copy the element type table. */
+
+ hashTableIterInit(&iter, &(oldDtd->elementTypes));
+
+ for (;;) {
+ int i;
+ ELEMENT_TYPE *newE;
+ const XML_Char *name;
+ const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (!oldE)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldE->name);
+ if (!name)
+ return 0;
+ newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE));
+ if (!newE)
+ return 0;
+ if (oldE->nDefaultAtts) {
+ newE->defaultAtts = (DEFAULT_ATTRIBUTE *)malloc(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
+ if (!newE->defaultAtts)
+ return 0;
+ }
+ newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
+ if (oldE->prefix)
+ newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldE->prefix->name, 0);
+ for (i = 0; i < newE->nDefaultAtts; i++) {
+ newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
+ newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
+ if (oldE->defaultAtts[i].value) {
+ newE->defaultAtts[i].value = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
+ if (!newE->defaultAtts[i].value)
+ return 0;
+ }
+ else
+ newE->defaultAtts[i].value = 0;
+ }
+ }
+
+ /* Copy the entity table. */
+
+ hashTableIterInit(&iter, &(oldDtd->generalEntities));
+
+ for (;;) {
+ ENTITY *newE;
+ const XML_Char *name;
+ const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
+ if (!oldE)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldE->name);
+ if (!name)
+ return 0;
+ newE = (ENTITY *)lookup(&(newDtd->generalEntities), name, sizeof(ENTITY));
+ if (!newE)
+ return 0;
+ if (oldE->systemId) {
+ const XML_Char *tem = poolCopyString(&(newDtd->pool), oldE->systemId);
+ if (!tem)
+ return 0;
+ newE->systemId = tem;
+ if (oldE->base) {
+ if (oldE->base == oldDtd->base)
+ newE->base = newDtd->base;
+ tem = poolCopyString(&(newDtd->pool), oldE->base);
+ if (!tem)
+ return 0;
+ newE->base = tem;
+ }
+ }
+ else {
+ const XML_Char *tem = poolCopyStringN(&(newDtd->pool), oldE->textPtr, oldE->textLen);
+ if (!tem)
+ return 0;
+ newE->textPtr = tem;
+ newE->textLen = oldE->textLen;
+ }
+ if (oldE->notation) {
+ const XML_Char *tem = poolCopyString(&(newDtd->pool), oldE->notation);
+ if (!tem)
+ return 0;
+ newE->notation = tem;
+ }
+ }
+
+ newDtd->complete = oldDtd->complete;
+ newDtd->standalone = oldDtd->standalone;
+ return 1;
+}
+
+static
+void poolInit(STRING_POOL *pool)
+{
+ pool->blocks = 0;
+ pool->freeBlocks = 0;
+ pool->start = 0;
+ pool->ptr = 0;
+ pool->end = 0;
+}
+
+static
+void poolClear(STRING_POOL *pool)
+{
+ if (!pool->freeBlocks)
+ pool->freeBlocks = pool->blocks;
+ else {
+ BLOCK *p = pool->blocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ p->next = pool->freeBlocks;
+ pool->freeBlocks = p;
+ p = tem;
+ }
+ }
+ pool->blocks = 0;
+ pool->start = 0;
+ pool->ptr = 0;
+ pool->end = 0;
+}
+
+static
+void poolDestroy(STRING_POOL *pool)
+{
+ BLOCK *p = pool->blocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ free(p);
+ p = tem;
+ }
+ pool->blocks = 0;
+ p = pool->freeBlocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ free(p);
+ p = tem;
+ }
+ pool->freeBlocks = 0;
+ pool->ptr = 0;
+ pool->start = 0;
+ pool->end = 0;
+}
+
+static
+XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end)
+{
+ if (!pool->ptr && !poolGrow(pool))
+ return 0;
+ for (;;) {
+ XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
+ if (ptr == end)
+ break;
+ if (!poolGrow(pool))
+ return 0;
+ }
+ return pool->start;
+}
+
+static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s)
+{
+ do {
+ if (!poolAppendChar(pool, *s))
+ return 0;
+ } while (*s++);
+ s = pool->start;
+ poolFinish(pool);
+ return s;
+}
+
+static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
+{
+ if (!pool->ptr && !poolGrow(pool))
+ return 0;
+ for (; n > 0; --n, s++) {
+ if (!poolAppendChar(pool, *s))
+ return 0;
+
+ }
+ s = pool->start;
+ poolFinish(pool);
+ return s;
+}
+
+static
+XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end)
+{
+ if (!poolAppend(pool, enc, ptr, end))
+ return 0;
+ if (pool->ptr == pool->end && !poolGrow(pool))
+ return 0;
+ *(pool->ptr)++ = 0;
+ return pool->start;
+}
+
+static
+int poolGrow(STRING_POOL *pool)
+{
+ if (pool->freeBlocks) {
+ if (pool->start == 0) {
+ pool->blocks = pool->freeBlocks;
+ pool->freeBlocks = pool->freeBlocks->next;
+ pool->blocks->next = 0;
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + pool->blocks->size;
+ pool->ptr = pool->start;
+ return 1;
+ }
+ if (pool->end - pool->start < pool->freeBlocks->size) {
+ BLOCK *tem = pool->freeBlocks->next;
+ pool->freeBlocks->next = pool->blocks;
+ pool->blocks = pool->freeBlocks;
+ pool->freeBlocks = tem;
+ memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char));
+ pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + pool->blocks->size;
+ return 1;
+ }
+ }
+ if (pool->blocks && pool->start == pool->blocks->s) {
+ int blockSize = (pool->end - pool->start)*2;
+ pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
+ if (!pool->blocks)
+ return 0;
+ pool->blocks->size = blockSize;
+ pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + blockSize;
+ }
+ else {
+ BLOCK *tem;
+ int blockSize = pool->end - pool->start;
+ if (blockSize < INIT_BLOCK_SIZE)
+ blockSize = INIT_BLOCK_SIZE;
+ else
+ blockSize *= 2;
+ tem = malloc(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
+ if (!tem)
+ return 0;
+ tem->size = blockSize;
+ tem->next = pool->blocks;
+ pool->blocks = tem;
+ memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char));
+ pool->ptr = tem->s + (pool->ptr - pool->start);
+ pool->start = tem->s;
+ pool->end = tem->s + blockSize;
+ }
+ return 1;
+}
diff --git a/usr.sbin/httpd/src/lib/expat-lite/xmlparse.h b/usr.sbin/httpd/src/lib/expat-lite/xmlparse.h
new file mode 100644
index 00000000000..f2f9c9be1c0
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/xmlparse.h
@@ -0,0 +1,482 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#ifndef XmlParse_INCLUDED
+#define XmlParse_INCLUDED 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef XMLPARSEAPI
+#define XMLPARSEAPI /* as nothing */
+#endif
+
+typedef void *XML_Parser;
+
+#ifdef XML_UNICODE_WCHAR_T
+
+/* XML_UNICODE_WCHAR_T will work only if sizeof(wchar_t) == 2 and wchar_t
+uses Unicode. */
+/* Information is UTF-16 encoded as wchar_ts */
+
+#ifndef XML_UNICODE
+#define XML_UNICODE
+#endif
+
+#include <stddef.h>
+typedef wchar_t XML_Char;
+typedef wchar_t XML_LChar;
+
+#else /* not XML_UNICODE_WCHAR_T */
+
+#ifdef XML_UNICODE
+
+/* Information is UTF-16 encoded as unsigned shorts */
+typedef unsigned short XML_Char;
+typedef char XML_LChar;
+
+#else /* not XML_UNICODE */
+
+/* Information is UTF-8 encoded. */
+typedef char XML_Char;
+typedef char XML_LChar;
+
+#endif /* not XML_UNICODE */
+
+#endif /* not XML_UNICODE_WCHAR_T */
+
+
+/* Constructs a new parser; encoding is the encoding specified by the external
+protocol or null if there is none specified. */
+
+XML_Parser XMLPARSEAPI
+XML_ParserCreate(const XML_Char *encoding);
+
+/* Constructs a new parser and namespace processor. Element type names
+and attribute names that belong to a namespace will be expanded;
+unprefixed attribute names are never expanded; unprefixed element type
+names are expanded only if there is a default namespace. The expanded
+name is the concatenation of the namespace URI, the namespace separator character,
+and the local part of the name. If the namespace separator is '\0' then
+the namespace URI and the local part will be concatenated without any
+separator. When a namespace is not declared, the name and prefix will be
+passed through without expansion. */
+
+XML_Parser XMLPARSEAPI
+XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator);
+
+
+/* atts is array of name/value pairs, terminated by 0;
+ names and values are 0 terminated. */
+
+typedef void (*XML_StartElementHandler)(void *userData,
+ const XML_Char *name,
+ const XML_Char **atts);
+
+typedef void (*XML_EndElementHandler)(void *userData,
+ const XML_Char *name);
+
+/* s is not 0 terminated. */
+typedef void (*XML_CharacterDataHandler)(void *userData,
+ const XML_Char *s,
+ int len);
+
+/* target and data are 0 terminated */
+typedef void (*XML_ProcessingInstructionHandler)(void *userData,
+ const XML_Char *target,
+ const XML_Char *data);
+
+/* data is 0 terminated */
+typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data);
+
+typedef void (*XML_StartCdataSectionHandler)(void *userData);
+typedef void (*XML_EndCdataSectionHandler)(void *userData);
+
+/* This is called for any characters in the XML document for
+which there is no applicable handler. This includes both
+characters that are part of markup which is of a kind that is
+not reported (comments, markup declarations), or characters
+that are part of a construct which could be reported but
+for which no handler has been supplied. The characters are passed
+exactly as they were in the XML document except that
+they will be encoded in UTF-8. Line boundaries are not normalized.
+Note that a byte order mark character is not passed to the default handler.
+There are no guarantees about how characters are divided between calls
+to the default handler: for example, a comment might be split between
+multiple calls. */
+
+typedef void (*XML_DefaultHandler)(void *userData,
+ const XML_Char *s,
+ int len);
+
+/* This is called for a declaration of an unparsed (NDATA)
+entity. The base argument is whatever was set by XML_SetBase.
+The entityName, systemId and notationName arguments will never be null.
+The other arguments may be. */
+
+typedef void (*XML_UnparsedEntityDeclHandler)(void *userData,
+ const XML_Char *entityName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+ const XML_Char *notationName);
+
+/* This is called for a declaration of notation.
+The base argument is whatever was set by XML_SetBase.
+The notationName will never be null. The other arguments can be. */
+
+typedef void (*XML_NotationDeclHandler)(void *userData,
+ const XML_Char *notationName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
+
+/* When namespace processing is enabled, these are called once for
+each namespace declaration. The call to the start and end element
+handlers occur between the calls to the start and end namespace
+declaration handlers. For an xmlns attribute, prefix will be null.
+For an xmlns="" attribute, uri will be null. */
+
+typedef void (*XML_StartNamespaceDeclHandler)(void *userData,
+ const XML_Char *prefix,
+ const XML_Char *uri);
+
+typedef void (*XML_EndNamespaceDeclHandler)(void *userData,
+ const XML_Char *prefix);
+
+/* This is called if the document is not standalone (it has an
+external subset or a reference to a parameter entity, but does not
+have standalone="yes"). If this handler returns 0, then processing
+will not continue, and the parser will return a
+XML_ERROR_NOT_STANDALONE error. */
+
+typedef int (*XML_NotStandaloneHandler)(void *userData);
+
+/* This is called for a reference to an external parsed general entity.
+The referenced entity is not automatically parsed.
+The application can parse it immediately or later using
+XML_ExternalEntityParserCreate.
+The parser argument is the parser parsing the entity containing the reference;
+it can be passed as the parser argument to XML_ExternalEntityParserCreate.
+The systemId argument is the system identifier as specified in the entity declaration;
+it will not be null.
+The base argument is the system identifier that should be used as the base for
+resolving systemId if systemId was relative; this is set by XML_SetBase;
+it may be null.
+The publicId argument is the public identifier as specified in the entity declaration,
+or null if none was specified; the whitespace in the public identifier
+will have been normalized as required by the XML spec.
+The context argument specifies the parsing context in the format
+expected by the context argument to
+XML_ExternalEntityParserCreate; context is valid only until the handler
+returns, so if the referenced entity is to be parsed later, it must be copied.
+The handler should return 0 if processing should not continue because of
+a fatal error in the handling of the external entity.
+In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING
+error.
+Note that unlike other handlers the first argument is the parser, not userData. */
+
+typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
+
+/* This structure is filled in by the XML_UnknownEncodingHandler
+to provide information to the parser about encodings that are unknown
+to the parser.
+The map[b] member gives information about byte sequences
+whose first byte is b.
+If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c.
+If map[b] is -1, then the byte sequence is malformed.
+If map[b] is -n, where n >= 2, then b is the first byte of an n-byte
+sequence that encodes a single Unicode scalar value.
+The data member will be passed as the first argument to the convert function.
+The convert function is used to convert multibyte sequences;
+s will point to a n-byte sequence where map[(unsigned char)*s] == -n.
+The convert function must return the Unicode scalar value
+represented by this byte sequence or -1 if the byte sequence is malformed.
+The convert function may be null if the encoding is a single-byte encoding,
+that is if map[b] >= -1 for all bytes b.
+When the parser is finished with the encoding, then if release is not null,
+it will call release passing it the data member;
+once release has been called, the convert function will not be called again.
+
+Expat places certain restrictions on the encodings that are supported
+using this mechanism.
+
+1. Every ASCII character that can appear in a well-formed XML document,
+other than the characters
+
+ $@\^`{}~
+
+must be represented by a single byte, and that byte must be the
+same byte that represents that character in ASCII.
+
+2. No character may require more than 4 bytes to encode.
+
+3. All characters encoded must have Unicode scalar values <= 0xFFFF,
+(ie characters that would be encoded by surrogates in UTF-16
+are not allowed). Note that this restriction doesn't apply to
+the built-in support for UTF-8 and UTF-16.
+
+4. No Unicode character may be encoded by more than one distinct sequence
+of bytes. */
+
+typedef struct {
+ int map[256];
+ void *data;
+ int (*convert)(void *data, const char *s);
+ void (*release)(void *data);
+} XML_Encoding;
+
+/* This is called for an encoding that is unknown to the parser.
+The encodingHandlerData argument is that which was passed as the
+second argument to XML_SetUnknownEncodingHandler.
+The name argument gives the name of the encoding as specified in
+the encoding declaration.
+If the callback can provide information about the encoding,
+it must fill in the XML_Encoding structure, and return 1.
+Otherwise it must return 0.
+If info does not describe a suitable encoding,
+then the parser will return an XML_UNKNOWN_ENCODING error. */
+
+typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData,
+ const XML_Char *name,
+ XML_Encoding *info);
+
+void XMLPARSEAPI
+XML_SetElementHandler(XML_Parser parser,
+ XML_StartElementHandler start,
+ XML_EndElementHandler end);
+
+void XMLPARSEAPI
+XML_SetCharacterDataHandler(XML_Parser parser,
+ XML_CharacterDataHandler handler);
+
+void XMLPARSEAPI
+XML_SetProcessingInstructionHandler(XML_Parser parser,
+ XML_ProcessingInstructionHandler handler);
+void XMLPARSEAPI
+XML_SetCommentHandler(XML_Parser parser,
+ XML_CommentHandler handler);
+
+void XMLPARSEAPI
+XML_SetCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start,
+ XML_EndCdataSectionHandler end);
+
+/* This sets the default handler and also inhibits expansion of internal entities.
+The entity reference will be passed to the default handler. */
+
+void XMLPARSEAPI
+XML_SetDefaultHandler(XML_Parser parser,
+ XML_DefaultHandler handler);
+
+/* This sets the default handler but does not inhibit expansion of internal entities.
+The entity reference will not be passed to the default handler. */
+
+void XMLPARSEAPI
+XML_SetDefaultHandlerExpand(XML_Parser parser,
+ XML_DefaultHandler handler);
+
+void XMLPARSEAPI
+XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+ XML_UnparsedEntityDeclHandler handler);
+
+void XMLPARSEAPI
+XML_SetNotationDeclHandler(XML_Parser parser,
+ XML_NotationDeclHandler handler);
+
+void XMLPARSEAPI
+XML_SetNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start,
+ XML_EndNamespaceDeclHandler end);
+
+void XMLPARSEAPI
+XML_SetNotStandaloneHandler(XML_Parser parser,
+ XML_NotStandaloneHandler handler);
+
+void XMLPARSEAPI
+XML_SetExternalEntityRefHandler(XML_Parser parser,
+ XML_ExternalEntityRefHandler handler);
+
+/* If a non-null value for arg is specified here, then it will be passed
+as the first argument to the external entity ref handler instead
+of the parser object. */
+void XMLPARSEAPI
+XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg);
+
+void XMLPARSEAPI
+XML_SetUnknownEncodingHandler(XML_Parser parser,
+ XML_UnknownEncodingHandler handler,
+ void *encodingHandlerData);
+
+/* This can be called within a handler for a start element, end element,
+processing instruction or character data. It causes the corresponding
+markup to be passed to the default handler. */
+void XMLPARSEAPI XML_DefaultCurrent(XML_Parser parser);
+
+/* This value is passed as the userData argument to callbacks. */
+void XMLPARSEAPI
+XML_SetUserData(XML_Parser parser, void *userData);
+
+/* Returns the last value set by XML_SetUserData or null. */
+#define XML_GetUserData(parser) (*(void **)(parser))
+
+/* This is equivalent to supplying an encoding argument
+to XML_CreateParser. It must not be called after XML_Parse
+or XML_ParseBuffer. */
+
+int XMLPARSEAPI
+XML_SetEncoding(XML_Parser parser, const XML_Char *encoding);
+
+/* If this function is called, then the parser will be passed
+as the first argument to callbacks instead of userData.
+The userData will still be accessible using XML_GetUserData. */
+
+void XMLPARSEAPI
+XML_UseParserAsHandlerArg(XML_Parser parser);
+
+/* Sets the base to be used for resolving relative URIs in system identifiers in
+declarations. Resolving relative identifiers is left to the application:
+this value will be passed through as the base argument to the
+XML_ExternalEntityRefHandler, XML_NotationDeclHandler
+and XML_UnparsedEntityDeclHandler. The base argument will be copied.
+Returns zero if out of memory, non-zero otherwise. */
+
+int XMLPARSEAPI
+XML_SetBase(XML_Parser parser, const XML_Char *base);
+
+const XML_Char XMLPARSEAPI *
+XML_GetBase(XML_Parser parser);
+
+/* Returns the number of the attributes passed in last call to the
+XML_StartElementHandler that were specified in the start-tag rather
+than defaulted. */
+
+int XMLPARSEAPI XML_GetSpecifiedAttributeCount(XML_Parser parser);
+
+/* Parses some input. Returns 0 if a fatal error is detected.
+The last call to XML_Parse must have isFinal true;
+len may be zero for this call (or any other). */
+int XMLPARSEAPI
+XML_Parse(XML_Parser parser, const char *s, int len, int isFinal);
+
+void XMLPARSEAPI *
+XML_GetBuffer(XML_Parser parser, int len);
+
+int XMLPARSEAPI
+XML_ParseBuffer(XML_Parser parser, int len, int isFinal);
+
+/* Creates an XML_Parser object that can parse an external general entity;
+context is a '\0'-terminated string specifying the parse context;
+encoding is a '\0'-terminated string giving the name of the externally specified encoding,
+or null if there is no externally specified encoding.
+The context string consists of a sequence of tokens separated by formfeeds (\f);
+a token consisting of a name specifies that the general entity of the name
+is open; a token of the form prefix=uri specifies the namespace for a particular
+prefix; a token of the form =uri specifies the default namespace.
+This can be called at any point after the first call to an ExternalEntityRefHandler
+so longer as the parser has not yet been freed.
+The new parser is completely independent and may safely be used in a separate thread.
+The handlers and userData are initialized from the parser argument.
+Returns 0 if out of memory. Otherwise returns a new XML_Parser object. */
+XML_Parser XMLPARSEAPI
+XML_ExternalEntityParserCreate(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *encoding);
+
+enum XML_Error {
+ XML_ERROR_NONE,
+ XML_ERROR_NO_MEMORY,
+ XML_ERROR_SYNTAX,
+ XML_ERROR_NO_ELEMENTS,
+ XML_ERROR_INVALID_TOKEN,
+ XML_ERROR_UNCLOSED_TOKEN,
+ XML_ERROR_PARTIAL_CHAR,
+ XML_ERROR_TAG_MISMATCH,
+ XML_ERROR_DUPLICATE_ATTRIBUTE,
+ XML_ERROR_JUNK_AFTER_DOC_ELEMENT,
+ XML_ERROR_PARAM_ENTITY_REF,
+ XML_ERROR_UNDEFINED_ENTITY,
+ XML_ERROR_RECURSIVE_ENTITY_REF,
+ XML_ERROR_ASYNC_ENTITY,
+ XML_ERROR_BAD_CHAR_REF,
+ XML_ERROR_BINARY_ENTITY_REF,
+ XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF,
+ XML_ERROR_MISPLACED_XML_PI,
+ XML_ERROR_UNKNOWN_ENCODING,
+ XML_ERROR_INCORRECT_ENCODING,
+ XML_ERROR_UNCLOSED_CDATA_SECTION,
+ XML_ERROR_EXTERNAL_ENTITY_HANDLING,
+ XML_ERROR_NOT_STANDALONE
+};
+
+/* If XML_Parse or XML_ParseBuffer have returned 0, then XML_GetErrorCode
+returns information about the error. */
+
+enum XML_Error XMLPARSEAPI XML_GetErrorCode(XML_Parser parser);
+
+/* These functions return information about the current parse location.
+They may be called when XML_Parse or XML_ParseBuffer return 0;
+in this case the location is the location of the character at which
+the error was detected.
+They may also be called from any other callback called to report
+some parse event; in this the location is the location of the first
+of the sequence of characters that generated the event. */
+
+int XMLPARSEAPI XML_GetCurrentLineNumber(XML_Parser parser);
+int XMLPARSEAPI XML_GetCurrentColumnNumber(XML_Parser parser);
+long XMLPARSEAPI XML_GetCurrentByteIndex(XML_Parser parser);
+
+/* Return the number of bytes in the current event.
+Returns 0 if the event is in an internal entity. */
+
+int XMLPARSEAPI XML_GetCurrentByteCount(XML_Parser parser);
+
+/* For backwards compatibility with previous versions. */
+#define XML_GetErrorLineNumber XML_GetCurrentLineNumber
+#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber
+#define XML_GetErrorByteIndex XML_GetCurrentByteIndex
+
+/* Frees memory used by the parser. */
+void XMLPARSEAPI
+XML_ParserFree(XML_Parser parser);
+
+/* Returns a string describing the error. */
+const XML_LChar XMLPARSEAPI *XML_ErrorString(int code);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlParse_INCLUDED */
diff --git a/usr.sbin/httpd/src/lib/expat-lite/xmlrole.c b/usr.sbin/httpd/src/lib/expat-lite/xmlrole.c
new file mode 100644
index 00000000000..b18e35eb3c4
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/xmlrole.c
@@ -0,0 +1,1113 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#include "xmldef.h"
+#include "xmlrole.h"
+
+/* Doesn't check:
+
+ that ,| are not mixed in a model group
+ content of literals
+
+*/
+
+#ifndef MIN_BYTES_PER_CHAR
+#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar)
+#endif
+
+typedef int PROLOG_HANDLER(struct prolog_state *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc);
+
+static PROLOG_HANDLER
+ prolog0, prolog1, prolog2,
+ doctype0, doctype1, doctype2, doctype3, doctype4, doctype5,
+ internalSubset,
+ entity0, entity1, entity2, entity3, entity4, entity5, entity6,
+ entity7, entity8, entity9,
+ notation0, notation1, notation2, notation3, notation4,
+ attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6,
+ attlist7, attlist8, attlist9,
+ element0, element1, element2, element3, element4, element5, element6,
+ element7,
+ declClose,
+ error;
+
+static
+int syntaxError(PROLOG_STATE *);
+
+static
+int prolog0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ state->handler = prolog1;
+ return XML_ROLE_NONE;
+ case XML_TOK_XML_DECL:
+ state->handler = prolog1;
+ return XML_ROLE_XML_DECL;
+ case XML_TOK_PI:
+ state->handler = prolog1;
+ return XML_ROLE_NONE;
+ case XML_TOK_COMMENT:
+ state->handler = prolog1;
+ case XML_TOK_BOM:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (!XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ "DOCTYPE"))
+ break;
+ state->handler = doctype0;
+ return XML_ROLE_NONE;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return syntaxError(state);
+}
+
+static
+int prolog1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_PI:
+ case XML_TOK_COMMENT:
+ case XML_TOK_BOM:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (!XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ "DOCTYPE"))
+ break;
+ state->handler = doctype0;
+ return XML_ROLE_NONE;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return syntaxError(state);
+}
+
+static
+int prolog2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_PI:
+ case XML_TOK_COMMENT:
+ return XML_ROLE_NONE;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return syntaxError(state);
+}
+
+static
+int doctype0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = doctype1;
+ return XML_ROLE_DOCTYPE_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int doctype1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = internalSubset;
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) {
+ state->handler = doctype3;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) {
+ state->handler = doctype2;
+ return XML_ROLE_NONE;
+ }
+ break;
+ }
+ return syntaxError(state);
+}
+
+static
+int doctype2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = doctype3;
+ return XML_ROLE_DOCTYPE_PUBLIC_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int doctype3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = doctype4;
+ return XML_ROLE_DOCTYPE_SYSTEM_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int doctype4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = internalSubset;
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ }
+ return syntaxError(state);
+}
+
+static
+int doctype5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ }
+ return syntaxError(state);
+}
+
+static
+int internalSubset(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ "ENTITY")) {
+ state->handler = entity0;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ "ATTLIST")) {
+ state->handler = attlist0;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ "ELEMENT")) {
+ state->handler = element0;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ "NOTATION")) {
+ state->handler = notation0;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_PI:
+ case XML_TOK_COMMENT:
+ return XML_ROLE_NONE;
+ case XML_TOK_PARAM_ENTITY_REF:
+ return XML_ROLE_PARAM_ENTITY_REF;
+ case XML_TOK_CLOSE_BRACKET:
+ state->handler = doctype5;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_PERCENT:
+ state->handler = entity1;
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = entity2;
+ return XML_ROLE_GENERAL_ENTITY_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = entity7;
+ return XML_ROLE_PARAM_ENTITY_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) {
+ state->handler = entity4;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) {
+ state->handler = entity3;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_ENTITY_VALUE;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity4;
+ return XML_ROLE_ENTITY_PUBLIC_ID;
+ }
+ return syntaxError(state);
+}
+
+
+static
+int entity4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity5;
+ return XML_ROLE_ENTITY_SYSTEM_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = internalSubset;
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, "NDATA")) {
+ state->handler = entity6;
+ return XML_ROLE_NONE;
+ }
+ break;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity6(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = declClose;
+ return XML_ROLE_ENTITY_NOTATION_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity7(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) {
+ state->handler = entity9;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) {
+ state->handler = entity8;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_ENTITY_VALUE;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity8(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity9;
+ return XML_ROLE_ENTITY_PUBLIC_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int entity9(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_ENTITY_SYSTEM_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int notation0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = notation1;
+ return XML_ROLE_NOTATION_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int notation1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) {
+ state->handler = notation3;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) {
+ state->handler = notation2;
+ return XML_ROLE_NONE;
+ }
+ break;
+ }
+ return syntaxError(state);
+}
+
+static
+int notation2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = notation4;
+ return XML_ROLE_NOTATION_PUBLIC_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int notation3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_NOTATION_SYSTEM_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int notation4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_NOTATION_SYSTEM_ID;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = internalSubset;
+ return XML_ROLE_NOTATION_NO_SYSTEM_ID;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist1;
+ return XML_ROLE_ATTLIST_ELEMENT_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = internalSubset;
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist2;
+ return XML_ROLE_ATTRIBUTE_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ {
+ static const char *types[] = {
+ "CDATA",
+ "ID",
+ "IDREF",
+ "IDREFS",
+ "ENTITY",
+ "ENTITIES",
+ "NMTOKEN",
+ "NMTOKENS",
+ };
+ int i;
+ for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++)
+ if (XmlNameMatchesAscii(enc, ptr, types[i])) {
+ state->handler = attlist8;
+ return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i;
+ }
+ }
+ if (XmlNameMatchesAscii(enc, ptr, "NOTATION")) {
+ state->handler = attlist5;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = attlist3;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NMTOKEN:
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist4;
+ return XML_ROLE_ATTRIBUTE_ENUM_VALUE;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->handler = attlist8;
+ return XML_ROLE_NONE;
+ case XML_TOK_OR:
+ state->handler = attlist3;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = attlist6;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+
+static
+int attlist6(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = attlist7;
+ return XML_ROLE_ATTRIBUTE_NOTATION_VALUE;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist7(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->handler = attlist8;
+ return XML_ROLE_NONE;
+ case XML_TOK_OR:
+ state->handler = attlist6;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+/* default value */
+static
+int attlist8(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_POUND_NAME:
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ "IMPLIED")) {
+ state->handler = attlist1;
+ return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ "REQUIRED")) {
+ state->handler = attlist1;
+ return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ "FIXED")) {
+ state->handler = attlist9;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = attlist1;
+ return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE;
+ }
+ return syntaxError(state);
+}
+
+static
+int attlist9(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = attlist1;
+ return XML_ROLE_FIXED_ATTRIBUTE_VALUE;
+ }
+ return syntaxError(state);
+}
+
+static
+int element0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element1;
+ return XML_ROLE_ELEMENT_NAME;
+ }
+ return syntaxError(state);
+}
+
+static
+int element1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, "EMPTY")) {
+ state->handler = declClose;
+ return XML_ROLE_CONTENT_EMPTY;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, "ANY")) {
+ state->handler = declClose;
+ return XML_ROLE_CONTENT_ANY;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = element2;
+ state->level = 1;
+ return XML_ROLE_GROUP_OPEN;
+ }
+ return syntaxError(state);
+}
+
+static
+int element2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_POUND_NAME:
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ "PCDATA")) {
+ state->handler = element3;
+ return XML_ROLE_CONTENT_PCDATA;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->level = 2;
+ state->handler = element6;
+ return XML_ROLE_GROUP_OPEN;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT;
+ case XML_TOK_NAME_QUESTION:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_OPT;
+ case XML_TOK_NAME_ASTERISK:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_REP;
+ case XML_TOK_NAME_PLUS:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_PLUS;
+ }
+ return syntaxError(state);
+}
+
+static
+int element3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_OR:
+ state->handler = element4;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+static
+int element4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element5;
+ return XML_ROLE_CONTENT_ELEMENT;
+ }
+ return syntaxError(state);
+}
+
+static
+int element5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_OR:
+ state->handler = element4;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+static
+int element6(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_PAREN:
+ state->level += 1;
+ return XML_ROLE_GROUP_OPEN;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT;
+ case XML_TOK_NAME_QUESTION:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_OPT;
+ case XML_TOK_NAME_ASTERISK:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_REP;
+ case XML_TOK_NAME_PLUS:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_PLUS;
+ }
+ return syntaxError(state);
+}
+
+static
+int element7(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->level -= 1;
+ if (state->level == 0)
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE;
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->level -= 1;
+ if (state->level == 0)
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_CLOSE_PAREN_QUESTION:
+ state->level -= 1;
+ if (state->level == 0)
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_OPT;
+ case XML_TOK_CLOSE_PAREN_PLUS:
+ state->level -= 1;
+ if (state->level == 0)
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_PLUS;
+ case XML_TOK_COMMA:
+ state->handler = element6;
+ return XML_ROLE_GROUP_SEQUENCE;
+ case XML_TOK_OR:
+ state->handler = element6;
+ return XML_ROLE_GROUP_CHOICE;
+ }
+ return syntaxError(state);
+}
+
+static
+int declClose(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = internalSubset;
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+
+#if 0
+
+static
+int ignore(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_DECL_CLOSE:
+ state->handler = internalSubset;
+ return 0;
+ default:
+ return XML_ROLE_NONE;
+ }
+ return syntaxError(state);
+}
+#endif
+
+static
+int error(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ return XML_ROLE_NONE;
+}
+
+static
+int syntaxError(PROLOG_STATE *state)
+{
+ state->handler = error;
+ return XML_ROLE_ERROR;
+}
+
+void XmlPrologStateInit(PROLOG_STATE *state)
+{
+ state->handler = prolog0;
+}
diff --git a/usr.sbin/httpd/src/lib/expat-lite/xmlrole.h b/usr.sbin/httpd/src/lib/expat-lite/xmlrole.h
new file mode 100644
index 00000000000..877c40ba1f8
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/xmlrole.h
@@ -0,0 +1,111 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#ifndef XmlRole_INCLUDED
+#define XmlRole_INCLUDED 1
+
+#include "xmltok.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ XML_ROLE_ERROR = -1,
+ XML_ROLE_NONE = 0,
+ XML_ROLE_XML_DECL,
+ XML_ROLE_INSTANCE_START,
+ XML_ROLE_DOCTYPE_NAME,
+ XML_ROLE_DOCTYPE_SYSTEM_ID,
+ XML_ROLE_DOCTYPE_PUBLIC_ID,
+ XML_ROLE_DOCTYPE_CLOSE,
+ XML_ROLE_GENERAL_ENTITY_NAME,
+ XML_ROLE_PARAM_ENTITY_NAME,
+ XML_ROLE_ENTITY_VALUE,
+ XML_ROLE_ENTITY_SYSTEM_ID,
+ XML_ROLE_ENTITY_PUBLIC_ID,
+ XML_ROLE_ENTITY_NOTATION_NAME,
+ XML_ROLE_NOTATION_NAME,
+ XML_ROLE_NOTATION_SYSTEM_ID,
+ XML_ROLE_NOTATION_NO_SYSTEM_ID,
+ XML_ROLE_NOTATION_PUBLIC_ID,
+ XML_ROLE_ATTRIBUTE_NAME,
+ XML_ROLE_ATTRIBUTE_TYPE_CDATA,
+ XML_ROLE_ATTRIBUTE_TYPE_ID,
+ XML_ROLE_ATTRIBUTE_TYPE_IDREF,
+ XML_ROLE_ATTRIBUTE_TYPE_IDREFS,
+ XML_ROLE_ATTRIBUTE_TYPE_ENTITY,
+ XML_ROLE_ATTRIBUTE_TYPE_ENTITIES,
+ XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN,
+ XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS,
+ XML_ROLE_ATTRIBUTE_ENUM_VALUE,
+ XML_ROLE_ATTRIBUTE_NOTATION_VALUE,
+ XML_ROLE_ATTLIST_ELEMENT_NAME,
+ XML_ROLE_IMPLIED_ATTRIBUTE_VALUE,
+ XML_ROLE_REQUIRED_ATTRIBUTE_VALUE,
+ XML_ROLE_DEFAULT_ATTRIBUTE_VALUE,
+ XML_ROLE_FIXED_ATTRIBUTE_VALUE,
+ XML_ROLE_ELEMENT_NAME,
+ XML_ROLE_CONTENT_ANY,
+ XML_ROLE_CONTENT_EMPTY,
+ XML_ROLE_CONTENT_PCDATA,
+ XML_ROLE_GROUP_OPEN,
+ XML_ROLE_GROUP_CLOSE,
+ XML_ROLE_GROUP_CLOSE_REP,
+ XML_ROLE_GROUP_CLOSE_OPT,
+ XML_ROLE_GROUP_CLOSE_PLUS,
+ XML_ROLE_GROUP_CHOICE,
+ XML_ROLE_GROUP_SEQUENCE,
+ XML_ROLE_CONTENT_ELEMENT,
+ XML_ROLE_CONTENT_ELEMENT_REP,
+ XML_ROLE_CONTENT_ELEMENT_OPT,
+ XML_ROLE_CONTENT_ELEMENT_PLUS,
+ XML_ROLE_PARAM_ENTITY_REF
+};
+
+typedef struct prolog_state {
+ int (*handler)(struct prolog_state *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc);
+ unsigned level;
+} PROLOG_STATE;
+
+void XMLTOKAPI XmlPrologStateInit(PROLOG_STATE *);
+
+#define XmlTokenRole(state, tok, ptr, end, enc) \
+ (((state)->handler)(state, tok, ptr, end, enc))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlRole_INCLUDED */
diff --git a/usr.sbin/httpd/src/lib/expat-lite/xmltok.c b/usr.sbin/httpd/src/lib/expat-lite/xmltok.c
new file mode 100644
index 00000000000..f0570d81456
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/xmltok.c
@@ -0,0 +1,1527 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#include "xmldef.h"
+#include "xmltok.h"
+#include "nametab.h"
+
+#define VTABLE1 \
+ { PREFIX(prologTok), PREFIX(contentTok), PREFIX(cdataSectionTok) }, \
+ { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \
+ PREFIX(sameName), \
+ PREFIX(nameMatchesAscii), \
+ PREFIX(nameLength), \
+ PREFIX(skipS), \
+ PREFIX(getAtts), \
+ PREFIX(charRefNumber), \
+ PREFIX(predefinedEntityName), \
+ PREFIX(updatePosition), \
+ PREFIX(isPublicId)
+
+#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16)
+
+#define UCS2_GET_NAMING(pages, hi, lo) \
+ (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F)))
+
+/* A 2 byte UTF-8 representation splits the characters 11 bits
+between the bottom 5 and 6 bits of the bytes.
+We need 8 bits to index into pages, 3 bits to add to that index and
+5 bits to generate the mask. */
+#define UTF8_GET_NAMING2(pages, byte) \
+ (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \
+ + ((((byte)[0]) & 3) << 1) \
+ + ((((byte)[1]) >> 5) & 1)] \
+ & (1 << (((byte)[1]) & 0x1F)))
+
+/* A 3 byte UTF-8 representation splits the characters 16 bits
+between the bottom 4, 6 and 6 bits of the bytes.
+We need 8 bits to index into pages, 3 bits to add to that index and
+5 bits to generate the mask. */
+#define UTF8_GET_NAMING3(pages, byte) \
+ (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \
+ + ((((byte)[1]) >> 2) & 0xF)] \
+ << 3) \
+ + ((((byte)[1]) & 3) << 1) \
+ + ((((byte)[2]) >> 5) & 1)] \
+ & (1 << (((byte)[2]) & 0x1F)))
+
+#define UTF8_GET_NAMING(pages, p, n) \
+ ((n) == 2 \
+ ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
+ : ((n) == 3 \
+ ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \
+ : 0))
+
+#define UTF8_INVALID3(p) \
+ ((*p) == 0xED \
+ ? (((p)[1] & 0x20) != 0) \
+ : ((*p) == 0xEF \
+ ? ((p)[1] == 0xBF && ((p)[2] == 0xBF || (p)[2] == 0xBE)) \
+ : 0))
+
+#define UTF8_INVALID4(p) ((*p) == 0xF4 && ((p)[1] & 0x30) != 0)
+
+static
+int isNever(const ENCODING *enc, const char *p)
+{
+ return 0;
+}
+
+static
+int utf8_isName2(const ENCODING *enc, const char *p)
+{
+ return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
+}
+
+static
+int utf8_isName3(const ENCODING *enc, const char *p)
+{
+ return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
+}
+
+#define utf8_isName4 isNever
+
+static
+int utf8_isNmstrt2(const ENCODING *enc, const char *p)
+{
+ return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
+}
+
+static
+int utf8_isNmstrt3(const ENCODING *enc, const char *p)
+{
+ return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
+}
+
+#define utf8_isNmstrt4 isNever
+
+#define utf8_isInvalid2 isNever
+
+static
+int utf8_isInvalid3(const ENCODING *enc, const char *p)
+{
+ return UTF8_INVALID3((const unsigned char *)p);
+}
+
+static
+int utf8_isInvalid4(const ENCODING *enc, const char *p)
+{
+ return UTF8_INVALID4((const unsigned char *)p);
+}
+
+struct normal_encoding {
+ ENCODING enc;
+ unsigned char type[256];
+#ifdef XML_MIN_SIZE
+ int (*byteType)(const ENCODING *, const char *);
+ int (*isNameMin)(const ENCODING *, const char *);
+ int (*isNmstrtMin)(const ENCODING *, const char *);
+ int (*byteToAscii)(const ENCODING *, const char *);
+ int (*charMatches)(const ENCODING *, const char *, int);
+#endif /* XML_MIN_SIZE */
+ int (*isName2)(const ENCODING *, const char *);
+ int (*isName3)(const ENCODING *, const char *);
+ int (*isName4)(const ENCODING *, const char *);
+ int (*isNmstrt2)(const ENCODING *, const char *);
+ int (*isNmstrt3)(const ENCODING *, const char *);
+ int (*isNmstrt4)(const ENCODING *, const char *);
+ int (*isInvalid2)(const ENCODING *, const char *);
+ int (*isInvalid3)(const ENCODING *, const char *);
+ int (*isInvalid4)(const ENCODING *, const char *);
+};
+
+#ifdef XML_MIN_SIZE
+
+#define STANDARD_VTABLE(E) \
+ E ## byteType, \
+ E ## isNameMin, \
+ E ## isNmstrtMin, \
+ E ## byteToAscii, \
+ E ## charMatches,
+
+#else
+
+#define STANDARD_VTABLE(E) /* as nothing */
+
+#endif
+
+#define NORMAL_VTABLE(E) \
+ E ## isName2, \
+ E ## isName3, \
+ E ## isName4, \
+ E ## isNmstrt2, \
+ E ## isNmstrt3, \
+ E ## isNmstrt4, \
+ E ## isInvalid2, \
+ E ## isInvalid3, \
+ E ## isInvalid4
+
+static int checkCharRefNumber(int);
+
+#include "xmltok_impl.h"
+
+#ifdef XML_MIN_SIZE
+#define sb_isNameMin isNever
+#define sb_isNmstrtMin isNever
+#endif
+
+#ifdef XML_MIN_SIZE
+#define MINBPC(enc) ((enc)->minBytesPerChar)
+#else
+/* minimum bytes per character */
+#define MINBPC(enc) 1
+#endif
+
+#define SB_BYTE_TYPE(enc, p) \
+ (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
+
+#ifdef XML_MIN_SIZE
+static
+int sb_byteType(const ENCODING *enc, const char *p)
+{
+ return SB_BYTE_TYPE(enc, p);
+}
+#define BYTE_TYPE(enc, p) \
+ (((const struct normal_encoding *)(enc))->byteType(enc, p))
+#else
+#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
+#endif
+
+#ifdef XML_MIN_SIZE
+#define BYTE_TO_ASCII(enc, p) \
+ (((const struct normal_encoding *)(enc))->byteToAscii(enc, p))
+static
+int sb_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return *p;
+}
+#else
+#define BYTE_TO_ASCII(enc, p) (*p)
+#endif
+
+#define IS_NAME_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isName ## n(enc, p))
+#define IS_NMSTRT_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isNmstrt ## n(enc, p))
+#define IS_INVALID_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isInvalid ## n(enc, p))
+
+#ifdef XML_MIN_SIZE
+#define IS_NAME_CHAR_MINBPC(enc, p) \
+ (((const struct normal_encoding *)(enc))->isNameMin(enc, p))
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ (((const struct normal_encoding *)(enc))->isNmstrtMin(enc, p))
+#else
+#define IS_NAME_CHAR_MINBPC(enc, p) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
+#endif
+
+#ifdef XML_MIN_SIZE
+#define CHAR_MATCHES(enc, p, c) \
+ (((const struct normal_encoding *)(enc))->charMatches(enc, p, c))
+static
+int sb_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return *p == c;
+}
+#else
+/* c is an ASCII character */
+#define CHAR_MATCHES(enc, p, c) (*(p) == c)
+#endif
+
+#define PREFIX(ident) normal_ ## ident
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */
+ UTF8_cval1 = 0x00,
+ UTF8_cval2 = 0xc0,
+ UTF8_cval3 = 0xe0,
+ UTF8_cval4 = 0xf0
+};
+
+static
+void utf8_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ char *to;
+ const char *from;
+ if (fromLim - *fromP > toLim - *toP) {
+ /* Avoid copying partial characters. */
+ for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--)
+ if (((unsigned char)fromLim[-1] & 0xc0) != 0x80)
+ break;
+ }
+ for (to = *toP, from = *fromP; from != fromLim; from++, to++)
+ *to = *from;
+ *fromP = from;
+ *toP = to;
+}
+
+static
+void utf8_toUtf16(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ unsigned short *to = *toP;
+ const char *from = *fromP;
+ while (from != fromLim && to != toLim) {
+ switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) {
+ case BT_LEAD2:
+ *to++ = ((from[0] & 0x1f) << 6) | (from[1] & 0x3f);
+ from += 2;
+ break;
+ case BT_LEAD3:
+ *to++ = ((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f);
+ from += 3;
+ break;
+ case BT_LEAD4:
+ {
+ unsigned long n;
+ if (to + 1 == toLim)
+ break;
+ n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
+ n -= 0x10000;
+ to[0] = (unsigned short)((n >> 10) | 0xD800);
+ to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
+ to += 2;
+ from += 4;
+ }
+ break;
+ default:
+ *to++ = *from++;
+ break;
+ }
+ }
+ *fromP = from;
+ *toP = to;
+}
+
+#ifdef XML_NS
+static const struct normal_encoding utf8_encoding_ns = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#include "asciitab.h"
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+#endif
+
+static const struct normal_encoding utf8_encoding = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_utf8_encoding_ns = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#include "iasciitab.h"
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+#endif
+
+static const struct normal_encoding internal_utf8_encoding = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+static
+void latin1_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ for (;;) {
+ unsigned char c;
+ if (*fromP == fromLim)
+ break;
+ c = (unsigned char)**fromP;
+ if (c & 0x80) {
+ if (toLim - *toP < 2)
+ break;
+ *(*toP)++ = ((c >> 6) | UTF8_cval2);
+ *(*toP)++ = ((c & 0x3f) | 0x80);
+ (*fromP)++;
+ }
+ else {
+ if (*toP == toLim)
+ break;
+ *(*toP)++ = *(*fromP)++;
+ }
+ }
+}
+
+static
+void latin1_toUtf16(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ while (*fromP != fromLim && *toP != toLim)
+ *(*toP)++ = (unsigned char)*(*fromP)++;
+}
+
+#ifdef XML_NS
+
+static const struct normal_encoding latin1_encoding_ns = {
+ { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+#endif
+
+static const struct normal_encoding latin1_encoding = {
+ { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+static
+void ascii_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ while (*fromP != fromLim && *toP != toLim)
+ *(*toP)++ = *(*fromP)++;
+}
+
+#ifdef XML_NS
+
+static const struct normal_encoding ascii_encoding_ns = {
+ { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
+ {
+#include "asciitab.h"
+/* BT_NONXML == 0 */
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+#endif
+
+static const struct normal_encoding ascii_encoding = {
+ { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+/* BT_NONXML == 0 */
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+static int unicode_byte_type(char hi, char lo)
+{
+ switch ((unsigned char)hi) {
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+ return BT_LEAD4;
+ case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+ return BT_TRAIL;
+ case 0xFF:
+ switch ((unsigned char)lo) {
+ case 0xFF:
+ case 0xFE:
+ return BT_NONXML;
+ }
+ break;
+ }
+ return BT_NONASCII;
+}
+
+#define DEFINE_UTF16_TO_UTF8(E) \
+static \
+void E ## toUtf8(const ENCODING *enc, \
+ const char **fromP, const char *fromLim, \
+ char **toP, const char *toLim) \
+{ \
+ const char *from; \
+ for (from = *fromP; from != fromLim; from += 2) { \
+ int plane; \
+ unsigned char lo2; \
+ unsigned char lo = GET_LO(from); \
+ unsigned char hi = GET_HI(from); \
+ switch (hi) { \
+ case 0: \
+ if (lo < 0x80) { \
+ if (*toP == toLim) { \
+ *fromP = from; \
+ return; \
+ } \
+ *(*toP)++ = lo; \
+ break; \
+ } \
+ /* fall through */ \
+ case 0x1: case 0x2: case 0x3: \
+ case 0x4: case 0x5: case 0x6: case 0x7: \
+ if (toLim - *toP < 2) { \
+ *fromP = from; \
+ return; \
+ } \
+ *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \
+ *(*toP)++ = ((lo & 0x3f) | 0x80); \
+ break; \
+ default: \
+ if (toLim - *toP < 3) { \
+ *fromP = from; \
+ return; \
+ } \
+ /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
+ *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
+ *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \
+ *(*toP)++ = ((lo & 0x3f) | 0x80); \
+ break; \
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB: \
+ if (toLim - *toP < 4) { \
+ *fromP = from; \
+ return; \
+ } \
+ plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
+ *(*toP)++ = ((plane >> 2) | UTF8_cval4); \
+ *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \
+ from += 2; \
+ lo2 = GET_LO(from); \
+ *(*toP)++ = (((lo & 0x3) << 4) \
+ | ((GET_HI(from) & 0x3) << 2) \
+ | (lo2 >> 6) \
+ | 0x80); \
+ *(*toP)++ = ((lo2 & 0x3f) | 0x80); \
+ break; \
+ } \
+ } \
+ *fromP = from; \
+}
+
+#define DEFINE_UTF16_TO_UTF16(E) \
+static \
+void E ## toUtf16(const ENCODING *enc, \
+ const char **fromP, const char *fromLim, \
+ unsigned short **toP, const unsigned short *toLim) \
+{ \
+ /* Avoid copying first half only of surrogate */ \
+ if (fromLim - *fromP > ((toLim - *toP) << 1) \
+ && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \
+ fromLim -= 2; \
+ for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \
+ *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
+}
+
+#define SET2(ptr, ch) \
+ (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8)))
+#define GET_LO(ptr) ((unsigned char)(ptr)[0])
+#define GET_HI(ptr) ((unsigned char)(ptr)[1])
+
+DEFINE_UTF16_TO_UTF8(little2_)
+DEFINE_UTF16_TO_UTF16(little2_)
+
+#undef SET2
+#undef GET_LO
+#undef GET_HI
+
+#define SET2(ptr, ch) \
+ (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF)))
+#define GET_LO(ptr) ((unsigned char)(ptr)[1])
+#define GET_HI(ptr) ((unsigned char)(ptr)[0])
+
+DEFINE_UTF16_TO_UTF8(big2_)
+DEFINE_UTF16_TO_UTF16(big2_)
+
+#undef SET2
+#undef GET_LO
+#undef GET_HI
+
+#define LITTLE2_BYTE_TYPE(enc, p) \
+ ((p)[1] == 0 \
+ ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \
+ : unicode_byte_type((p)[1], (p)[0]))
+#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1)
+#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c)
+#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
+#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
+
+#ifdef XML_MIN_SIZE
+
+static
+int little2_byteType(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_BYTE_TYPE(enc, p);
+}
+
+static
+int little2_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_BYTE_TO_ASCII(enc, p);
+}
+
+static
+int little2_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return LITTLE2_CHAR_MATCHES(enc, p, c);
+}
+
+static
+int little2_isNameMin(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p);
+}
+
+static
+int little2_isNmstrtMin(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+}
+
+#undef VTABLE
+#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16
+
+#else /* not XML_MIN_SIZE */
+
+#undef PREFIX
+#define PREFIX(ident) little2_ ## ident
+#define MINBPC(enc) 2
+/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
+#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
+#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p)
+#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c)
+#define IS_NAME_CHAR(enc, p, n) 0
+#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p)
+#define IS_NMSTRT_CHAR(enc, p, n) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p)
+
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+#endif /* not XML_MIN_SIZE */
+
+#ifdef XML_NS
+
+static const struct normal_encoding little2_encoding_ns = {
+ { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 12
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#endif
+
+static const struct normal_encoding little2_encoding = {
+ { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 12
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#if XML_BYTE_ORDER != 21
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_little2_encoding_ns = {
+ { VTABLE, 2, 0, 1 },
+ {
+#include "iasciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#endif
+
+static const struct normal_encoding internal_little2_encoding = {
+ { VTABLE, 2, 0, 1 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#endif
+
+
+#define BIG2_BYTE_TYPE(enc, p) \
+ ((p)[0] == 0 \
+ ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \
+ : unicode_byte_type((p)[0], (p)[1]))
+#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1)
+#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c)
+#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
+#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
+
+#ifdef XML_MIN_SIZE
+
+static
+int big2_byteType(const ENCODING *enc, const char *p)
+{
+ return BIG2_BYTE_TYPE(enc, p);
+}
+
+static
+int big2_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return BIG2_BYTE_TO_ASCII(enc, p);
+}
+
+static
+int big2_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return BIG2_CHAR_MATCHES(enc, p, c);
+}
+
+static
+int big2_isNameMin(const ENCODING *enc, const char *p)
+{
+ return BIG2_IS_NAME_CHAR_MINBPC(enc, p);
+}
+
+static
+int big2_isNmstrtMin(const ENCODING *enc, const char *p)
+{
+ return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+}
+
+#undef VTABLE
+#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16
+
+#else /* not XML_MIN_SIZE */
+
+#undef PREFIX
+#define PREFIX(ident) big2_ ## ident
+#define MINBPC(enc) 2
+/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
+#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
+#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p)
+#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c)
+#define IS_NAME_CHAR(enc, p, n) 0
+#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p)
+#define IS_NMSTRT_CHAR(enc, p, n) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p)
+
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+#endif /* not XML_MIN_SIZE */
+
+#ifdef XML_NS
+
+static const struct normal_encoding big2_encoding_ns = {
+ { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 21
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#endif
+
+static const struct normal_encoding big2_encoding = {
+ { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 21
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#if XML_BYTE_ORDER != 12
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_big2_encoding_ns = {
+ { VTABLE, 2, 0, 1 },
+ {
+#include "iasciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#endif
+
+static const struct normal_encoding internal_big2_encoding = {
+ { VTABLE, 2, 0, 1 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#endif
+
+#undef PREFIX
+
+static
+int streqci(const char *s1, const char *s2)
+{
+ for (;;) {
+ char c1 = *s1++;
+ char c2 = *s2++;
+ if ('a' <= c1 && c1 <= 'z')
+ c1 += 'A' - 'a';
+ if ('a' <= c2 && c2 <= 'z')
+ c2 += 'A' - 'a';
+ if (c1 != c2)
+ return 0;
+ if (!c1)
+ break;
+ }
+ return 1;
+}
+
+static
+void initUpdatePosition(const ENCODING *enc, const char *ptr,
+ const char *end, POSITION *pos)
+{
+ normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
+}
+
+static
+int toAscii(const ENCODING *enc, const char *ptr, const char *end)
+{
+ char buf[1];
+ char *p = buf;
+ XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
+ if (p == buf)
+ return -1;
+ else
+ return buf[0];
+}
+
+static
+int isSpace(int c)
+{
+ switch (c) {
+ case 0x20:
+ case 0xD:
+ case 0xA:
+ case 0x9:
+ return 1;
+ }
+ return 0;
+}
+
+/* Return 1 if there's just optional white space
+or there's an S followed by name=val. */
+static
+int parsePseudoAttribute(const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **namePtr,
+ const char **valPtr,
+ const char **nextTokPtr)
+{
+ int c;
+ char openchar;
+ if (ptr == end) {
+ *namePtr = 0;
+ return 1;
+ }
+ if (!isSpace(toAscii(enc, ptr, end))) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ do {
+ ptr += enc->minBytesPerChar;
+ } while (isSpace(toAscii(enc, ptr, end)));
+ if (ptr == end) {
+ *namePtr = 0;
+ return 1;
+ }
+ *namePtr = ptr;
+ for (;;) {
+ c = toAscii(enc, ptr, end);
+ if (c == -1) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ if (c == '=')
+ break;
+ if (isSpace(c)) {
+ do {
+ ptr += enc->minBytesPerChar;
+ } while (isSpace(c = toAscii(enc, ptr, end)));
+ if (c != '=') {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ break;
+ }
+ ptr += enc->minBytesPerChar;
+ }
+ if (ptr == *namePtr) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ ptr += enc->minBytesPerChar;
+ c = toAscii(enc, ptr, end);
+ while (isSpace(c)) {
+ ptr += enc->minBytesPerChar;
+ c = toAscii(enc, ptr, end);
+ }
+ if (c != '"' && c != '\'') {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ openchar = c;
+ ptr += enc->minBytesPerChar;
+ *valPtr = ptr;
+ for (;; ptr += enc->minBytesPerChar) {
+ c = toAscii(enc, ptr, end);
+ if (c == openchar)
+ break;
+ if (!('a' <= c && c <= 'z')
+ && !('A' <= c && c <= 'Z')
+ && !('0' <= c && c <= '9')
+ && c != '.'
+ && c != '-'
+ && c != '_') {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ }
+ *nextTokPtr = ptr + enc->minBytesPerChar;
+ return 1;
+}
+
+static
+int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *,
+ const char *,
+ const char *),
+ int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **encodingName,
+ const ENCODING **encoding,
+ int *standalone)
+{
+ const char *val = 0;
+ const char *name = 0;
+ ptr += 5 * enc->minBytesPerChar;
+ end -= 2 * enc->minBytesPerChar;
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr) || !name) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!XmlNameMatchesAscii(enc, name, "version")) {
+ if (!isGeneralTextEntity) {
+ *badPtr = name;
+ return 0;
+ }
+ }
+ else {
+ if (versionPtr)
+ *versionPtr = val;
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr)) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!name) {
+ if (isGeneralTextEntity) {
+ /* a TextDecl must have an EncodingDecl */
+ *badPtr = ptr;
+ return 0;
+ }
+ return 1;
+ }
+ }
+ if (XmlNameMatchesAscii(enc, name, "encoding")) {
+ int c = toAscii(enc, val, end);
+ if (!('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z')) {
+ *badPtr = val;
+ return 0;
+ }
+ if (encodingName)
+ *encodingName = val;
+ if (encoding)
+ *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar);
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr)) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!name)
+ return 1;
+ }
+ if (!XmlNameMatchesAscii(enc, name, "standalone") || isGeneralTextEntity) {
+ *badPtr = name;
+ return 0;
+ }
+ if (XmlNameMatchesAscii(enc, val, "yes")) {
+ if (standalone)
+ *standalone = 1;
+ }
+ else if (XmlNameMatchesAscii(enc, val, "no")) {
+ if (standalone)
+ *standalone = 0;
+ }
+ else {
+ *badPtr = val;
+ return 0;
+ }
+ while (isSpace(toAscii(enc, ptr, end)))
+ ptr += enc->minBytesPerChar;
+ if (ptr != end) {
+ *badPtr = ptr;
+ return 0;
+ }
+ return 1;
+}
+
+static
+int checkCharRefNumber(int result)
+{
+ switch (result >> 8) {
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+ case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+ return -1;
+ case 0:
+ if (latin1_encoding.type[result] == BT_NONXML)
+ return -1;
+ break;
+ case 0xFF:
+ if (result == 0xFFFE || result == 0xFFFF)
+ return -1;
+ break;
+ }
+ return result;
+}
+
+int XmlUtf8Encode(int c, char *buf)
+{
+ enum {
+ /* minN is minimum legal resulting value for N byte sequence */
+ min2 = 0x80,
+ min3 = 0x800,
+ min4 = 0x10000
+ };
+
+ if (c < 0)
+ return 0;
+ if (c < min2) {
+ buf[0] = (c | UTF8_cval1);
+ return 1;
+ }
+ if (c < min3) {
+ buf[0] = ((c >> 6) | UTF8_cval2);
+ buf[1] = ((c & 0x3f) | 0x80);
+ return 2;
+ }
+ if (c < min4) {
+ buf[0] = ((c >> 12) | UTF8_cval3);
+ buf[1] = (((c >> 6) & 0x3f) | 0x80);
+ buf[2] = ((c & 0x3f) | 0x80);
+ return 3;
+ }
+ if (c < 0x110000) {
+ buf[0] = ((c >> 18) | UTF8_cval4);
+ buf[1] = (((c >> 12) & 0x3f) | 0x80);
+ buf[2] = (((c >> 6) & 0x3f) | 0x80);
+ buf[3] = ((c & 0x3f) | 0x80);
+ return 4;
+ }
+ return 0;
+}
+
+int XmlUtf16Encode(int charNum, unsigned short *buf)
+{
+ if (charNum < 0)
+ return 0;
+ if (charNum < 0x10000) {
+ buf[0] = charNum;
+ return 1;
+ }
+ if (charNum < 0x110000) {
+ charNum -= 0x10000;
+ buf[0] = (charNum >> 10) + 0xD800;
+ buf[1] = (charNum & 0x3FF) + 0xDC00;
+ return 2;
+ }
+ return 0;
+}
+
+struct unknown_encoding {
+ struct normal_encoding normal;
+ int (*convert)(void *userData, const char *p);
+ void *userData;
+ unsigned short utf16[256];
+ char utf8[256][4];
+};
+
+int XmlSizeOfUnknownEncoding(void)
+{
+ return sizeof(struct unknown_encoding);
+}
+
+static
+int unknown_isName(const ENCODING *enc, const char *p)
+{
+ int c = ((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, p);
+ if (c & ~0xFFFF)
+ return 0;
+ return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
+}
+
+static
+int unknown_isNmstrt(const ENCODING *enc, const char *p)
+{
+ int c = ((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, p);
+ if (c & ~0xFFFF)
+ return 0;
+ return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
+}
+
+static
+int unknown_isInvalid(const ENCODING *enc, const char *p)
+{
+ int c = ((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, p);
+ return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
+}
+
+static
+void unknown_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ char buf[XML_UTF8_ENCODE_MAX];
+ for (;;) {
+ const char *utf8;
+ int n;
+ if (*fromP == fromLim)
+ break;
+ utf8 = ((const struct unknown_encoding *)enc)->utf8[(unsigned char)**fromP];
+ n = *utf8++;
+ if (n == 0) {
+ int c = ((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
+ n = XmlUtf8Encode(c, buf);
+ if (n > toLim - *toP)
+ break;
+ utf8 = buf;
+ *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP]
+ - (BT_LEAD2 - 2);
+ }
+ else {
+ if (n > toLim - *toP)
+ break;
+ (*fromP)++;
+ }
+ do {
+ *(*toP)++ = *utf8++;
+ } while (--n != 0);
+ }
+}
+
+static
+void unknown_toUtf16(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ while (*fromP != fromLim && *toP != toLim) {
+ unsigned short c
+ = ((const struct unknown_encoding *)enc)->utf16[(unsigned char)**fromP];
+ if (c == 0) {
+ c = (unsigned short)((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
+ *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP]
+ - (BT_LEAD2 - 2);
+ }
+ else
+ (*fromP)++;
+ *(*toP)++ = c;
+ }
+}
+
+ENCODING *
+XmlInitUnknownEncoding(void *mem,
+ int *table,
+ int (*convert)(void *userData, const char *p),
+ void *userData)
+{
+ int i;
+ struct unknown_encoding *e = mem;
+ for (i = 0; i < sizeof(struct normal_encoding); i++)
+ ((char *)mem)[i] = ((char *)&latin1_encoding)[i];
+ for (i = 0; i < 128; i++)
+ if (latin1_encoding.type[i] != BT_OTHER
+ && latin1_encoding.type[i] != BT_NONXML
+ && table[i] != i)
+ return 0;
+ for (i = 0; i < 256; i++) {
+ int c = table[i];
+ if (c == -1) {
+ e->normal.type[i] = BT_MALFORM;
+ /* This shouldn't really get used. */
+ e->utf16[i] = 0xFFFF;
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = 0;
+ }
+ else if (c < 0) {
+ if (c < -4)
+ return 0;
+ e->normal.type[i] = BT_LEAD2 - (c + 2);
+ e->utf8[i][0] = 0;
+ e->utf16[i] = 0;
+ }
+ else if (c < 0x80) {
+ if (latin1_encoding.type[c] != BT_OTHER
+ && latin1_encoding.type[c] != BT_NONXML
+ && c != i)
+ return 0;
+ e->normal.type[i] = latin1_encoding.type[c];
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = (char)c;
+ e->utf16[i] = c == 0 ? 0xFFFF : c;
+ }
+ else if (checkCharRefNumber(c) < 0) {
+ e->normal.type[i] = BT_NONXML;
+ /* This shouldn't really get used. */
+ e->utf16[i] = 0xFFFF;
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = 0;
+ }
+ else {
+ if (c > 0xFFFF)
+ return 0;
+ if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff))
+ e->normal.type[i] = BT_NMSTRT;
+ else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff))
+ e->normal.type[i] = BT_NAME;
+ else
+ e->normal.type[i] = BT_OTHER;
+ e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1);
+ e->utf16[i] = c;
+ }
+ }
+ e->userData = userData;
+ e->convert = convert;
+ if (convert) {
+ e->normal.isName2 = unknown_isName;
+ e->normal.isName3 = unknown_isName;
+ e->normal.isName4 = unknown_isName;
+ e->normal.isNmstrt2 = unknown_isNmstrt;
+ e->normal.isNmstrt3 = unknown_isNmstrt;
+ e->normal.isNmstrt4 = unknown_isNmstrt;
+ e->normal.isInvalid2 = unknown_isInvalid;
+ e->normal.isInvalid3 = unknown_isInvalid;
+ e->normal.isInvalid4 = unknown_isInvalid;
+ }
+ e->normal.enc.utf8Convert = unknown_toUtf8;
+ e->normal.enc.utf16Convert = unknown_toUtf16;
+ return &(e->normal.enc);
+}
+
+/* If this enumeration is changed, getEncodingIndex and encodings
+must also be changed. */
+enum {
+ UNKNOWN_ENC = -1,
+ ISO_8859_1_ENC = 0,
+ US_ASCII_ENC,
+ UTF_8_ENC,
+ UTF_16_ENC,
+ UTF_16BE_ENC,
+ UTF_16LE_ENC,
+ /* must match encodingNames up to here */
+ NO_ENC
+};
+
+static
+int getEncodingIndex(const char *name)
+{
+ static const char *encodingNames[] = {
+ "ISO-8859-1",
+ "US-ASCII",
+ "UTF-8",
+ "UTF-16",
+ "UTF-16BE"
+ "UTF-16LE",
+ };
+ int i;
+ if (name == 0)
+ return NO_ENC;
+ for (i = 0; i < sizeof(encodingNames)/sizeof(encodingNames[0]); i++)
+ if (streqci(name, encodingNames[i]))
+ return i;
+ return UNKNOWN_ENC;
+}
+
+/* For binary compatibility, we store the index of the encoding specified
+at initialization in the isUtf16 member. */
+
+#define INIT_ENC_INDEX(enc) ((enc)->initEnc.isUtf16)
+
+/* This is what detects the encoding.
+encodingTable maps from encoding indices to encodings;
+INIT_ENC_INDEX(enc) is the index of the external (protocol) specified encoding;
+state is XML_CONTENT_STATE if we're parsing an external text entity,
+and XML_PROLOG_STATE otherwise.
+*/
+
+
+static
+int initScan(const ENCODING **encodingTable,
+ const INIT_ENCODING *enc,
+ int state,
+ const char *ptr,
+ const char *end,
+ const char **nextTokPtr)
+{
+ const ENCODING **encPtr;
+
+ if (ptr == end)
+ return XML_TOK_NONE;
+ encPtr = enc->encPtr;
+ if (ptr + 1 == end) {
+ /* only a single byte available for auto-detection */
+ /* a well-formed document entity must have more than one byte */
+ if (state != XML_CONTENT_STATE)
+ return XML_TOK_PARTIAL;
+ /* so we're parsing an external text entity... */
+ /* if UTF-16 was externally specified, then we need at least 2 bytes */
+ switch (INIT_ENC_INDEX(enc)) {
+ case UTF_16_ENC:
+ case UTF_16LE_ENC:
+ case UTF_16BE_ENC:
+ return XML_TOK_PARTIAL;
+ }
+ switch ((unsigned char)*ptr) {
+ case 0xFE:
+ case 0xFF:
+ case 0xEF: /* possibly first byte of UTF-8 BOM */
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ /* fall through */
+ case 0x00:
+ case 0x3C:
+ return XML_TOK_PARTIAL;
+ }
+ }
+ else {
+ switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
+ case 0xFEFF:
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ *nextTokPtr = ptr + 2;
+ *encPtr = encodingTable[UTF_16BE_ENC];
+ return XML_TOK_BOM;
+ /* 00 3C is handled in the default case */
+ case 0x3C00:
+ if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
+ || INIT_ENC_INDEX(enc) == UTF_16_ENC)
+ && state == XML_CONTENT_STATE)
+ break;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ case 0xFFFE:
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ *nextTokPtr = ptr + 2;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XML_TOK_BOM;
+ case 0xEFBB:
+ /* Maybe a UTF-8 BOM (EF BB BF) */
+ /* If there's an explicitly specified (external) encoding
+ of ISO-8859-1 or some flavour of UTF-16
+ and this is an external text entity,
+ don't look for the BOM,
+ because it might be a legal data. */
+ if (state == XML_CONTENT_STATE) {
+ int e = INIT_ENC_INDEX(enc);
+ if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC || e == UTF_16_ENC)
+ break;
+ }
+ if (ptr + 2 == end)
+ return XML_TOK_PARTIAL;
+ if ((unsigned char)ptr[2] == 0xBF) {
+ *encPtr = encodingTable[UTF_8_ENC];
+ return XML_TOK_BOM;
+ }
+ break;
+ default:
+ if (ptr[0] == '\0') {
+ /* 0 isn't a legal data character. Furthermore a document entity can only
+ start with ASCII characters. So the only way this can fail to be big-endian
+ UTF-16 if it it's an external parsed general entity that's labelled as
+ UTF-16LE. */
+ if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
+ break;
+ *encPtr = encodingTable[UTF_16BE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ }
+ else if (ptr[1] == '\0') {
+ /* We could recover here in the case:
+ - parsing an external entity
+ - second byte is 0
+ - no externally specified encoding
+ - no encoding declaration
+ by assuming UTF-16LE. But we don't, because this would mean when
+ presented just with a single byte, we couldn't reliably determine
+ whether we needed further bytes. */
+ if (state == XML_CONTENT_STATE)
+ break;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ }
+ break;
+ }
+ }
+ *encPtr = encodingTable[(int)INIT_ENC_INDEX(enc)];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+}
+
+
+#define NS(x) x
+#define ns(x) x
+#include "xmltok_ns.c"
+#undef NS
+#undef ns
+
+#ifdef XML_NS
+
+#define NS(x) x ## NS
+#define ns(x) x ## _ns
+
+#include "xmltok_ns.c"
+
+#undef NS
+#undef ns
+
+ENCODING *
+XmlInitUnknownEncodingNS(void *mem,
+ int *table,
+ int (*convert)(void *userData, const char *p),
+ void *userData)
+{
+ ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
+ if (enc)
+ ((struct normal_encoding *)enc)->type[':'] = BT_COLON;
+ return enc;
+}
+
+#endif /* XML_NS */
diff --git a/usr.sbin/httpd/src/lib/expat-lite/xmltok.h b/usr.sbin/httpd/src/lib/expat-lite/xmltok.h
new file mode 100644
index 00000000000..fd0ed08e34b
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/xmltok.h
@@ -0,0 +1,307 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#ifndef XmlTok_INCLUDED
+#define XmlTok_INCLUDED 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef XMLTOKAPI
+#define XMLTOKAPI /* as nothing */
+#endif
+
+/* The following token may be returned by XmlContentTok */
+#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of
+ illegal ]]> sequence */
+/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */
+#define XML_TOK_NONE -4 /* The string to be scanned is empty */
+#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan;
+ might be part of CRLF sequence */
+#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
+#define XML_TOK_PARTIAL -1 /* only part of a token */
+#define XML_TOK_INVALID 0
+
+/* The following tokens are returned by XmlContentTok; some are also
+ returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok */
+
+#define XML_TOK_START_TAG_WITH_ATTS 1
+#define XML_TOK_START_TAG_NO_ATTS 2
+#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */
+#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4
+#define XML_TOK_END_TAG 5
+#define XML_TOK_DATA_CHARS 6
+#define XML_TOK_DATA_NEWLINE 7
+#define XML_TOK_CDATA_SECT_OPEN 8
+#define XML_TOK_ENTITY_REF 9
+#define XML_TOK_CHAR_REF 10 /* numeric character reference */
+
+/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */
+#define XML_TOK_PI 11 /* processing instruction */
+#define XML_TOK_XML_DECL 12 /* XML decl or text decl */
+#define XML_TOK_COMMENT 13
+#define XML_TOK_BOM 14 /* Byte order mark */
+
+/* The following tokens are returned only by XmlPrologTok */
+#define XML_TOK_PROLOG_S 15
+#define XML_TOK_DECL_OPEN 16 /* <!foo */
+#define XML_TOK_DECL_CLOSE 17 /* > */
+#define XML_TOK_NAME 18
+#define XML_TOK_NMTOKEN 19
+#define XML_TOK_POUND_NAME 20 /* #name */
+#define XML_TOK_OR 21 /* | */
+#define XML_TOK_PERCENT 22
+#define XML_TOK_OPEN_PAREN 23
+#define XML_TOK_CLOSE_PAREN 24
+#define XML_TOK_OPEN_BRACKET 25
+#define XML_TOK_CLOSE_BRACKET 26
+#define XML_TOK_LITERAL 27
+#define XML_TOK_PARAM_ENTITY_REF 28
+#define XML_TOK_INSTANCE_START 29
+
+/* The following occur only in element type declarations */
+#define XML_TOK_NAME_QUESTION 30 /* name? */
+#define XML_TOK_NAME_ASTERISK 31 /* name* */
+#define XML_TOK_NAME_PLUS 32 /* name+ */
+#define XML_TOK_COND_SECT_OPEN 33 /* <![ */
+#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
+#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
+#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
+#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
+#define XML_TOK_COMMA 38
+
+/* The following token is returned only by XmlAttributeValueTok */
+#define XML_TOK_ATTRIBUTE_VALUE_S 39
+
+/* The following token is returned only by XmlCdataSectionTok */
+#define XML_TOK_CDATA_SECT_CLOSE 40
+
+/* With namespace processing this is returned by XmlPrologTok
+ for a name with a colon. */
+#define XML_TOK_PREFIXED_NAME 41
+
+#define XML_N_STATES 3
+#define XML_PROLOG_STATE 0
+#define XML_CONTENT_STATE 1
+#define XML_CDATA_SECTION_STATE 2
+
+#define XML_N_LITERAL_TYPES 2
+#define XML_ATTRIBUTE_VALUE_LITERAL 0
+#define XML_ENTITY_VALUE_LITERAL 1
+
+/* The size of the buffer passed to XmlUtf8Encode must be at least this. */
+#define XML_UTF8_ENCODE_MAX 4
+/* The size of the buffer passed to XmlUtf16Encode must be at least this. */
+#define XML_UTF16_ENCODE_MAX 2
+
+typedef struct position {
+ /* first line and first column are 0 not 1 */
+ unsigned long lineNumber;
+ unsigned long columnNumber;
+} POSITION;
+
+typedef struct {
+ const char *name;
+ const char *valuePtr;
+ const char *valueEnd;
+ char normalized;
+} ATTRIBUTE;
+
+struct encoding;
+typedef struct encoding ENCODING;
+
+struct encoding {
+ int (*scanners[XML_N_STATES])(const ENCODING *,
+ const char *,
+ const char *,
+ const char **);
+ int (*literalScanners[XML_N_LITERAL_TYPES])(const ENCODING *,
+ const char *,
+ const char *,
+ const char **);
+ int (*sameName)(const ENCODING *,
+ const char *, const char *);
+ int (*nameMatchesAscii)(const ENCODING *,
+ const char *, const char *);
+ int (*nameLength)(const ENCODING *, const char *);
+ const char *(*skipS)(const ENCODING *, const char *);
+ int (*getAtts)(const ENCODING *enc, const char *ptr,
+ int attsMax, ATTRIBUTE *atts);
+ int (*charRefNumber)(const ENCODING *enc, const char *ptr);
+ int (*predefinedEntityName)(const ENCODING *, const char *, const char *);
+ void (*updatePosition)(const ENCODING *,
+ const char *ptr,
+ const char *end,
+ POSITION *);
+ int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **badPtr);
+ void (*utf8Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim,
+ char **toP,
+ const char *toLim);
+ void (*utf16Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim,
+ unsigned short **toP,
+ const unsigned short *toLim);
+ int minBytesPerChar;
+ char isUtf8;
+ char isUtf16;
+};
+
+/*
+Scan the string starting at ptr until the end of the next complete token,
+but do not scan past eptr. Return an integer giving the type of token.
+
+Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set.
+
+Return XML_TOK_PARTIAL when the string does not contain a complete token;
+nextTokPtr will not be set.
+
+Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr
+will be set to point to the character which made the token invalid.
+
+Otherwise the string starts with a valid token; nextTokPtr will be set to point
+to the character following the end of that token.
+
+Each data character counts as a single token, but adjacent data characters
+may be returned together. Similarly for characters in the prolog outside
+literals, comments and processing instructions.
+*/
+
+
+#define XmlTok(enc, state, ptr, end, nextTokPtr) \
+ (((enc)->scanners[state])(enc, ptr, end, nextTokPtr))
+
+#define XmlPrologTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
+
+#define XmlContentTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
+
+#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
+
+/* This is used for performing a 2nd-level tokenization on
+the content of a literal that has already been returned by XmlTok. */
+
+#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
+ (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr))
+
+#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
+ XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
+
+#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \
+ XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
+
+#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2))
+
+#define XmlNameMatchesAscii(enc, ptr1, ptr2) \
+ (((enc)->nameMatchesAscii)(enc, ptr1, ptr2))
+
+#define XmlNameLength(enc, ptr) \
+ (((enc)->nameLength)(enc, ptr))
+
+#define XmlSkipS(enc, ptr) \
+ (((enc)->skipS)(enc, ptr))
+
+#define XmlGetAttributes(enc, ptr, attsMax, atts) \
+ (((enc)->getAtts)(enc, ptr, attsMax, atts))
+
+#define XmlCharRefNumber(enc, ptr) \
+ (((enc)->charRefNumber)(enc, ptr))
+
+#define XmlPredefinedEntityName(enc, ptr, end) \
+ (((enc)->predefinedEntityName)(enc, ptr, end))
+
+#define XmlUpdatePosition(enc, ptr, end, pos) \
+ (((enc)->updatePosition)(enc, ptr, end, pos))
+
+#define XmlIsPublicId(enc, ptr, end, badPtr) \
+ (((enc)->isPublicId)(enc, ptr, end, badPtr))
+
+#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \
+ (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim))
+
+#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \
+ (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim))
+
+typedef struct {
+ ENCODING initEnc;
+ const ENCODING **encPtr;
+} INIT_ENCODING;
+
+int XMLTOKAPI XmlParseXmlDecl(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **encodingNamePtr,
+ const ENCODING **namedEncodingPtr,
+ int *standalonePtr);
+
+int XMLTOKAPI XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name);
+const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncoding(void);
+const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncoding(void);
+int XMLTOKAPI XmlUtf8Encode(int charNumber, char *buf);
+int XMLTOKAPI XmlUtf16Encode(int charNumber, unsigned short *buf);
+
+int XMLTOKAPI XmlSizeOfUnknownEncoding(void);
+ENCODING XMLTOKAPI *
+XmlInitUnknownEncoding(void *mem,
+ int *table,
+ int (*conv)(void *userData, const char *p),
+ void *userData);
+
+int XMLTOKAPI XmlParseXmlDeclNS(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **encodingNamePtr,
+ const ENCODING **namedEncodingPtr,
+ int *standalonePtr);
+int XMLTOKAPI XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name);
+const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncodingNS(void);
+const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncodingNS(void);
+ENCODING XMLTOKAPI *
+XmlInitUnknownEncodingNS(void *mem,
+ int *table,
+ int (*conv)(void *userData, const char *p),
+ void *userData);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlTok_INCLUDED */
diff --git a/usr.sbin/httpd/src/lib/expat-lite/xmltok_impl.c b/usr.sbin/httpd/src/lib/expat-lite/xmltok_impl.c
new file mode 100644
index 00000000000..5dfe29f1b9e
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/xmltok_impl.c
@@ -0,0 +1,1746 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+#ifndef IS_INVALID_CHAR
+#define IS_INVALID_CHAR(enc, ptr, n) (0)
+#endif
+
+#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (IS_INVALID_CHAR(enc, ptr, n)) { \
+ *(nextTokPtr) = (ptr); \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define INVALID_CASES(ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(2, ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(3, ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(4, ptr, nextTokPtr) \
+ case BT_NONXML: \
+ case BT_MALFORM: \
+ case BT_TRAIL: \
+ *(nextTokPtr) = (ptr); \
+ return XML_TOK_INVALID;
+
+#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (!IS_NAME_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \
+ case BT_NONASCII: \
+ if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ case BT_NMSTRT: \
+ case BT_HEX: \
+ case BT_DIGIT: \
+ case BT_NAME: \
+ case BT_MINUS: \
+ ptr += MINBPC(enc); \
+ break; \
+ CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \
+ CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \
+ CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr)
+
+#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \
+ case BT_NONASCII: \
+ if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ case BT_NMSTRT: \
+ case BT_HEX: \
+ ptr += MINBPC(enc); \
+ break; \
+ CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \
+ CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \
+ CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr)
+
+#ifndef PREFIX
+#define PREFIX(ident) ident
+#endif
+
+/* ptr points to character following "<!-" */
+
+static
+int PREFIX(scanComment)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr != end) {
+ if (!CHAR_MATCHES(enc, ptr, '-')) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_MINUS:
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, '-')) {
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, '>')) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COMMENT;
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<!" */
+
+static
+int PREFIX(scanDecl)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_MINUS:
+ return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LSQB:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COND_SECT_OPEN;
+ case BT_NMSTRT:
+ case BT_HEX:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_PERCNT:
+ if (ptr + MINBPC(enc) == end)
+ return XML_TOK_PARTIAL;
+ /* don't allow <!ENTITY% foo "whatever"> */
+ switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) {
+ case BT_S: case BT_CR: case BT_LF: case BT_PERCNT:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ /* fall through */
+ case BT_S: case BT_CR: case BT_LF:
+ *nextTokPtr = ptr;
+ return XML_TOK_DECL_OPEN;
+ case BT_NMSTRT:
+ case BT_HEX:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end, int *tokPtr)
+{
+ int upper = 0;
+ *tokPtr = XML_TOK_PI;
+ if (end - ptr != MINBPC(enc)*3)
+ return 1;
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 'x':
+ break;
+ case 'X':
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ ptr += MINBPC(enc);
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 'm':
+ break;
+ case 'M':
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ ptr += MINBPC(enc);
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 'l':
+ break;
+ case 'L':
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ if (upper)
+ return 0;
+ *tokPtr = XML_TOK_XML_DECL;
+ return 1;
+}
+
+/* ptr points to character following "<?" */
+
+static
+int PREFIX(scanPi)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ int tok;
+ const char *target = ptr;
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_QUEST:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, '>')) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return tok;
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ return XML_TOK_PARTIAL;
+ case BT_QUEST:
+ if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, '>')) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return tok;
+ }
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+
+static
+int PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ int i;
+ /* CDATA[ */
+ if (end - ptr < 6 * MINBPC(enc))
+ return XML_TOK_PARTIAL;
+ for (i = 0; i < 6; i++, ptr += MINBPC(enc)) {
+ if (!CHAR_MATCHES(enc, ptr, "CDATA["[i])) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_CDATA_SECT_OPEN;
+}
+
+static
+int PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ']'))
+ break;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, '>')) {
+ ptr -= MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CDATA_SECT_CLOSE;
+ case BT_CR:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ case BT_LF:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ INVALID_CASES(ptr, nextTokPtr)
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_DATA_CHARS; \
+ } \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONXML:
+ case BT_MALFORM:
+ case BT_TRAIL:
+ case BT_CR:
+ case BT_LF:
+ case BT_RSQB:
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+/* ptr points to character following "</" */
+
+static
+int PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_CR: case BT_LF:
+ break;
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_END_TAG;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+#ifdef XML_NS
+ case BT_COLON:
+ /* no need to check qname syntax here, since end-tag must match exactly */
+ ptr += MINBPC(enc);
+ break;
+#endif
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_END_TAG;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#X" */
+
+static
+int PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ break;
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CHAR_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#" */
+
+static
+int PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr != end) {
+ if (CHAR_MATCHES(enc, ptr, 'x'))
+ return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ break;
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CHAR_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&" */
+
+static
+int PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_NUM:
+ return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_ENTITY_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following first character of attribute name */
+
+static
+int PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+#ifdef XML_NS
+ int hadColon = 0;
+#endif
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+ case BT_COLON:
+ if (hadColon) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ hadColon = 1;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+#endif
+ case BT_S: case BT_CR: case BT_LF:
+ for (;;) {
+ int t;
+
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ t = BYTE_TYPE(enc, ptr);
+ if (t == BT_EQUALS)
+ break;
+ switch (t) {
+ case BT_S:
+ case BT_LF:
+ case BT_CR:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ /* fall through */
+ case BT_EQUALS:
+ {
+ int opentype;
+#ifdef XML_NS
+ hadColon = 0;
+#endif
+ for (;;) {
+
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ opentype = BYTE_TYPE(enc, ptr);
+ if (opentype == BT_QUOT || opentype == BT_APOS)
+ break;
+ switch (opentype) {
+ case BT_S:
+ case BT_LF:
+ case BT_CR:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ ptr += MINBPC(enc);
+ /* in attribute value */
+ for (;;) {
+ int t;
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ t = BYTE_TYPE(enc, ptr);
+ if (t == opentype)
+ break;
+ switch (t) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_AMP:
+ {
+ int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr);
+ if (tok <= 0) {
+ if (tok == XML_TOK_INVALID)
+ *nextTokPtr = ptr;
+ return tok;
+ }
+ break;
+ }
+ case BT_LT:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
+ break;
+ case BT_SOL:
+ goto sol;
+ case BT_GT:
+ goto gt;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ /* ptr points to closing quote */
+ for (;;) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ continue;
+ case BT_GT:
+ gt:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_START_TAG_WITH_ATTS;
+ case BT_SOL:
+ sol:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, '>')) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_EMPTY_ELEMENT_WITH_ATTS;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+ }
+ break;
+ }
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<" */
+
+static
+int PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+#ifdef XML_NS
+ int hadColon;
+#endif
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_EXCL:
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_MINUS:
+ return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LSQB:
+ return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_QUEST:
+ return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_SOL:
+ return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+#ifdef XML_NS
+ hadColon = 0;
+#endif
+ /* we have a start-tag */
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+ case BT_COLON:
+ if (hadColon) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ hadColon = 1;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+#endif
+ case BT_S: case BT_CR: case BT_LF:
+ {
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_GT:
+ goto gt;
+ case BT_SOL:
+ goto sol;
+ case BT_S: case BT_CR: case BT_LF:
+ ptr += MINBPC(enc);
+ continue;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr);
+ }
+ return XML_TOK_PARTIAL;
+ }
+ case BT_GT:
+ gt:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_START_TAG_NO_ATTS;
+ case BT_SOL:
+ sol:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, '>')) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_EMPTY_ELEMENT_NO_ATTS;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_LT:
+ return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_AMP:
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_CR:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ case BT_LF:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_RSQB;
+ if (!CHAR_MATCHES(enc, ptr, ']'))
+ break;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_RSQB;
+ if (!CHAR_MATCHES(enc, ptr, '>')) {
+ ptr -= MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ INVALID_CASES(ptr, nextTokPtr)
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_DATA_CHARS; \
+ } \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_RSQB:
+ if (ptr + MINBPC(enc) != end) {
+ if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ']')) {
+ ptr += MINBPC(enc);
+ break;
+ }
+ if (ptr + 2*MINBPC(enc) != end) {
+ if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), '>')) {
+ ptr += MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr + 2*MINBPC(enc);
+ return XML_TOK_INVALID;
+ }
+ }
+ /* fall through */
+ case BT_AMP:
+ case BT_LT:
+ case BT_NONXML:
+ case BT_MALFORM:
+ case BT_TRAIL:
+ case BT_CR:
+ case BT_LF:
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+/* ptr points to character following "%" */
+
+static
+int PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_LF: case BT_CR: case BT_PERCNT:
+ *nextTokPtr = ptr;
+ return XML_TOK_PERCENT;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_PARAM_ENTITY_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_CR: case BT_LF: case BT_S:
+ case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR:
+ *nextTokPtr = ptr;
+ return XML_TOK_POUND_NAME;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(scanLit)(int opentype, const ENCODING *enc,
+ const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ while (ptr != end) {
+ int t = BYTE_TYPE(enc, ptr);
+ switch (t) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_QUOT:
+ case BT_APOS:
+ ptr += MINBPC(enc);
+ if (t != opentype)
+ break;
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ *nextTokPtr = ptr;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_CR: case BT_LF:
+ case BT_GT: case BT_PERCNT: case BT_LSQB:
+ return XML_TOK_LITERAL;
+ default:
+ return XML_TOK_INVALID;
+ }
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ int tok;
+ if (ptr == end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_QUOT:
+ return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_APOS:
+ return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LT:
+ {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_EXCL:
+ return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_QUEST:
+ return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_NMSTRT:
+ case BT_HEX:
+ case BT_NONASCII:
+ case BT_LEAD2:
+ case BT_LEAD3:
+ case BT_LEAD4:
+ *nextTokPtr = ptr - MINBPC(enc);
+ return XML_TOK_INSTANCE_START;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ case BT_CR:
+ if (ptr + MINBPC(enc) == end)
+ return XML_TOK_TRAILING_CR;
+ /* fall through */
+ case BT_S: case BT_LF:
+ for (;;) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ break;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_LF:
+ break;
+ case BT_CR:
+ /* don't split CR/LF pair */
+ if (ptr + MINBPC(enc) != end)
+ break;
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_PROLOG_S;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_PROLOG_S;
+ case BT_PERCNT:
+ return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_COMMA:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COMMA;
+ case BT_LSQB:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OPEN_BRACKET;
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ']')) {
+ if (ptr + MINBPC(enc) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr + MINBPC(enc), '>')) {
+ *nextTokPtr = ptr + 2*MINBPC(enc);
+ return XML_TOK_COND_SECT_CLOSE;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_CLOSE_BRACKET;
+ case BT_LPAR:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OPEN_PAREN;
+ case BT_RPAR:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_AST:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_ASTERISK;
+ case BT_QUEST:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_QUESTION;
+ case BT_PLUS:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_PLUS;
+ case BT_CR: case BT_LF: case BT_S:
+ case BT_GT: case BT_COMMA: case BT_VERBAR:
+ case BT_RPAR:
+ *nextTokPtr = ptr;
+ return XML_TOK_CLOSE_PAREN;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_VERBAR:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OR;
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DECL_CLOSE;
+ case BT_NUM:
+ return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
+ ptr += n; \
+ tok = XML_TOK_NAME; \
+ break; \
+ } \
+ if (IS_NAME_CHAR(enc, ptr, n)) { \
+ ptr += n; \
+ tok = XML_TOK_NMTOKEN; \
+ break; \
+ } \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NMSTRT:
+ case BT_HEX:
+ tok = XML_TOK_NAME;
+ ptr += MINBPC(enc);
+ break;
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ tok = XML_TOK_NMTOKEN;
+ ptr += MINBPC(enc);
+ break;
+ case BT_NONASCII:
+ if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) {
+ ptr += MINBPC(enc);
+ tok = XML_TOK_NAME;
+ break;
+ }
+ if (IS_NAME_CHAR_MINBPC(enc, ptr)) {
+ ptr += MINBPC(enc);
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_GT: case BT_RPAR: case BT_COMMA:
+ case BT_VERBAR: case BT_LSQB: case BT_PERCNT:
+ case BT_S: case BT_CR: case BT_LF:
+ *nextTokPtr = ptr;
+ return tok;
+#ifdef XML_NS
+ case BT_COLON:
+ ptr += MINBPC(enc);
+ switch (tok) {
+ case XML_TOK_NAME:
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ tok = XML_TOK_PREFIXED_NAME;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ break;
+ case XML_TOK_PREFIXED_NAME:
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ break;
+#endif
+ case BT_PLUS:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_PLUS;
+ case BT_AST:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_ASTERISK;
+ case BT_QUEST:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_QUESTION;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ const char *start;
+ if (ptr == end)
+ return XML_TOK_NONE;
+ start = ptr;
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_AMP:
+ if (ptr == start)
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_LT:
+ /* this is for inside entity references */
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_LF:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_CR:
+ if (ptr == start) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_S:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_ATTRIBUTE_VALUE_S;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+static
+int PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ const char *start;
+ if (ptr == end)
+ return XML_TOK_NONE;
+ start = ptr;
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_AMP:
+ if (ptr == start)
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_PERCNT:
+ if (ptr == start)
+ return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_LF:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_CR:
+ if (ptr == start) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+static
+int PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **badPtr)
+{
+ ptr += MINBPC(enc);
+ end -= MINBPC(enc);
+ for (; ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ case BT_MINUS:
+ case BT_APOS:
+ case BT_LPAR:
+ case BT_RPAR:
+ case BT_PLUS:
+ case BT_COMMA:
+ case BT_SOL:
+ case BT_EQUALS:
+ case BT_QUEST:
+ case BT_CR:
+ case BT_LF:
+ case BT_SEMI:
+ case BT_EXCL:
+ case BT_AST:
+ case BT_PERCNT:
+ case BT_NUM:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ break;
+ case BT_S:
+ if (CHAR_MATCHES(enc, ptr, '\t')) {
+ *badPtr = ptr;
+ return 0;
+ }
+ break;
+ case BT_NAME:
+ case BT_NMSTRT:
+ if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f))
+ break;
+ default:
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 0x24: /* $ */
+ case 0x40: /* @ */
+ break;
+ default:
+ *badPtr = ptr;
+ return 0;
+ }
+ break;
+ }
+ }
+ return 1;
+}
+
+/* This must only be called for a well-formed start-tag or empty element tag.
+Returns the number of attributes. Pointers to the first attsMax attributes
+are stored in atts. */
+
+static
+int PREFIX(getAtts)(const ENCODING *enc, const char *ptr,
+ int attsMax, ATTRIBUTE *atts)
+{
+ enum { other, inName, inValue } state = inName;
+ int nAtts = 0;
+ int opentype = 0;
+
+ for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define START_NAME \
+ if (state == other) { \
+ if (nAtts < attsMax) { \
+ atts[nAtts].name = ptr; \
+ atts[nAtts].normalized = 1; \
+ } \
+ state = inName; \
+ }
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONASCII:
+ case BT_NMSTRT:
+ case BT_HEX:
+ START_NAME
+ break;
+#undef START_NAME
+ case BT_QUOT:
+ if (state != inValue) {
+ if (nAtts < attsMax)
+ atts[nAtts].valuePtr = ptr + MINBPC(enc);
+ state = inValue;
+ opentype = BT_QUOT;
+ }
+ else if (opentype == BT_QUOT) {
+ state = other;
+ if (nAtts < attsMax)
+ atts[nAtts].valueEnd = ptr;
+ nAtts++;
+ }
+ break;
+ case BT_APOS:
+ if (state != inValue) {
+ if (nAtts < attsMax)
+ atts[nAtts].valuePtr = ptr + MINBPC(enc);
+ state = inValue;
+ opentype = BT_APOS;
+ }
+ else if (opentype == BT_APOS) {
+ state = other;
+ if (nAtts < attsMax)
+ atts[nAtts].valueEnd = ptr;
+ nAtts++;
+ }
+ break;
+ case BT_AMP:
+ if (nAtts < attsMax)
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_S:
+ if (state == inName)
+ state = other;
+ else if (state == inValue
+ && nAtts < attsMax
+ && atts[nAtts].normalized
+ && (ptr == atts[nAtts].valuePtr
+ || BYTE_TO_ASCII(enc, ptr) != ' '
+ || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ' '
+ || BYTE_TYPE(enc, ptr + MINBPC(enc)) == opentype))
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_CR: case BT_LF:
+ /* This case ensures that the first attribute name is counted
+ Apart from that we could just change state on the quote. */
+ if (state == inName)
+ state = other;
+ else if (state == inValue && nAtts < attsMax)
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_GT:
+ case BT_SOL:
+ if (state != inValue)
+ return nAtts;
+ break;
+ default:
+ break;
+ }
+ }
+ /* not reached */
+}
+
+static
+int PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr)
+{
+ int result = 0;
+ /* skip &# */
+ ptr += 2*MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 'x')) {
+ for (ptr += MINBPC(enc); !CHAR_MATCHES(enc, ptr, ';'); ptr += MINBPC(enc)) {
+ int c = BYTE_TO_ASCII(enc, ptr);
+ switch (c) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ result <<= 4;
+ result |= (c - '0');
+ break;
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ result <<= 4;
+ result += 10 + (c - 'A');
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ result <<= 4;
+ result += 10 + (c - 'a');
+ break;
+ }
+ if (result >= 0x110000)
+ return -1;
+ }
+ }
+ else {
+ for (; !CHAR_MATCHES(enc, ptr, ';'); ptr += MINBPC(enc)) {
+ int c = BYTE_TO_ASCII(enc, ptr);
+ result *= 10;
+ result += (c - '0');
+ if (result >= 0x110000)
+ return -1;
+ }
+ }
+ return checkCharRefNumber(result);
+}
+
+static
+int PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, const char *end)
+{
+ switch ((end - ptr)/MINBPC(enc)) {
+ case 2:
+ if (CHAR_MATCHES(enc, ptr + MINBPC(enc), 't')) {
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 'l':
+ return '<';
+ case 'g':
+ return '>';
+ }
+ }
+ break;
+ case 3:
+ if (CHAR_MATCHES(enc, ptr, 'a')) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 'm')) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 'p'))
+ return '&';
+ }
+ }
+ break;
+ case 4:
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 'q':
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 'u')) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 'o')) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 't'))
+ return '"';
+ }
+ }
+ break;
+ case 'a':
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 'p')) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 'o')) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, 's'))
+ return '\'';
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+static
+int PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2)
+{
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr1)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (*ptr1++ != *ptr2++) \
+ return 0;
+ LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2)
+#undef LEAD_CASE
+ /* fall through */
+ if (*ptr1++ != *ptr2++)
+ return 0;
+ break;
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 1) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 2) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 3) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ }
+ }
+ }
+ break;
+ default:
+ if (MINBPC(enc) == 1 && *ptr1 == *ptr2)
+ return 1;
+ switch (BYTE_TYPE(enc, ptr2)) {
+ case BT_LEAD2:
+ case BT_LEAD3:
+ case BT_LEAD4:
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ return 0;
+ default:
+ return 1;
+ }
+ }
+ }
+ /* not reached */
+}
+
+static
+int PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1, const char *ptr2)
+{
+ for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) {
+ if (!CHAR_MATCHES(enc, ptr1, *ptr2))
+ return 0;
+ }
+ switch (BYTE_TYPE(enc, ptr1)) {
+ case BT_LEAD2:
+ case BT_LEAD3:
+ case BT_LEAD4:
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+static
+int PREFIX(nameLength)(const ENCODING *enc, const char *ptr)
+{
+ const char *start = ptr;
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ return ptr - start;
+ }
+ }
+}
+
+static
+const char *PREFIX(skipS)(const ENCODING *enc, const char *ptr)
+{
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_LF:
+ case BT_CR:
+ case BT_S:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ return ptr;
+ }
+ }
+}
+
+static
+void PREFIX(updatePosition)(const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ POSITION *pos)
+{
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_LF:
+ pos->columnNumber = (unsigned)-1;
+ pos->lineNumber++;
+ ptr += MINBPC(enc);
+ break;
+ case BT_CR:
+ pos->lineNumber++;
+ ptr += MINBPC(enc);
+ if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ pos->columnNumber = (unsigned)-1;
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ pos->columnNumber++;
+ }
+}
+
+#undef DO_LEAD_CASE
+#undef MULTIBYTE_CASES
+#undef INVALID_CASES
+#undef CHECK_NAME_CASE
+#undef CHECK_NAME_CASES
+#undef CHECK_NMSTRT_CASE
+#undef CHECK_NMSTRT_CASES
diff --git a/usr.sbin/httpd/src/lib/expat-lite/xmltok_impl.h b/usr.sbin/httpd/src/lib/expat-lite/xmltok_impl.h
new file mode 100644
index 00000000000..e72b225c838
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/xmltok_impl.h
@@ -0,0 +1,71 @@
+/*
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is expat.
+
+The Initial Developer of the Original Code is James Clark.
+Portions created by James Clark are Copyright (C) 1998, 1999
+James Clark. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms
+of the GNU General Public License (the "GPL"), in which case the
+provisions of the GPL are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the GPL and not to allow others to use your version of this file under
+the MPL, indicate your decision by deleting the provisions above and
+replace them with the notice and other provisions required by the
+GPL. If you do not delete the provisions above, a recipient may use
+your version of this file under either the MPL or the GPL.
+*/
+
+enum {
+ BT_NONXML,
+ BT_MALFORM,
+ BT_LT,
+ BT_AMP,
+ BT_RSQB,
+ BT_LEAD2,
+ BT_LEAD3,
+ BT_LEAD4,
+ BT_TRAIL,
+ BT_CR,
+ BT_LF,
+ BT_GT,
+ BT_QUOT,
+ BT_APOS,
+ BT_EQUALS,
+ BT_QUEST,
+ BT_EXCL,
+ BT_SOL,
+ BT_SEMI,
+ BT_NUM,
+ BT_LSQB,
+ BT_S,
+ BT_NMSTRT,
+ BT_COLON,
+ BT_HEX,
+ BT_DIGIT,
+ BT_NAME,
+ BT_MINUS,
+ BT_OTHER, /* known not to be a name or name start character */
+ BT_NONASCII, /* might be a name or name start character */
+ BT_PERCNT,
+ BT_LPAR,
+ BT_RPAR,
+ BT_AST,
+ BT_PLUS,
+ BT_COMMA,
+ BT_VERBAR
+};
+
+#include <stddef.h>
diff --git a/usr.sbin/httpd/src/lib/expat-lite/xmltok_ns.c b/usr.sbin/httpd/src/lib/expat-lite/xmltok_ns.c
new file mode 100644
index 00000000000..a32c5774580
--- /dev/null
+++ b/usr.sbin/httpd/src/lib/expat-lite/xmltok_ns.c
@@ -0,0 +1,96 @@
+const ENCODING *NS(XmlGetUtf8InternalEncoding)(void)
+{
+ return &ns(internal_utf8_encoding).enc;
+}
+
+const ENCODING *NS(XmlGetUtf16InternalEncoding)(void)
+{
+#if XML_BYTE_ORDER == 12
+ return &ns(internal_little2_encoding).enc;
+#elif XML_BYTE_ORDER == 21
+ return &ns(internal_big2_encoding).enc;
+#else
+ const short n = 1;
+ return *(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc;
+#endif
+}
+
+static
+const ENCODING *NS(encodings)[] = {
+ &ns(latin1_encoding).enc,
+ &ns(ascii_encoding).enc,
+ &ns(utf8_encoding).enc,
+ &ns(big2_encoding).enc,
+ &ns(big2_encoding).enc,
+ &ns(little2_encoding).enc,
+ &ns(utf8_encoding).enc /* NO_ENC */
+};
+
+static
+int NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr);
+}
+
+static
+int NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr);
+}
+
+int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name)
+{
+ int i = getEncodingIndex(name);
+ if (i == UNKNOWN_ENC)
+ return 0;
+ INIT_ENC_INDEX(p) = (char)i;
+ p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog);
+ p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent);
+ p->initEnc.updatePosition = initUpdatePosition;
+ p->encPtr = encPtr;
+ *encPtr = &(p->initEnc);
+ return 1;
+}
+
+static
+const ENCODING *NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end)
+{
+#define ENCODING_MAX 128
+ char buf[ENCODING_MAX];
+ char *p = buf;
+ int i;
+ XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1);
+ if (ptr != end)
+ return 0;
+ *p = 0;
+ if (streqci(buf, "UTF-16") && enc->minBytesPerChar == 2)
+ return enc;
+ i = getEncodingIndex(buf);
+ if (i == UNKNOWN_ENC)
+ return 0;
+ return NS(encodings)[i];
+}
+
+int NS(XmlParseXmlDecl)(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **encodingName,
+ const ENCODING **encoding,
+ int *standalone)
+{
+ return doParseXmlDecl(NS(findEncoding),
+ isGeneralTextEntity,
+ enc,
+ ptr,
+ end,
+ badPtr,
+ versionPtr,
+ encodingName,
+ encoding,
+ standalone);
+}
diff --git a/usr.sbin/httpd/src/main/Makefile.tmpl b/usr.sbin/httpd/src/main/Makefile.tmpl
index be3400ecacc..0d774c3abb0 100644
--- a/usr.sbin/httpd/src/main/Makefile.tmpl
+++ b/usr.sbin/httpd/src/main/Makefile.tmpl
@@ -11,7 +11,7 @@ OBJS= alloc.o buff.o \
http_config.o http_core.o http_log.o \
http_main.o http_protocol.o http_request.o http_vhost.o \
util.o util_date.o util_script.o util_uri.o util_md5.o \
- md5c.o rfc1413.o
+ rfc1413.o
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $<
@@ -131,9 +131,6 @@ http_vhost.o: http_vhost.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
$(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
$(INCDIR)/http_log.h $(INCDIR)/http_vhost.h \
$(INCDIR)/http_protocol.h
-md5c.o: md5c.c $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
- $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(INCDIR)/ap_ctype.h \
- $(INCDIR)/hsregex.h $(INCDIR)/ap_md5.h
rfc1413.o: rfc1413.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
$(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/alloc.h \
diff --git a/usr.sbin/httpd/src/main/alloc.c b/usr.sbin/httpd/src/main/alloc.c
index 550f5f75c46..8086df2a6db 100644
--- a/usr.sbin/httpd/src/main/alloc.c
+++ b/usr.sbin/httpd/src/main/alloc.c
@@ -63,11 +63,20 @@
*/
#include "httpd.h"
+#ifdef EAPI
+#include "http_config.h"
+#include "http_conf_globals.h"
+#endif
#include "multithread.h"
#include "http_log.h"
#include <stdarg.h>
+#ifdef OS2
+#define INCL_DOS
+#include <os2.h>
+#endif
+
/* debugging support, define this to enable code which helps detect re-use
* of freed memory and other such nonsense.
*
@@ -111,6 +120,11 @@
*/
/* #define MAKE_TABLE_PROFILE */
+/* Provide some statistics on the cost of allocations. It requires a
+ * bit of an understanding of how alloc.c works.
+ */
+/* #define ALLOC_STATS */
+
#ifdef POOL_DEBUG
#ifdef ALLOC_USE_MALLOC
# error "sorry, no support for ALLOC_USE_MALLOC and POOL_DEBUG at the same time"
@@ -127,6 +141,10 @@
#define BLOCK_MINALLOC 0
#endif
+#if defined(EAPI) && defined(EAPI_MM)
+static AP_MM *mm = NULL;
+#endif
+
/*****************************************************************
*
* Managing free storage blocks...
@@ -155,6 +173,9 @@ union block_hdr {
char *endp;
union block_hdr *next;
char *first_avail;
+#if defined(EAPI) && defined(EAPI_MM)
+ int is_shm;
+#endif
#ifdef POOL_DEBUG
union block_hdr *global_next;
struct pool *owning_pool;
@@ -171,6 +192,13 @@ static int stack_direction;
static union block_hdr *global_block_list;
#define FREE_POOL ((struct pool *)(-1))
#endif
+#ifdef ALLOC_STATS
+static unsigned long long num_free_blocks_calls;
+static unsigned long long num_blocks_freed;
+static unsigned max_blocks_in_one_free;
+static unsigned num_malloc_calls;
+static unsigned num_malloc_bytes;
+#endif
#ifdef ALLOC_DEBUG
#define FILL_BYTE ((char)(0xa5))
@@ -198,7 +226,11 @@ static ap_inline void debug_verify_filled(const char *ptr,
/* Get a completely new block from the system pool. Note that we rely on
malloc() to provide aligned memory. */
+#if defined(EAPI) && defined(EAPI_MM)
+static union block_hdr *malloc_block(int size, int is_shm)
+#else
static union block_hdr *malloc_block(int size)
+#endif
{
union block_hdr *blok;
@@ -208,12 +240,24 @@ static union block_hdr *malloc_block(int size)
*/
size += CLICK_SZ;
#endif
+#ifdef ALLOC_STATS
+ ++num_malloc_calls;
+ num_malloc_bytes += size + sizeof(union block_hdr);
+#endif
+#if defined(EAPI) && defined(EAPI_MM)
+ if (is_shm)
+ blok = (union block_hdr *)ap_mm_malloc(mm, size + sizeof(union block_hdr));
+ else
+#endif
blok = (union block_hdr *) malloc(size + sizeof(union block_hdr));
if (blok == NULL) {
fprintf(stderr, "Ouch! malloc failed in malloc_block()\n");
exit(1);
}
debug_fill(blok, size + sizeof(union block_hdr));
+#if defined(EAPI) && defined(EAPI_MM)
+ blok->h.is_shm = is_shm;
+#endif
blok->h.next = NULL;
blok->h.first_avail = (char *) (blok + 1);
blok->h.endp = size + blok->h.first_avail;
@@ -261,6 +305,9 @@ static void free_blocks(union block_hdr *blok)
free(blok);
}
#else
+#ifdef ALLOC_STATS
+ unsigned num_blocks;
+#endif
/* First, put new blocks at the head of the free list ---
* we'll eventually bash the 'next' pointer of the last block
* in the chain to point to the free blocks we already had.
@@ -271,6 +318,10 @@ static void free_blocks(union block_hdr *blok)
if (blok == NULL)
return; /* Sanity check --- freeing empty pool? */
+#if defined(EAPI) && defined(EAPI_MM)
+ if (blok->h.is_shm)
+ (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
+#endif
(void) ap_acquire_mutex(alloc_mutex);
old_free_list = block_freelist;
block_freelist = blok;
@@ -281,7 +332,13 @@ static void free_blocks(union block_hdr *blok)
* now.
*/
+#ifdef ALLOC_STATS
+ num_blocks = 1;
+#endif
while (blok->h.next != NULL) {
+#ifdef ALLOC_STATS
+ ++num_blocks;
+#endif
chk_on_blk_list(blok, old_free_list);
blok->h.first_avail = (char *) (blok + 1);
debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
@@ -301,7 +358,20 @@ static void free_blocks(union block_hdr *blok)
/* Finally, reset next pointer to get the old free blocks back */
blok->h.next = old_free_list;
+
+#ifdef ALLOC_STATS
+ if (num_blocks > max_blocks_in_one_free) {
+ max_blocks_in_one_free = num_blocks;
+ }
+ ++num_free_blocks_calls;
+ num_blocks_freed += num_blocks;
+#endif
+
(void) ap_release_mutex(alloc_mutex);
+#if defined(EAPI) && defined(EAPI_MM)
+ if (blok->h.is_shm)
+ (void)ap_mm_unlock(mm);
+#endif
#endif
}
@@ -310,7 +380,11 @@ static void free_blocks(union block_hdr *blok)
* if necessary. Must be called with alarms blocked.
*/
+#if defined(EAPI) && defined(EAPI_MM)
+static union block_hdr *new_block(int min_size, int is_shm)
+#else
static union block_hdr *new_block(int min_size)
+#endif
{
union block_hdr **lastptr = &block_freelist;
union block_hdr *blok = block_freelist;
@@ -320,7 +394,12 @@ static union block_hdr *new_block(int min_size)
*/
while (blok != NULL) {
+#if defined(EAPI) && defined(EAPI_MM)
+ if (blok->h.is_shm == is_shm &&
+ min_size + BLOCK_MINFREE <= blok->h.endp - blok->h.first_avail) {
+#else
if (min_size + BLOCK_MINFREE <= blok->h.endp - blok->h.first_avail) {
+#endif
*lastptr = blok->h.next;
blok->h.next = NULL;
debug_verify_filled(blok->h.first_avail, blok->h.endp,
@@ -336,7 +415,11 @@ static union block_hdr *new_block(int min_size)
/* Nope. */
min_size += BLOCK_MINFREE;
+#if defined(EAPI) && defined(EAPI_MM)
+ blok = malloc_block((min_size > BLOCK_MINALLOC) ? min_size : BLOCK_MINALLOC, is_shm);
+#else
blok = malloc_block((min_size > BLOCK_MINALLOC) ? min_size : BLOCK_MINALLOC);
+#endif
return blok;
}
@@ -386,6 +469,9 @@ struct pool {
#ifdef POOL_DEBUG
struct pool *joined;
#endif
+#if defined(EAPI) && defined(EAPI_MM)
+ int is_shm;
+#endif
};
static pool *permanent_pool;
@@ -400,16 +486,28 @@ static pool *permanent_pool;
#define POOL_HDR_CLICKS (1 + ((sizeof(struct pool) - 1) / CLICK_SZ))
#define POOL_HDR_BYTES (POOL_HDR_CLICKS * CLICK_SZ)
+#if defined(EAPI) && defined(EAPI_MM)
+static struct pool *make_sub_pool_internal(struct pool *p, int is_shm)
+#else
API_EXPORT(struct pool *) ap_make_sub_pool(struct pool *p)
+#endif
{
union block_hdr *blok;
pool *new_pool;
ap_block_alarms();
+#if defined(EAPI) && defined(EAPI_MM)
+ if (is_shm)
+ (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
+#endif
(void) ap_acquire_mutex(alloc_mutex);
+#if defined(EAPI) && defined(EAPI_MM)
+ blok = new_block(POOL_HDR_BYTES, is_shm);
+#else
blok = new_block(POOL_HDR_BYTES);
+#endif
new_pool = (pool *) blok->h.first_avail;
blok->h.first_avail += POOL_HDR_BYTES;
#ifdef POOL_DEBUG
@@ -428,12 +526,38 @@ API_EXPORT(struct pool *) ap_make_sub_pool(struct pool *p)
p->sub_pools = new_pool;
}
+#if defined(EAPI) && defined(EAPI_MM)
+ new_pool->is_shm = is_shm;
+#endif
+
(void) ap_release_mutex(alloc_mutex);
+#if defined(EAPI) && defined(EAPI_MM)
+ if (is_shm)
+ (void)ap_mm_unlock(mm);
+#endif
ap_unblock_alarms();
return new_pool;
}
+#if defined(EAPI)
+#if defined(EAPI_MM)
+API_EXPORT(struct pool *) ap_make_sub_pool(struct pool *p)
+{
+ return make_sub_pool_internal(p, 0);
+}
+API_EXPORT(struct pool *) ap_make_shared_sub_pool(struct pool *p)
+{
+ return make_sub_pool_internal(p, 1);
+}
+#else
+API_EXPORT(struct pool *) ap_make_shared_sub_pool(struct pool *p)
+{
+ return NULL;
+}
+#endif
+#endif
+
#ifdef POOL_DEBUG
static void stack_var_init(char *s)
{
@@ -448,6 +572,27 @@ static void stack_var_init(char *s)
}
#endif
+#if defined(EAPI)
+int ap_shared_pool_possible(void)
+{
+ return ap_mm_useable();
+}
+#endif
+
+#ifdef ALLOC_STATS
+static void dump_stats(void)
+{
+ fprintf(stderr,
+ "alloc_stats: [%d] #free_blocks %llu #blocks %llu max %u #malloc %u #bytes %u\n",
+ (int)getpid(),
+ num_free_blocks_calls,
+ num_blocks_freed,
+ max_blocks_in_one_free,
+ num_malloc_calls,
+ num_malloc_bytes);
+}
+#endif
+
pool *ap_init_alloc(void)
{
#ifdef POOL_DEBUG
@@ -459,18 +604,80 @@ pool *ap_init_alloc(void)
alloc_mutex = ap_create_mutex(NULL);
spawn_mutex = ap_create_mutex(NULL);
permanent_pool = ap_make_sub_pool(NULL);
+#ifdef ALLOC_STATS
+ atexit(dump_stats);
+#endif
return permanent_pool;
}
+#if defined(EAPI)
+void ap_init_alloc_shared(int early)
+{
+#if defined(EAPI_MM)
+ int mm_size;
+ char *mm_path;
+ char *err1, *err2;
+
+ if (early) {
+ /* process very early on startup */
+ mm_size = ap_mm_maxsize();
+ if (mm_size > EAPI_MM_CORE_MAXSIZE)
+ mm_size = EAPI_MM_CORE_MAXSIZE;
+ mm_path = ap_server_root_relative(permanent_pool, EAPI_MM_CORE_PATH);
+ if ((mm = ap_mm_create(mm_size, mm_path)) == NULL) {
+ fprintf(stderr, "Ouch! ap_mm_create(%d, \"%s\") failed\n", mm_size, mm_path);
+ err1 = ap_mm_error();
+ if (err1 == NULL)
+ err1 = "-unknown-";
+ err2 = strerror(errno);
+ if (err2 == NULL)
+ err2 = "-unknown-";
+ fprintf(stderr, "Error: MM: %s: OS: %s\n", err1, err2);
+ abort();
+ exit(1);
+ }
+ }
+ else {
+ /* process a lot later on startup */
+#ifdef WIN32
+ ap_mm_permission(mm, (_S_IREAD|_S_IWRITE), ap_user_id, -1);
+#else
+ ap_mm_permission(mm, (S_IRUSR|S_IWUSR), ap_user_id, -1);
+#endif
+ }
+#endif /* EAPI_MM */
+ return;
+}
+
+void ap_kill_alloc_shared(void)
+{
+#if defined(EAPI_MM)
+ if (mm != NULL) {
+ ap_mm_destroy(mm);
+ mm = NULL;
+ }
+#endif /* EAPI_MM */
+ return;
+}
+#endif /* EAPI */
+
API_EXPORT(void) ap_clear_pool(struct pool *a)
{
ap_block_alarms();
+#if defined(EAPI) && defined(EAPI_MM)
+ if (a->is_shm)
+ (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
+#endif
(void) ap_acquire_mutex(alloc_mutex);
while (a->sub_pools)
ap_destroy_pool(a->sub_pools);
(void) ap_release_mutex(alloc_mutex);
+#if defined(EAPI) && defined(EAPI_MM)
+ if (a->is_shm)
+ (void)ap_mm_unlock(mm);
+#endif
/* Don't hold the mutex during cleanups. */
run_cleanups(a->cleanups);
a->cleanups = NULL;
@@ -504,6 +711,10 @@ API_EXPORT(void) ap_destroy_pool(pool *a)
ap_block_alarms();
ap_clear_pool(a);
+#if defined(EAPI) && defined(EAPI_MM)
+ if (a->is_shm)
+ (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
+#endif
(void) ap_acquire_mutex(alloc_mutex);
if (a->parent) {
if (a->parent->sub_pools == a)
@@ -514,6 +725,10 @@ API_EXPORT(void) ap_destroy_pool(pool *a)
a->sub_next->sub_prev = a->sub_prev;
}
(void) ap_release_mutex(alloc_mutex);
+#if defined(EAPI) && defined(EAPI_MM)
+ if (a->is_shm)
+ (void)ap_mm_unlock(mm);
+#endif
free_blocks(a->first);
ap_unblock_alarms();
@@ -528,6 +743,30 @@ API_EXPORT(long) ap_bytes_in_free_blocks(void)
return bytes_in_block_list(block_freelist);
}
+#if defined(EAPI)
+API_EXPORT(int) ap_acquire_pool(pool *p, ap_pool_lock_mode mode)
+{
+#if defined(EAPI_MM)
+ if (!p->is_shm)
+ return 1;
+ return ap_mm_lock(mm, mode == AP_POOL_RD ? AP_MM_LOCK_RD : AP_MM_LOCK_RW);
+#else
+ return 1;
+#endif
+}
+
+API_EXPORT(int) ap_release_pool(pool *p)
+{
+#if defined(EAPI_MM)
+ if (!p->is_shm)
+ return 1;
+ return ap_mm_unlock(mm);
+#else
+ return 1;
+#endif
+}
+#endif /* EAPI */
+
/*****************************************************************
* POOL_DEBUG support
*/
@@ -693,16 +932,31 @@ API_EXPORT(void *) ap_palloc(struct pool *a, int reqsize)
ap_block_alarms();
+#if defined(EAPI) && defined(EAPI_MM)
+ if (a->is_shm)
+ (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
+#endif
(void) ap_acquire_mutex(alloc_mutex);
+#if defined(EAPI) && defined(EAPI_MM)
+ blok = new_block(size, a->is_shm);
+#else
blok = new_block(size);
+#endif
a->last->h.next = blok;
a->last = blok;
#ifdef POOL_DEBUG
blok->h.owning_pool = a;
#endif
+#if defined(EAPI) && defined(EAPI_MM)
+ blok->h.is_shm = a->is_shm;
+#endif
(void) ap_release_mutex(alloc_mutex);
+#if defined(EAPI) && defined(EAPI_MM)
+ if (a->is_shm)
+ (void)ap_mm_unlock(mm);
+#endif
ap_unblock_alarms();
@@ -814,6 +1068,11 @@ static int psprintf_flush(ap_vformatter_buff *vbuff)
char *ptr;
size = (char *)ps->vbuff.curpos - ps->base;
+#if defined(EAPI) && defined(EAPI_MM)
+ if (ps->block->h.is_shm)
+ ptr = ap_mm_realloc(ps->base, 2*size);
+ else
+#endif
ptr = realloc(ps->base, 2*size);
if (ptr == NULL) {
fputs("Ouch! Out of memory!\n", stderr);
@@ -834,9 +1093,21 @@ static int psprintf_flush(ap_vformatter_buff *vbuff)
cur_len = strp - blok->h.first_avail;
/* must try another blok */
+#if defined(EAPI) && defined(EAPI_MM)
+ if (blok->h.is_shm)
+ (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
+#endif
(void) ap_acquire_mutex(alloc_mutex);
+#if defined(EAPI) && defined(EAPI_MM)
+ nblok = new_block(2 * cur_len, blok->h.is_shm);
+#else
nblok = new_block(2 * cur_len);
+#endif
(void) ap_release_mutex(alloc_mutex);
+#if defined(EAPI) && defined(EAPI_MM)
+ if (blok->h.is_shm)
+ (void)ap_mm_unlock(mm);
+#endif
memcpy(nblok->h.first_avail, blok->h.first_avail, cur_len);
ps->vbuff.curpos = nblok->h.first_avail + cur_len;
/* save a byte for the NUL terminator */
@@ -845,10 +1116,18 @@ static int psprintf_flush(ap_vformatter_buff *vbuff)
/* did we allocate the current blok? if so free it up */
if (ps->got_a_new_block) {
debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
+#if defined(EAPI) && defined(EAPI_MM)
+ if (blok->h.is_shm)
+ (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
+#endif
(void) ap_acquire_mutex(alloc_mutex);
blok->h.next = block_freelist;
block_freelist = blok;
(void) ap_release_mutex(alloc_mutex);
+#if defined(EAPI) && defined(EAPI_MM)
+ if (blok->h.is_shm)
+ (void)ap_mm_unlock(mm);
+#endif
}
ps->blok = nblok;
ps->got_a_new_block = 1;
@@ -867,6 +1146,11 @@ API_EXPORT(char *) ap_pvsprintf(pool *p, const char *fmt, va_list ap)
void *ptr;
ap_block_alarms();
+#if defined(EAPI) && defined(EAPI_MM)
+ if (p->is_shm)
+ ps.base = ap_mm_malloc(mm, 512);
+ else
+#endif
ps.base = malloc(512);
if (ps.base == NULL) {
fputs("Ouch! Out of memory!\n", stderr);
@@ -879,6 +1163,11 @@ API_EXPORT(char *) ap_pvsprintf(pool *p, const char *fmt, va_list ap)
*ps.vbuff.curpos++ = '\0';
ptr = ps.base;
/* shrink */
+#if defined(EAPI) && defined(EAPI_MM)
+ if (p->is_shm)
+ ptr = ap_mm_realloc(ptr, (char *)ps.vbuff.curpos - (char *)ptr);
+ else
+#endif
ptr = realloc(ptr, (char *)ps.vbuff.curpos - (char *)ptr);
if (ptr == NULL) {
fputs("Ouch! Out of memory!\n", stderr);
@@ -1671,9 +1960,9 @@ static void cleanup_pool_for_exec(pool *p)
API_EXPORT(void) ap_cleanup_for_exec(void)
{
-#ifndef WIN32
+#if !defined(WIN32) && !defined(OS2)
/*
- * Don't need to do anything on NT, because I
+ * Don't need to do anything on NT or OS/2, because I
* am actually going to spawn the new process - not
* exec it. All handles that are not inheritable, will
* be automajically closed. The only problem is with
@@ -1998,8 +2287,8 @@ struct process_chain {
struct process_chain *next;
};
-API_EXPORT(void) ap_note_subprocess(pool *a, int pid, enum kill_conditions how)
-{
+API_EXPORT(void) ap_note_subprocess(pool *a, pid_t pid, enum kill_conditions
+how) {
struct process_chain *new =
(struct process_chain *) ap_palloc(a, sizeof(struct process_chain));
@@ -2022,11 +2311,11 @@ API_EXPORT(void) ap_note_subprocess(pool *a, int pid, enum kill_conditions how)
#define BINMODE
#endif
-static int spawn_child_core(pool *p, int (*func) (void *, child_info *),
+static pid_t spawn_child_core(pool *p, int (*func) (void *, child_info *),
void *data,enum kill_conditions kill_how,
int *pipe_in, int *pipe_out, int *pipe_err)
{
- int pid;
+ pid_t pid;
int in_fds[2];
int out_fds[2];
int err_fds[2];
@@ -2141,6 +2430,60 @@ static int spawn_child_core(pool *p, int (*func) (void *, child_info *),
*/
}
+#elif defined(OS2)
+ {
+ int save_in=-1, save_out=-1, save_err=-1;
+
+ if (pipe_out) {
+ save_out = dup(STDOUT_FILENO);
+ dup2(out_fds[1], STDOUT_FILENO);
+ close(out_fds[1]);
+ DosSetFHState(out_fds[0], OPEN_FLAGS_NOINHERIT);
+ }
+
+ if (pipe_in) {
+ save_in = dup(STDIN_FILENO);
+ dup2(in_fds[0], STDIN_FILENO);
+ close(in_fds[0]);
+ DosSetFHState(in_fds[1], OPEN_FLAGS_NOINHERIT);
+ }
+
+ if (pipe_err) {
+ save_err = dup(STDERR_FILENO);
+ dup2(err_fds[1], STDERR_FILENO);
+ close(err_fds[1]);
+ DosSetFHState(err_fds[0], OPEN_FLAGS_NOINHERIT);
+ }
+
+ pid = func(data, NULL);
+
+ if ( pid )
+ ap_note_subprocess(p, pid, kill_how);
+
+ if (pipe_out) {
+ close(STDOUT_FILENO);
+ dup2(save_out, STDOUT_FILENO);
+ close(save_out);
+ *pipe_out = out_fds[0];
+ }
+
+ if (pipe_in) {
+ close(STDIN_FILENO);
+ dup2(save_in, STDIN_FILENO);
+ close(save_in);
+ *pipe_in = in_fds[1];
+ }
+
+ if (pipe_err) {
+ close(STDERR_FILENO);
+ dup2(save_err, STDERR_FILENO);
+ close(save_err);
+ *pipe_err = err_fds[0];
+ }
+ }
+#elif defined(TPF)
+ return (pid = ap_tpf_spawn_child(p, func, data, kill_how,
+ pipe_in, pipe_out, pipe_err, out_fds, in_fds, err_fds));
#else
if ((pid = fork()) < 0) {
@@ -2220,7 +2563,8 @@ API_EXPORT(int) ap_spawn_child(pool *p, int (*func) (void *, child_info *),
FILE **pipe_err)
{
int fd_in, fd_out, fd_err;
- int pid, save_errno;
+ pid_t pid;
+ int save_errno;
ap_block_alarms();
@@ -2280,7 +2624,7 @@ API_EXPORT(int) ap_bspawn_child(pool *p, int (*func) (void *, child_info *), voi
HANDLE hPipeOutputReadDup = NULL;
HANDLE hPipeErrorReadDup = NULL;
HANDLE hCurrentProcess;
- int pid = 0;
+ pid_t pid = 0;
child_info info;
@@ -2452,7 +2796,8 @@ API_EXPORT(int) ap_bspawn_child(pool *p, int (*func) (void *, child_info *), voi
#else
int fd_in, fd_out, fd_err;
- int pid, save_errno;
+ pid_t pid;
+ int save_errno;
ap_block_alarms();
@@ -2560,7 +2905,7 @@ static void free_proc_chain(struct process_chain *procs)
if ((p->kill_how == kill_after_timeout)
|| (p->kill_how == kill_only_once)) {
/* Subprocess may be dead already. Only need the timeout if not. */
- if (kill(p->pid, SIGTERM) != -1)
+ if (ap_os_kill(p->pid, SIGTERM) != -1)
need_timeout = 1;
}
else if (p->kill_how == kill_always) {
diff --git a/usr.sbin/httpd/src/main/buff.c b/usr.sbin/httpd/src/main/buff.c
index 85006a92478..33555a75763 100644
--- a/usr.sbin/httpd/src/main/buff.c
+++ b/usr.sbin/httpd/src/main/buff.c
@@ -272,11 +272,16 @@ static ap_inline int buff_read(BUFF *fb, void *buf, int nbyte)
}
else
rv = ap_read(fb, buf, nbyte);
+#elif defined (BEOS)
+ if (fb->flags & B_SOCKET) {
+ rv = recv(fb->fd_in, buf, nbyte, 0);
+ } else
+ rv = ap_read(fb,buf,nbyte);
#elif defined(TPF)
fd_set fds;
struct timeval tv;
- tpf_process_signals();
+ ap_check_signals();
if (fb->flags & B_SOCKET) {
alarm(rv = alarm(0));
FD_ZERO(&fds);
@@ -284,11 +289,10 @@ static ap_inline int buff_read(BUFF *fb, void *buf, int nbyte)
tv.tv_sec = rv+1;
tv.tv_usec = 0;
rv = ap_select(fb->fd_in + 1, &fds, NULL, NULL, &tv);
- if (rv < 1) {
- tpf_process_signals();
- return(rv);
- }
+ if (rv > 0)
+ rv = ap_read(fb, buf, nbyte);
}
+ else
rv = ap_read(fb, buf, nbyte);
#else
rv = ap_read(fb, buf, nbyte);
@@ -335,6 +339,11 @@ static ap_inline int buff_write(BUFF *fb, const void *buf, int nbyte)
}
else
rv = ap_write(fb, buf, nbyte);
+#elif defined(BEOS)
+ if(fb->flags & B_SOCKET) {
+ rv = send(fb->fd, buf, nbyte, 0);
+ } else
+ rv = ap_write(fb, buf,nbyte);
#else
rv = ap_write(fb, buf, nbyte);
#endif /* WIN32 */
@@ -705,6 +714,7 @@ static int read_with_errors(BUFF *fb, void *buf, int nbyte)
return rv;
}
+
/*
* Read up to nbyte bytes into buf.
* If fewer than byte bytes are currently available, then return those.
@@ -1259,8 +1269,10 @@ API_EXPORT(int) ap_bwrite(BUFF *fb, const void *buf, int nbyte)
if (cbuf != NULL)
free(cbuf);
cbuf = malloc(csize = nbyte+HUGE_STRING_LEN);
- if (cbuf == NULL)
+ if (cbuf == NULL) {
+ fprintf(stderr, "Ouch! Out of memory in ap_bwrite()!\n");
csize = 0;
+ }
}
ebcdic2ascii((cbuf) ? cbuf : (void*)buf, buf, nbyte);
buf = (cbuf) ? cbuf : buf;
@@ -1461,6 +1473,16 @@ API_EXPORT(int) ap_bclose(BUFF *fb)
rc3 = 0;
}
else {
+#elif defined(BEOS)
+ if (fb->flags & B_SOCKET) {
+ rc2 = ap_pclosesocket(fb->pool, fb->fd);
+ if (fb->fd_in != fb->fd) {
+ rc3 = ap_pclosesocket(fb->pool, fb->fd_in);
+ }
+ else {
+ rc3 = 0;
+ }
+ } else {
#endif
rc2 = ap_pclosef(fb->pool, fb->fd);
if (fb->fd_in != fb->fd) {
@@ -1469,7 +1491,7 @@ API_EXPORT(int) ap_bclose(BUFF *fb)
else {
rc3 = 0;
}
-#ifdef WIN32
+#if defined(WIN32) || defined (BEOS)
}
#endif
diff --git a/usr.sbin/httpd/src/main/http_config.c b/usr.sbin/httpd/src/main/http_config.c
index 2159c448550..8525b841103 100644
--- a/usr.sbin/httpd/src/main/http_config.c
+++ b/usr.sbin/httpd/src/main/http_config.c
@@ -99,7 +99,7 @@ static int total_modules = 0;
*/
static int dynamic_modules = 0;
API_VAR_EXPORT module *top_module = NULL;
-API_VAR_EXPORT module **ap_loaded_modules;
+API_VAR_EXPORT module **ap_loaded_modules=NULL;
typedef int (*handler_func) (request_rec *);
typedef void *(*dir_maker_func) (pool *, char *);
@@ -327,6 +327,9 @@ static void build_method_shortcuts(void)
}
}
method_ptrs = malloc((how_many_ptrs + NMETHODS) * sizeof(handler_func));
+ if (method_ptrs == NULL) {
+ fprintf(stderr, "Ouch! Out of memory in build_method_shortcuts()!\n");
+ }
next_ptr = 0;
for (i = 0; i < NMETHODS; ++i) {
/* XXX: This is an itsy bit presumptuous about the alignment
@@ -651,6 +654,7 @@ API_EXPORT(void) ap_remove_module(module *m)
m->module_index = -1; /* simulate being unloaded, should
* be unnecessary */
dynamic_modules--;
+ total_modules--;
}
API_EXPORT(void) ap_add_loaded_module(module *mod)
@@ -722,6 +726,9 @@ void ap_setup_prelinked_modules()
*/
ap_loaded_modules = (module **)malloc(
sizeof(module *)*(total_modules+DYNAMIC_MODULE_LIMIT+1));
+ if (ap_loaded_modules == NULL) {
+ fprintf(stderr, "Ouch! Out of memory in ap_setup_prelinked_modules()!\n");
+ }
for (m = ap_preloaded_modules, m2 = ap_loaded_modules; *m != NULL; )
*m2++ = *m++;
*m2 = NULL;
@@ -983,8 +990,26 @@ CORE_EXPORT(const command_rec *) ap_find_command_in_modules(const char *cmd_name
return NULL;
}
+CORE_EXPORT(void *) ap_set_config_vectors(cmd_parms *parms, void *config, module *mod)
+{
+ void *mconfig = ap_get_module_config(config, mod);
+ void *sconfig = ap_get_module_config(parms->server->module_config, mod);
+
+ if (!mconfig && mod->create_dir_config) {
+ mconfig = (*mod->create_dir_config) (parms->pool, parms->path);
+ ap_set_module_config(config, mod, mconfig);
+ }
+
+ if (!sconfig && mod->create_server_config) {
+ sconfig = (*mod->create_server_config) (parms->pool, parms->server);
+ ap_set_module_config(parms->server->module_config, mod, sconfig);
+ }
+ return mconfig;
+}
+
CORE_EXPORT(const char *) ap_handle_command(cmd_parms *parms, void *config, const char *l)
{
+ void *oldconfig;
const char *args, *cmd_name, *retval;
const command_rec *cmd;
module *mod = top_module;
@@ -1018,6 +1043,8 @@ CORE_EXPORT(const char *) ap_handle_command(cmd_parms *parms, void *config, cons
if (*cmd_name == '\0')
return NULL;
+ oldconfig = parms->context;
+ parms->context = config;
do {
if (!(cmd = ap_find_command_in_modules(cmd_name, &mod))) {
errno = EINVAL;
@@ -1026,25 +1053,13 @@ CORE_EXPORT(const char *) ap_handle_command(cmd_parms *parms, void *config, cons
"not included in the server configuration", NULL);
}
else {
- void *mconfig = ap_get_module_config(config, mod);
- void *sconfig =
- ap_get_module_config(parms->server->module_config, mod);
-
- if (!mconfig && mod->create_dir_config) {
- mconfig = (*mod->create_dir_config) (parms->pool, parms->path);
- ap_set_module_config(config, mod, mconfig);
- }
-
- if (!sconfig && mod->create_server_config) {
- sconfig =
- (*mod->create_server_config) (parms->pool, parms->server);
- ap_set_module_config(parms->server->module_config, mod, sconfig);
- }
+ void *mconfig = ap_set_config_vectors(parms,config, mod);
retval = invoke_cmd(cmd, parms, mconfig, args);
mod = mod->next; /* Next time around, skip this one */
}
} while (retval && !strcmp(retval, DECLINE_CMD));
+ parms->context = oldconfig;
return retval;
}
@@ -1119,7 +1134,7 @@ API_EXPORT_NONSTD(const char *) ap_set_file_slot(cmd_parms *cmd, char *struct_pt
*/
static cmd_parms default_parms =
-{NULL, 0, -1, NULL, NULL, NULL, NULL, NULL, NULL};
+{NULL, 0, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
API_EXPORT(char *) ap_server_root_relative(pool *p, char *file)
{
@@ -1544,14 +1559,6 @@ void ap_single_module_configure(pool *p, server_rec *s, module *m)
(*m->create_dir_config)(p, NULL));
}
-void ap_single_module_init(pool *p, server_rec *s, module *m)
-{
- if (m->init)
- (*m->init)(s, p);
- build_method_shortcuts();
- init_handlers(p);
-}
-
void ap_init_modules(pool *p, server_rec *s)
{
module *m;
diff --git a/usr.sbin/httpd/src/main/http_core.c b/usr.sbin/httpd/src/main/http_core.c
index 979f475122a..e02d32ec5f4 100644
--- a/usr.sbin/httpd/src/main/http_core.c
+++ b/usr.sbin/httpd/src/main/http_core.c
@@ -90,6 +90,9 @@
#endif
#endif
#endif
+#ifndef MMAP_LIMIT
+#define MMAP_LIMIT (4*1024*1024)
+#endif
/* Server core module... This module provides support for really basic
* server operations, including options and commands which control the
@@ -127,7 +130,7 @@ static void *create_core_dir_config(pool *a, char *dir)
conf->content_md5 = 2;
- conf->use_canonical_name = 1 | 2; /* 2 = unset, default on */
+ conf->use_canonical_name = USE_CANONICAL_NAME_UNSET;
conf->hostname_lookups = HOSTNAME_LOOKUP_UNSET;
conf->do_rfc1413 = DEFAULT_RFC1413 | 2; /* set bit 1 to indicate default */
@@ -145,6 +148,11 @@ static void *create_core_dir_config(pool *a, char *dir)
conf->limit_req_body = 0;
conf->sec = ap_make_array(a, 2, sizeof(void *));
+#ifdef WIN32
+ conf->script_interpreter_source = INTERPRETER_SOURCE_UNSET;
+#endif
+
+ conf->server_signature = srv_sig_unset;
return (void *)conf;
}
@@ -234,7 +242,7 @@ static void *merge_core_dir_configs(pool *a, void *basev, void *newv)
if ((new->content_md5 & 2) == 0) {
conf->content_md5 = new->content_md5;
}
- if ((new->use_canonical_name & 2) == 0) {
+ if (new->use_canonical_name != USE_CANONICAL_NAME_UNSET) {
conf->use_canonical_name = new->use_canonical_name;
}
@@ -262,6 +270,17 @@ static void *merge_core_dir_configs(pool *a, void *basev, void *newv)
if (new->satisfy != SATISFY_NOSPEC) {
conf->satisfy = new->satisfy;
}
+
+#ifdef WIN32
+ if (new->script_interpreter_source != INTERPRETER_SOURCE_UNSET) {
+ conf->script_interpreter_source = new->script_interpreter_source;
+ }
+#endif
+
+ if (new->server_signature != srv_sig_unset) {
+ conf->server_signature = new->server_signature;
+ }
+
return (void*)conf;
}
@@ -324,7 +343,7 @@ CORE_EXPORT(void) ap_add_per_url_conf(server_rec *s, void *url_config)
*new_space = url_config;
}
-static void add_file_conf(core_dir_config *conf, void *url_config)
+CORE_EXPORT(void) ap_add_file_conf(core_dir_config *conf, void *url_config)
{
void **new_space = (void **)ap_push_array(conf->sec);
@@ -339,7 +358,7 @@ static void add_file_conf(core_dir_config *conf, void *url_config)
* See directory_walk().
*/
-#if defined(OS2) || defined(WIN32)
+#ifdef HAVE_DRIVE_LETTERS
#define IS_SPECIAL(entry_core) \
((entry_core)->r != NULL \
|| ((entry_core)->d[0] != '/' && (entry_core)->d[1] != ':'))
@@ -398,18 +417,16 @@ void ap_core_reorder_directories(pool *p, server_rec *s)
int nelts;
void **elts;
int i;
+ pool *tmp;
- /* XXX: we are about to waste some ram ... we will build a new array
- * and we need some scratch space to do it. The old array and the
- * scratch space are never freed.
- */
sconf = ap_get_module_config(s->module_config, &core_module);
sec = sconf->sec;
nelts = sec->nelts;
elts = (void **)sec->elts;
- /* build our sorting space */
- sortbin = ap_palloc(p, sec->nelts * sizeof(*sortbin));
+ /* we have to allocate tmp space to do a stable sort */
+ tmp = ap_make_sub_pool(p);
+ sortbin = ap_palloc(tmp, sec->nelts * sizeof(*sortbin));
for (i = 0; i < nelts; ++i) {
sortbin[i].orig_index = i;
sortbin[i].elt = elts[i];
@@ -417,15 +434,12 @@ void ap_core_reorder_directories(pool *p, server_rec *s)
qsort(sortbin, nelts, sizeof(*sortbin), reorder_sorter);
- /* and now build a new array */
- /* XXX: uh I don't see why we can't reuse the old array, what
- * was I thinking? -djg */
- sec = ap_make_array(p, nelts, sizeof(void *));
+ /* and now copy back to the original array */
for (i = 0; i < nelts; ++i) {
- *(void **)ap_push_array(sec) = sortbin[i].elt;
+ elts[i] = sortbin[i].elt;
}
- sconf->sec = sec;
+ ap_destroy_pool(tmp);
}
/*****************************************************************
@@ -658,17 +672,50 @@ API_EXPORT(const char *) ap_get_remote_logname(request_rec *r)
* name" as supplied by a possible Host: header or full URI. We never
* trust the port passed in the client's headers, we always use the
* port of the actual socket.
+ *
+ * The DNS option to UseCanonicalName causes this routine to do a
+ * reverse lookup on the local IP address of the connectiona and use
+ * that for the ServerName. This makes its value more reliable while
+ * at the same time allowing Demon's magic virtual hosting to work.
+ * The assumption is that DNS lookups are sufficiently quick...
+ * -- fanf 1998-10-03
*/
-API_EXPORT(const char *) ap_get_server_name(const request_rec *r)
+API_EXPORT(const char *) ap_get_server_name(request_rec *r)
{
+ conn_rec *conn = r->connection;
core_dir_config *d;
d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
&core_module);
- if (d->use_canonical_name & 1) {
- return r->server->server_hostname;
+
+ if (d->use_canonical_name == USE_CANONICAL_NAME_OFF) {
+ return r->hostname ? r->hostname : r->server->server_hostname;
+ }
+ if (d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
+ if (conn->local_host == NULL) {
+ struct in_addr *iaddr;
+ struct hostent *hptr;
+ int old_stat;
+ old_stat = ap_update_child_status(conn->child_num,
+ SERVER_BUSY_DNS, r);
+ iaddr = &(conn->local_addr.sin_addr);
+ hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr),
+ AF_INET);
+ if (hptr != NULL) {
+ conn->local_host = ap_pstrdup(conn->pool,
+ (void *)hptr->h_name);
+ ap_str_tolower(conn->local_host);
+ }
+ else {
+ conn->local_host = ap_pstrdup(conn->pool,
+ r->server->server_hostname);
+ }
+ (void) ap_update_child_status(conn->child_num, old_stat, r);
+ }
+ return conn->local_host;
}
- return r->hostname ? r->hostname : r->server->server_hostname;
+ /* default */
+ return r->server->server_hostname;
}
API_EXPORT(unsigned) ap_get_server_port(const request_rec *r)
@@ -679,38 +726,21 @@ API_EXPORT(unsigned) ap_get_server_port(const request_rec *r)
port = r->server->port ? r->server->port : ap_default_port(r);
- if (d->use_canonical_name & 1) {
- return port;
+ if (d->use_canonical_name == USE_CANONICAL_NAME_OFF
+ || d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
+ return r->hostname ? ntohs(r->connection->local_addr.sin_port)
+ : port;
}
- return r->hostname ? ntohs(r->connection->local_addr.sin_port)
- : port;
+ /* default */
+ return port;
}
API_EXPORT(char *) ap_construct_url(pool *p, const char *uri,
- const request_rec *r)
+ request_rec *r)
{
- unsigned port;
- const char *host;
- core_dir_config *d =
- (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
-
- if (d->use_canonical_name & 1) {
- port = r->server->port ? r->server->port : ap_default_port(r);
- host = r->server->server_hostname;
- }
- else {
- if (r->hostname) {
- port = ntohs(r->connection->local_addr.sin_port);
- }
- else if (r->server->port) {
- port = r->server->port;
- }
- else {
- port = ap_default_port(r);
- }
+ unsigned port = ap_get_server_port(r);
+ const char *host = ap_get_server_name(r);
- host = r->hostname ? r->hostname : r->server->server_hostname;
- }
if (ap_is_default_port(port, r)) {
return ap_pstrcat(p, ap_http_method(r), "://", host, uri, NULL);
}
@@ -725,6 +755,196 @@ API_EXPORT(unsigned long) ap_get_limit_req_body(const request_rec *r)
return d->limit_req_body;
}
+#ifdef WIN32
+static char* get_interpreter_from_win32_registry(pool *p, const char* ext)
+{
+ char extension_path[] = "SOFTWARE\\Classes\\";
+ char executable_path[] = "\\SHELL\\OPEN\\COMMAND";
+
+ HKEY hkeyOpen;
+ DWORD type;
+ int size;
+ int result;
+ char *keyName;
+ char *buffer;
+ char *s;
+
+ if (!ext)
+ return NULL;
+ /*
+ * Future optimization:
+ * When the registry is successfully searched, store the interpreter
+ * string in a table to make subsequent look-ups faster
+ */
+
+ /* Open the key associated with the script extension */
+ keyName = ap_pstrcat(p, extension_path, ext, NULL);
+
+ result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE,
+ &hkeyOpen);
+
+ if (result != ERROR_SUCCESS)
+ return NULL;
+
+ /* Read to NULL buffer to find value size */
+ size = 0;
+ result = RegQueryValueEx(hkeyOpen, "", NULL, &type, NULL, &size);
+
+ if (result == ERROR_SUCCESS) {
+ buffer = ap_palloc(p, size);
+ result = RegQueryValueEx(hkeyOpen, "", NULL, &type, buffer, &size);
+ }
+
+ RegCloseKey(hkeyOpen);
+
+ if (result != ERROR_SUCCESS)
+ return NULL;
+
+ /* Open the key associated with the interpreter path */
+ keyName = ap_pstrcat(p, extension_path, buffer, executable_path, NULL);
+
+ result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE,
+ &hkeyOpen);
+
+ if (result != ERROR_SUCCESS)
+ return NULL;
+
+ /* Read to NULL buffer to find value size */
+ size = 0;
+ result = RegQueryValueEx(hkeyOpen, "", 0, &type, NULL, &size);
+
+ if (result == ERROR_SUCCESS) {
+ buffer = ap_palloc(p, size);
+ result = RegQueryValueEx(hkeyOpen, "", 0, &type, buffer, &size);
+ }
+
+ RegCloseKey(hkeyOpen);
+
+ if (result != ERROR_SUCCESS)
+ return NULL;
+
+ /*
+ * The canonical way shell command entries are entered in the Win32
+ * registry is as follows:
+ * shell [options] "%1"
+ * where
+ * shell - full path name to interpreter or shell to run.
+ * E.g., c:\usr\local\ntreskit\perl\bin\perl.exe
+ * options - optional switches
+ * E.g., \C
+ * "%1" - Place holder for file to run the shell against.
+ * Typically quoted.
+ *
+ * If we find a %1 or a quoted %1, lop it off.
+ */
+ if (buffer && *buffer) {
+ if ((s = strstr(buffer, "\"%1")))
+ *s = '\0';
+ else if ((s = strstr(buffer, "%1")))
+ *s = '\0';
+ }
+
+ return buffer;
+}
+
+API_EXPORT (file_type_e) ap_get_win32_interpreter(const request_rec *r,
+ char** interpreter )
+{
+ HANDLE hFile;
+ DWORD nBytesRead;
+ BOOLEAN bResult;
+ char buffer[1024];
+ core_dir_config *d;
+ int i;
+ file_type_e fileType = eFileTypeUNKNOWN;
+ char *ext = NULL;
+ char *exename = NULL;
+
+ d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+
+ /* Find the file extension */
+ exename = strrchr(r->filename, '/');
+ if (!exename) {
+ exename = strrchr(r->filename, '\\');
+ }
+ if (!exename) {
+ exename = r->filename;
+ }
+ else {
+ exename++;
+ }
+ ext = strrchr(exename, '.');
+
+ if (ext && (!strcasecmp(ext,".bat") || !strcasecmp(ext,".cmd"))) {
+ return eFileTypeEXE32;
+ }
+
+ /* If the file has an extension and it is not .com and not .exe and
+ * we've been instructed to search the registry, then do it!
+ */
+ if (ext && strcasecmp(ext,".exe") && strcasecmp(ext,".com") &&
+ d->script_interpreter_source == INTERPRETER_SOURCE_REGISTRY) {
+ /* Check the registry */
+ *interpreter = get_interpreter_from_win32_registry(r->pool, ext);
+ if (*interpreter)
+ return eFileTypeSCRIPT;
+ else {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r->server,
+ "ScriptInterpreterSource config directive set to \"registry\".\n\t"
+ "Registry was searched but interpreter not found. Trying the shebang line.");
+ }
+ }
+
+ /* Need to peek into the file figure out what it really is... */
+ hFile = CreateFile(r->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ return eFileTypeUNKNOWN;
+ }
+ bResult = ReadFile(hFile, (void*) &buffer, sizeof(buffer) - 1,
+ &nBytesRead, NULL);
+ if (!bResult || (nBytesRead == 0)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "ReadFile(%s) failed", r->filename);
+ CloseHandle(hFile);
+ return eFileTypeUNKNOWN;
+ }
+ CloseHandle(hFile);
+ buffer[nBytesRead] = '\0';
+
+ /* Script or executable, that is the question... */
+ if ((buffer[0] == '#') && (buffer[1] == '!')) {
+ /* Assuming file is a script since it starts with a shebang */
+ fileType = eFileTypeSCRIPT;
+ for (i = 2; i < sizeof(buffer); i++) {
+ if ((buffer[i] == '\r')
+ || (buffer[i] == '\n')) {
+ break;
+ }
+ }
+ buffer[i] = '\0';
+ for (i = 2; buffer[i] == ' ' ; ++i)
+ ;
+ *interpreter = ap_pstrdup(r->pool, buffer + i );
+ }
+ else {
+ /* Not a script, is it an executable? */
+ IMAGE_DOS_HEADER *hdr = (IMAGE_DOS_HEADER*)buffer;
+ if ((nBytesRead >= sizeof(IMAGE_DOS_HEADER)) && (hdr->e_magic == IMAGE_DOS_SIGNATURE)) {
+ if (hdr->e_lfarlc < 0x40)
+ fileType = eFileTypeEXE16;
+ else
+ fileType = eFileTypeEXE32;
+ }
+ else
+ fileType = eFileTypeUNKNOWN;
+ }
+
+ return fileType;
+}
+#endif
+
/*****************************************************************
*
* Commands... this module handles almost all of the NCSA httpd.conf
@@ -827,7 +1047,7 @@ static const char *set_document_root(cmd_parms *cmd, void *dummy, char *arg)
}
arg = ap_os_canonical_filename(cmd->pool, arg);
- if (!ap_is_directory(arg)) {
+ if (ap_configtestonly && ap_docrootcheck && !ap_is_directory(arg)) {
if (cmd->server->is_virtual) {
fprintf(stderr, "Warning: DocumentRoot [%s] does not exist\n",
arg);
@@ -893,7 +1113,7 @@ static const char *set_error_document(cmd_parms *cmd, core_dir_config *conf,
if (error_number == 401 &&
line[0] != '/' && line[0] != '"') { /* Ignore it... */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, NULL,
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, cmd->server,
"cannot use a full URL in a 401 ErrorDocument "
"directive --- ignoring!");
}
@@ -1064,6 +1284,7 @@ CORE_EXPORT_NONSTD(const char *) ap_limit_section(cmd_parms *cmd, void *dummy,
const char *arg)
{
const char *limited_methods = ap_getword(cmd->pool, &arg, '>');
+ void *tog = cmd->cmd->cmd_data;
int limited = 0;
const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
@@ -1072,7 +1293,7 @@ CORE_EXPORT_NONSTD(const char *) ap_limit_section(cmd_parms *cmd, void *dummy,
}
/* XXX: NB: Currently, we have no way of checking
- * whether <Limit> sections are closed properly.
+ * whether <Limit> or <LimitExcept> sections are closed properly.
* (If we would add a srm_command_loop() here we might...)
*/
@@ -1080,26 +1301,31 @@ CORE_EXPORT_NONSTD(const char *) ap_limit_section(cmd_parms *cmd, void *dummy,
char *method = ap_getword_conf(cmd->pool, &limited_methods);
int methnum = ap_method_number_of(method);
- if (methnum == M_TRACE) {
+ if (methnum == M_TRACE && !tog) {
return "TRACE cannot be controlled by <Limit>";
}
else if (methnum == M_INVALID) {
- return ap_pstrcat(cmd->pool, "unknown method \"",
- method, "\" in <Limit>", NULL);
+ return ap_pstrcat(cmd->pool, "unknown method \"", method,
+ "\" in <Limit", tog ? "Except>" : ">", NULL);
}
else {
limited |= (1 << methnum);
}
}
- cmd->limited = limited;
+ /* Killing two features with one function,
+ * if (tog == NULL) <Limit>, else <LimitExcept>
+ */
+ cmd->limited = tog ? ~limited : limited;
return NULL;
}
static const char *endlimit_section(cmd_parms *cmd, void *dummy, void *dummy2)
{
+ void *tog = cmd->cmd->cmd_data;
+
if (cmd->limited == -1) {
- return "</Limit> unexpected";
+ return tog ? "</LimitExcept> unexpected" : "</Limit> unexpected";
}
cmd->limited = -1;
@@ -1183,10 +1409,6 @@ static const char *dirsection(cmd_parms *cmd, void *dummy, const char *arg)
*endp = '\0';
cmd->path = ap_getword_conf(cmd->pool, &arg);
-#ifdef OS2
- /* Fix OS/2 HPFS filename case problem. */
- cmd->path = strlwr(cmd->path);
-#endif
cmd->override = OR_ALL|ACCESS_CONF;
if (thiscmd->cmd_data) { /* <DirectoryMatch> */
@@ -1360,7 +1582,7 @@ static const char *filesection(cmd_parms *cmd, core_dir_config *c,
conf->d_is_fnmatch = ap_is_fnmatch(conf->d) != 0;
conf->r = r;
- add_file_conf(c, new_file_conf);
+ ap_add_file_conf(c, new_file_conf);
if (*arg != '\0') {
return ap_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
@@ -1719,7 +1941,7 @@ static const char *set_user(cmd_parms *cmd, void *dummy, char *arg)
"Error:\tApache has not been designed to serve pages while\n"
"\trunning as root. There are known race conditions that\n"
"\twill allow any local user to read any file on the system.\n"
- "\tShould you still desire to serve pages as root then\n"
+ "\tIf you still desire to serve pages as root then\n"
"\tadd -DBIG_SECURITY_HOLE to the EXTRA_CFLAGS line in your\n"
"\tsrc/Configuration file and rebuild the server. It is\n"
"\tstrongly suggested that you instead modify the User\n"
@@ -1923,15 +2145,25 @@ static const char *set_content_md5(cmd_parms *cmd, core_dir_config *d, int arg)
}
static const char *set_use_canonical_name(cmd_parms *cmd, core_dir_config *d,
- int arg)
+ char *arg)
{
const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
-
if (err != NULL) {
return err;
}
-
- d->use_canonical_name = arg != 0;
+
+ if (strcasecmp(arg, "on") == 0) {
+ d->use_canonical_name = USE_CANONICAL_NAME_ON;
+ }
+ else if (strcasecmp(arg, "off") == 0) {
+ d->use_canonical_name = USE_CANONICAL_NAME_OFF;
+ }
+ else if (strcasecmp(arg, "dns") == 0) {
+ d->use_canonical_name = USE_CANONICAL_NAME_DNS;
+ }
+ else {
+ return "parameter must be 'on', 'off', or 'dns'";
+ }
return NULL;
}
@@ -2300,7 +2532,8 @@ API_EXPORT(const char *) ap_psignature(const char *prefix, request_rec *r)
conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
&core_module);
- if (conf->server_signature == srv_sig_off) {
+ if ((conf->server_signature == srv_sig_off)
+ || (conf->server_signature == srv_sig_unset)) {
return "";
}
@@ -2452,6 +2685,21 @@ static const char *set_limit_req_body(cmd_parms *cmd, core_dir_config *conf,
return NULL;
}
+#ifdef WIN32
+static const char *set_interpreter_source(cmd_parms *cmd, core_dir_config *d,
+ char *arg)
+{
+ if (!strcasecmp(arg, "registry")) {
+ d->script_interpreter_source = INTERPRETER_SOURCE_REGISTRY;
+ } else if (!strcasecmp(arg, "script")) {
+ d->script_interpreter_source = INTERPRETER_SOURCE_SHEBANG;
+ } else {
+ d->script_interpreter_source = INTERPRETER_SOURCE_SHEBANG;
+ }
+ return NULL;
+}
+#endif
+
/* Note --- ErrorDocument will now work from .htaccess files.
* The AllowOverride of Fileinfo allows webmasters to turn it off
*/
@@ -2483,6 +2731,11 @@ static const command_rec core_cmds[] = {
"authentication directives when accessed using specified HTTP methods" },
{ "</Limit>", endlimit_section, NULL, OR_ALL, NO_ARGS,
"Marks end of <Limit>" },
+{ "<LimitExcept", ap_limit_section, (void*)1, OR_ALL, RAW_ARGS,
+ "Container for authentication directives to be applied when any HTTP "
+ "method other than those specified is used to access the resource" },
+{ "</LimitExcept>", endlimit_section, (void*)1, OR_ALL, NO_ARGS,
+ "Marks end of <LimitExcept>" },
{ "<IfModule", start_ifmod, NULL, OR_ALL, TAKE1,
"Container for directives based on existance of specified modules" },
{ end_ifmodule_section, end_ifmod, NULL, OR_ALL, NO_ARGS,
@@ -2554,7 +2807,7 @@ static const command_rec core_cmds[] = {
{ "ServerName", set_server_string_slot,
(void *)XtOffsetOf (server_rec, server_hostname), RSRC_CONF, TAKE1,
"The hostname of the server" },
-{ "ServerSignature", set_signature_flag, NULL, ACCESS_CONF|RSRC_CONF, TAKE1,
+{ "ServerSignature", set_signature_flag, NULL, OR_ALL, TAKE1,
"En-/disable server signature (on|off|email)" },
{ "ServerRoot", set_server_root, NULL, RSRC_CONF, TAKE1,
"Common directory of server-related files (logs, confs, etc.)" },
@@ -2589,9 +2842,8 @@ static const command_rec core_cmds[] = {
{ "ContentDigest", set_content_md5, NULL, OR_OPTIONS,
FLAG, "whether or not to send a Content-MD5 header with each request" },
{ "UseCanonicalName", set_use_canonical_name, NULL,
- OR_OPTIONS, FLAG,
- "Whether or not to always use the canonical ServerName : Port when "
- "constructing URLs" },
+ RSRC_CONF, TAKE1,
+ "How to work out the ServerName : Port when constructing URLs" },
{ "StartServers", set_daemons_to_start, NULL, RSRC_CONF, TAKE1,
"Number of child processes launched at server startup" },
{ "MinSpareServers", set_min_free_servers, NULL, RSRC_CONF, TAKE1,
@@ -2656,6 +2908,10 @@ static const command_rec core_cmds[] = {
{ "BS2000Account", set_bs2000_account, NULL, RSRC_CONF, TAKE1,
"Name of server User's bs2000 logon account name" },
#endif
+#ifdef WIN32
+{ "ScriptInterpreterSource", set_interpreter_source, NULL, OR_FILEINFO, TAKE1,
+ "Where to find interpreter to run Win32 scripts (Registry or script shebang line)" },
+#endif
{ "ServerTokens", set_serv_tokens, NULL, RSRC_CONF, TAKE1,
"Determine tokens displayed in the Server: header - Min(imal), OS or Full" },
{ "LimitRequestLine", set_limit_req_line, NULL, RSRC_CONF, TAKE1,
@@ -2668,7 +2924,7 @@ static const command_rec core_cmds[] = {
(void*)XtOffsetOf(core_dir_config, limit_req_body),
OR_ALL, TAKE1,
"Limit (in bytes) on maximum size of request message body" },
-{ NULL },
+{ NULL }
};
/*****************************************************************
@@ -2721,16 +2977,20 @@ static int core_translate(request_rec *r)
static int do_nothing(request_rec *r) { return OK; }
#ifdef USE_MMAP_FILES
-struct mmap {
+struct mmap_rec {
void *mm;
size_t length;
};
static void mmap_cleanup(void *mmv)
{
- struct mmap *mmd = mmv;
+ struct mmap_rec *mmd = mmv;
- munmap(mmd->mm, mmd->length);
+ if (munmap(mmd->mm, mmd->length) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
+ "Failed to munmap memory of length %ld at 0x%lx",
+ (long) mmd->length, (long) mmd->mm);
+ }
}
#endif
@@ -2751,6 +3011,9 @@ static int default_handler(request_rec *r)
#ifdef USE_MMAP_FILES
caddr_t mm;
#endif
+#ifdef CHARSET_EBCDIC
+ int convert_flag;
+#endif
/* This handler has no use for a request body (yet), but we still
* need to read and discard it if the client sent one.
@@ -2815,6 +3078,7 @@ static int default_handler(request_rec *r)
#ifdef USE_MMAP_FILES
ap_block_alarms();
if ((r->finfo.st_size >= MMAP_THRESHOLD)
+ && (r->finfo.st_size < MMAP_LIMIT)
&& (!r->header_only || (d->content_md5 & 1))) {
/* we need to protect ourselves in case we die while we've got the
* file mmapped */
@@ -2833,22 +3097,27 @@ static int default_handler(request_rec *r)
ap_unblock_alarms();
#endif
- if (d->content_md5 & 1) {
- ap_table_setn(r->headers_out, "Content-MD5",
- ap_md5digest(r->pool, f));
- }
-
- rangestatus = ap_set_byterange(r);
#ifdef CHARSET_EBCDIC
- /* To make serving of "raw ASCII text" files easy (they serve faster
+ /* To make serving of "raw ASCII text" files easy (they serve faster
* since they don't have to be converted from EBCDIC), a new
* "magic" type prefix was invented: text/x-ascii-{plain,html,...}
* If we detect one of these content types here, we simply correct
* the type to the real text/{plain,html,...} type. Otherwise, we
* set a flag that translation is required later on.
*/
- ap_checkconv(r);
-#endif /*CHARSET_EBCDIC*/
+ convert_flag = ap_checkconv(r);
+ if (d->content_md5 & 1) {
+ ap_table_setn(r->headers_out, "Content-MD5",
+ ap_md5digest(r->pool, f, convert_flag));
+ }
+#else
+ if (d->content_md5 & 1) {
+ ap_table_setn(r->headers_out, "Content-MD5",
+ ap_md5digest(r->pool, f));
+ }
+#endif /* CHARSET_EBCDIC */
+
+ rangestatus = ap_set_byterange(r);
ap_send_http_header(r);
@@ -2859,8 +3128,18 @@ static int default_handler(request_rec *r)
else {
long offset, length;
while (ap_each_byterange(r, &offset, &length)) {
- fseek(f, offset, SEEK_SET);
- ap_send_fd_length(f, r, length);
+ /*
+ * Non zero returns are more portable than checking
+ * for a return of -1.
+ */
+ if (fseek(f, offset, SEEK_SET)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "Failed to fseek for byterange (%ld, %ld)",
+ offset, length);
+ }
+ else {
+ ap_send_fd_length(f, r, length);
+ }
}
}
}
@@ -2868,7 +3147,7 @@ static int default_handler(request_rec *r)
#ifdef USE_MMAP_FILES
}
else {
- struct mmap *mmd;
+ struct mmap_rec *mmd;
mmd = ap_palloc(r->pool, sizeof(*mmd));
mmd->mm = mm;
@@ -2880,7 +3159,7 @@ static int default_handler(request_rec *r)
AP_MD5_CTX context;
ap_MD5Init(&context);
- ap_MD5Update(&context, (void *)mm, r->finfo.st_size);
+ ap_MD5Update(&context, (void *)mm, (unsigned int)r->finfo.st_size);
ap_table_setn(r->headers_out, "Content-MD5",
ap_md5contextTo64(r->pool, &context));
}
@@ -2909,7 +3188,7 @@ static int default_handler(request_rec *r)
static const handler_rec core_handlers[] = {
{ "*/*", default_handler },
{ "default-handler", default_handler },
-{ NULL }
+{ NULL, NULL }
};
API_VAR_EXPORT module core_module = {
diff --git a/usr.sbin/httpd/src/main/http_log.c b/usr.sbin/httpd/src/main/http_log.c
index 02424e748e4..7a1e0ea5d0c 100644
--- a/usr.sbin/httpd/src/main/http_log.c
+++ b/usr.sbin/httpd/src/main/http_log.c
@@ -172,8 +172,10 @@ static int error_log_child(void *cmd, child_info *pinfo)
child_pid = spawnl(_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
return(child_pid);
#elif defined(OS2)
- /* For OS/2 we need to use a '/' */
- execl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
+ /* For OS/2 we need to use a '/' and spawn the child rather than exec as
+ * we haven't forked */
+ child_pid = spawnl(P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
+ return(child_pid);
#else
execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
#endif
@@ -188,9 +190,17 @@ static void open_error_log(server_rec *s, pool *p)
if (*s->error_fname == '|') {
FILE *dummy;
-
+#ifdef TPF
+ TPF_FORK_CHILD cld;
+ cld.filename = s->error_fname+1;
+ cld.subprocess_env = NULL;
+ cld.prog_type = FORK_NAME;
+ if (!ap_spawn_child(p, NULL, &cld,
+ kill_after_timeout, &dummy, NULL, NULL)) {
+#else
if (!ap_spawn_child(p, error_log_child, (void *)(s->error_fname+1),
kill_after_timeout, &dummy, NULL, NULL)) {
+#endif /* TPF */
perror("ap_spawn_child");
fprintf(stderr, "Couldn't fork child for ErrorLog process\n");
exit(1);
@@ -311,6 +321,18 @@ static void log_error_core(const char *file, int line, int level,
return;
logf = s->error_log;
}
+#ifdef TPF
+ else if (tpf_child) {
+ /*
+ * If we are doing normal logging, don't log messages that are
+ * above the server log level unless it is a startup/shutdown notice
+ */
+ if (((level & APLOG_LEVELMASK) != APLOG_NOTICE) &&
+ ((level & APLOG_LEVELMASK) > s->loglevel))
+ return;
+ logf = stderr;
+ }
+#endif /* TPF */
else {
/*
* If we are doing syslog logging, don't log messages that are
@@ -322,8 +344,7 @@ static void log_error_core(const char *file, int line, int level,
}
if (logf) {
- len = ap_snprintf(errstr, sizeof(errstr), "%s: [%s] ",
- ap_server_argv0, ap_get_time());
+ len = ap_snprintf(errstr, sizeof(errstr), "[%s] ", ap_get_time());
} else {
len = 0;
}
@@ -331,6 +352,7 @@ static void log_error_core(const char *file, int line, int level,
len += ap_snprintf(errstr + len, sizeof(errstr) - len,
"[%s] ", priorities[level & APLOG_LEVELMASK].t_name);
+#ifndef TPF
if (file && (level & APLOG_LEVELMASK) == APLOG_DEBUG) {
#ifdef _OSD_POSIX
char tmp[256];
@@ -353,6 +375,7 @@ static void log_error_core(const char *file, int line, int level,
len += ap_snprintf(errstr + len, sizeof(errstr) - len,
"%s(%d): ", file, line);
}
+#endif /* TPF */
if (r) {
/* XXX: TODO: add a method of selecting whether logged client
* addresses are in dotted quad or resolved form... dotted
@@ -456,6 +479,8 @@ API_EXPORT(void) ap_log_rerror(const char *file, int line, int level,
* something, even an empty string, into the "error-notes" cell
* before calling this routine.
*/
+ va_end(args);
+ va_start(args,fmt);
if (((level & APLOG_LEVELMASK) <= APLOG_WARNING)
&& (ap_table_get(r->notes, "error-notes") == NULL)) {
ap_table_setn(r->notes, "error-notes",
@@ -704,8 +729,10 @@ static int piped_log_child(void *cmd, child_info *pinfo)
child_pid = spawnl(_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
return(child_pid);
#elif defined(OS2)
- /* For OS/2 we need to use a '/' */
- execl (SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
+ /* For OS/2 we need to use a '/' and spawn the child rather than exec as
+ * we haven't forked */
+ child_pid = spawnl(P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
+ return(child_pid);
#else
execl (SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
#endif
@@ -719,9 +746,18 @@ API_EXPORT(piped_log *) ap_open_piped_log(pool *p, const char *program)
{
piped_log *pl;
FILE *dummy;
-
+#ifdef TPF
+ TPF_FORK_CHILD cld;
+ cld.filename = (char *)program;
+ cld.subprocess_env = NULL;
+ cld.prog_type = FORK_NAME;
+
+ if (!ap_spawn_child (p, NULL, &cld,
+ kill_after_timeout, &dummy, NULL, NULL)){
+#else
if (!ap_spawn_child(p, piped_log_child, (void *)program,
kill_after_timeout, &dummy, NULL, NULL)) {
+#endif /* TPF */
perror("ap_spawn_child");
fprintf(stderr, "Couldn't fork child for piped log process\n");
exit (1);
diff --git a/usr.sbin/httpd/src/main/http_main.c b/usr.sbin/httpd/src/main/http_main.c
index c197baa2191..469b3ebd8d9 100644
--- a/usr.sbin/httpd/src/main/http_main.c
+++ b/usr.sbin/httpd/src/main/http_main.c
@@ -180,6 +180,10 @@ void ap_force_library_loading(void) {
#ifdef WIN32
#include "../os/win32/service.h"
#include "../os/win32/registry.h"
+#define DEFAULTSERVICENAME "Apache"
+#define PATHSEPARATOR '\\'
+#else
+#define PATHSEPARATOR '/'
#endif
@@ -225,26 +229,28 @@ void *ap_dummy_mutex = &ap_dummy_mutex;
* for the most part the only code that acts on 'em. (Hmmm... mod_main.c?)
*/
-int ap_standalone;
-uid_t ap_user_id;
-char *ap_user_name;
-gid_t ap_group_id;
+int ap_standalone=0;
+int ap_configtestonly=0;
+int ap_docrootcheck=1;
+uid_t ap_user_id=0;
+char *ap_user_name=NULL;
+gid_t ap_group_id=0;
#ifdef MULTIPLE_GROUPS
gid_t group_id_list[NGROUPS_MAX];
#endif
-int ap_max_requests_per_child;
-int ap_threads_per_child;
-int ap_excess_requests_per_child;
-char *ap_pid_fname;
-char *ap_scoreboard_fname;
+int ap_max_requests_per_child=0;
+int ap_threads_per_child=0;
+int ap_excess_requests_per_child=0;
+char *ap_pid_fname=NULL;
+char *ap_scoreboard_fname=NULL;
char *ap_lock_fname;
-char *ap_server_argv0;
+char *ap_server_argv0=NULL;
struct in_addr ap_bind_address;
-int ap_daemons_to_start;
-int ap_daemons_min_free;
-int ap_daemons_max_free;
-int ap_daemons_limit;
-time_t ap_restart_time;
+int ap_daemons_to_start=0;
+int ap_daemons_min_free=0;
+int ap_daemons_max_free=0;
+int ap_daemons_limit=0;
+time_t ap_restart_time=0;
int ap_suexec_enabled = 0;
int ap_listenbacklog;
int ap_dump_settings = 0;
@@ -280,8 +286,8 @@ static int max_daemons_limit = -1;
listen_rec *ap_listeners;
static listen_rec *head_listener;
-API_VAR_EXPORT char ap_server_root[MAX_STRING_LEN];
-char ap_server_confname[MAX_STRING_LEN];
+API_VAR_EXPORT char ap_server_root[MAX_STRING_LEN]="";
+char ap_server_confname[MAX_STRING_LEN]="";
char ap_coredump_dir[MAX_STRING_LEN];
array_header *ap_server_pre_read_config;
@@ -332,7 +338,9 @@ struct other_child_rec {
static other_child_rec *other_children;
#endif
+static pool *pglobal; /* Global pool */
static pool *pconf; /* Pool for config stuff */
+static pool *plog; /* Pool for error-logging files */
static pool *ptrans; /* Pool for per-transaction stuff */
static pool *pchild; /* Pool for httpd child stuff */
static pool *pcommands; /* Pool for -C and -c switches */
@@ -342,6 +350,11 @@ static int APACHE_TLS my_pid; /* it seems silly to call getpid all the time */
static int my_child_num;
#endif
+#ifdef TPF
+int tpf_child = 0;
+char tpf_server_name[INETD_SERVNAME_LENGTH+1];
+#endif /* TPF */
+
scoreboard *ap_scoreboard_image = NULL;
/*
@@ -424,6 +437,20 @@ API_EXPORT(void) ap_add_config_define(const char *define)
*var = ap_pstrdup(pcommands, define);
return;
}
+
+/*
+ * Invoke the `close_connection' hook of modules to let them do
+ * some connection dependent actions before we close it.
+ */
+static void ap_call_close_connection_hook(conn_rec *c)
+{
+ module *m;
+ for (m = top_module; m != NULL; m = m->next)
+ if (m->magic == MODULE_MAGIC_COOKIE_EAPI)
+ if (m->close_connection != NULL)
+ (*m->close_connection)(c);
+ return;
+}
#endif /* EAPI */
static APACHE_TLS int volatile exit_after_unblock = 0;
@@ -745,17 +772,21 @@ static void accept_mutex_init(pool *p)
static void accept_mutex_on(void)
{
- if (semop(sem_id, &op_on, 1) < 0) {
- perror("accept_mutex_on");
- clean_child_exit(APEXIT_CHILDFATAL);
+ while (semop(sem_id, &op_on, 1) < 0) {
+ if (errno != EINTR) {
+ perror("accept_mutex_on");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
}
}
static void accept_mutex_off(void)
{
- if (semop(sem_id, &op_off, 1) < 0) {
- perror("accept_mutex_off");
- clean_child_exit(APEXIT_CHILDFATAL);
+ while (semop(sem_id, &op_off, 1) < 0) {
+ if (errno != EINTR) {
+ perror("accept_mutex_off");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
}
}
@@ -911,9 +942,11 @@ static void accept_mutex_child_init(pool *p)
int rc = DosOpenMutexSem(NULL, &lock_sem);
if (rc != 0) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
- "Child cannot open lock semaphore");
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
+ "Child cannot open lock semaphore, rc=%d", rc);
clean_child_exit(APEXIT_CHILDINIT);
+ } else {
+ ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
}
}
@@ -926,8 +959,8 @@ static void accept_mutex_init(pool *p)
int rc = DosCreateMutexSem(NULL, &lock_sem, DC_SEM_SHARED, FALSE);
if (rc != 0) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
- "Parent cannot create lock semaphore");
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
+ "Parent cannot create lock semaphore, rc=%d", rc);
exit(APEXIT_INIT);
}
@@ -939,7 +972,7 @@ static void accept_mutex_on(void)
int rc = DosRequestMutexSem(lock_sem, SEM_INDEFINITE_WAIT);
if (rc != 0) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
"OS2SEM: Error %d getting accept lock. Exiting!", rc);
clean_child_exit(APEXIT_CHILDFATAL);
}
@@ -950,12 +983,44 @@ static void accept_mutex_off(void)
int rc = DosReleaseMutexSem(lock_sem);
if (rc != 0) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
"OS2SEM: Error %d freeing accept lock. Exiting!", rc);
clean_child_exit(APEXIT_CHILDFATAL);
}
}
+#elif defined(USE_TPF_CORE_SERIALIZED_ACCEPT)
+
+static int tpf_core_held;
+
+static void accept_mutex_cleanup(void *foo)
+{
+ if(tpf_core_held)
+ coruc(RESOURCE_KEY);
+}
+
+#define accept_mutex_init(x)
+
+static void accept_mutex_child_init(pool *p)
+{
+ ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
+ tpf_core_held = 0;
+}
+
+static void accept_mutex_on(void)
+{
+ corhc(RESOURCE_KEY);
+ tpf_core_held = 1;
+ ap_check_signals();
+}
+
+static void accept_mutex_off(void)
+{
+ coruc(RESOURCE_KEY);
+ tpf_core_held = 0;
+ ap_check_signals();
+}
+
#else
/* Default --- no serialization. Other methods *could* go here,
* as #elifs...
@@ -991,12 +1056,15 @@ static void usage(char *bin)
pad[i] = ' ';
pad[i] = '\0';
#ifdef SHARED_CORE
- fprintf(stderr, "Usage: %s [-R directory] [-d directory] [-f file]\n", bin);
+ fprintf(stderr, "Usage: %s [-R directory] [-D name] [-d directory] [-f file]\n", bin);
#else
- fprintf(stderr, "Usage: %s [-d directory] [-f file]\n", bin);
+ fprintf(stderr, "Usage: %s [-D name] [-d directory] [-f file]\n", bin);
#endif
fprintf(stderr, " %s [-C \"directive\"] [-c \"directive\"]\n", pad);
- fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t]\n", pad);
+ fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t] [-T]\n", pad);
+#ifdef WIN32
+ fprintf(stderr, " %s [-n service] [-k signal] [-i] [-u]\n", pad);
+#endif
fprintf(stderr, "Options:\n");
#ifdef SHARED_CORE
fprintf(stderr, " -R directory : specify an alternate location for shared object files\n");
@@ -1012,10 +1080,15 @@ static void usage(char *bin)
fprintf(stderr, " -l : list compiled-in modules\n");
fprintf(stderr, " -L : list available configuration directives\n");
fprintf(stderr, " -S : show parsed settings (currently only vhost settings)\n");
- fprintf(stderr, " -t : run syntax test for configuration files only\n");
+ fprintf(stderr, " -t : run syntax check for config files (with docroot check)\n");
+ fprintf(stderr, " -T : run syntax check for config files (without docroot check)\n");
#ifdef WIN32
+ fprintf(stderr, " -n name : set service name and use its ServerConfigFile\n");
fprintf(stderr, " -k shutdown : tell running Apache to shutdown\n");
fprintf(stderr, " -k restart : tell running Apache to do a graceful restart\n");
+ fprintf(stderr, " -k start : tell Apache to start\n");
+ fprintf(stderr, " -i : install an Apache service\n");
+ fprintf(stderr, " -u : uninstall an Apache service\n");
#endif
exit(1);
}
@@ -1034,10 +1107,9 @@ static APACHE_TLS int volatile alarms_blocked = 0;
static APACHE_TLS int volatile alarm_pending = 0;
static void timeout(int sig)
-{ /* Also called on SIGPIPE */
+{
void *dirconf;
- signal(SIGPIPE, SIG_IGN); /* Block SIGPIPE */
if (alarms_blocked) {
alarm_pending = 1;
return;
@@ -1055,20 +1127,10 @@ static void timeout(int sig)
else
dirconf = current_conn->server->lookup_defaults;
if (!current_conn->keptalive) {
- if (sig == SIGPIPE) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
- current_conn->server,
- "[client %s] stopped connection before %s completed",
- current_conn->remote_ip,
- timeout_name ? timeout_name : "request");
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
- current_conn->server,
- "[client %s] %s timed out",
- current_conn->remote_ip,
- timeout_name ? timeout_name : "request");
- }
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
+ current_conn->server, "[client %s] %s timed out",
+ current_conn->remote_ip,
+ timeout_name ? timeout_name : "request");
}
if (timeout_req) {
@@ -1092,8 +1154,17 @@ static void timeout(int sig)
log_req = log_req->prev;
}
- if (!current_conn->keptalive)
+ if (!current_conn->keptalive) {
+ /* in some cases we come here before setting the time */
+ if (log_req->request_time == 0) {
+ log_req->request_time = time(0);
+ }
ap_log_transaction(log_req);
+ }
+
+#ifdef EAPI
+ ap_call_close_connection_hook(save_req->connection);
+#endif /* EAPI */
ap_bsetflag(save_req->connection->client, B_EOUT, 1);
ap_bclose(save_req->connection->client);
@@ -1104,6 +1175,9 @@ static void timeout(int sig)
ap_longjmp(jmpbuffer, 1);
}
else { /* abort the connection */
+#ifdef EAPI
+ ap_call_close_connection_hook(current_conn);
+#endif /* EAPI */
ap_bsetflag(current_conn->client, B_EOUT, 1);
ap_bclose(current_conn->client);
current_conn->aborted = 1;
@@ -1196,6 +1270,7 @@ unsigned int ap_set_callback_and_alarm(void (*fn) (int), int x)
/* Just note the timeout in our scoreboard, no need to call the system.
* We also note that the virtual time has gone forward.
*/
+ ap_check_signals();
old = ap_scoreboard_image->servers[my_child_num].timeout_len;
ap_scoreboard_image->servers[my_child_num].timeout_len = x;
++ap_scoreboard_image->servers[my_child_num].cur_vtime;
@@ -1281,6 +1356,7 @@ API_EXPORT(void) ap_soft_timeout(char *name, request_rec *r)
API_EXPORT(void) ap_kill_timeout(request_rec *dummy)
{
+ ap_check_signals();
ap_set_callback_and_alarm(NULL, 0);
timeout_req = NULL;
timeout_name = NULL;
@@ -1379,10 +1455,16 @@ static void lingering_close(request_rec *r)
/* Send any leftover data to the client, but never try to again */
if (ap_bflush(r->connection->client) == -1) {
+#ifdef EAPI
+ ap_call_close_connection_hook(r->connection);
+#endif /* EAPI */
ap_kill_timeout(r);
ap_bclose(r->connection->client);
return;
}
+#ifdef EAPI
+ ap_call_close_connection_hook(r->connection);
+#endif /* EAPI */
ap_bsetflag(r->connection->client, B_EOUT, 1);
/* Close our half of the connection --- send the client a FIN */
@@ -1561,6 +1643,9 @@ static void reinit_scoreboard(pool *p)
{
ap_assert(!ap_scoreboard_image);
ap_scoreboard_image = (scoreboard *) malloc(SCOREBOARD_SIZE);
+ if (ap_scoreboard_image == NULL) {
+ fprintf(stderr, "Ouch! Out of memory reiniting scoreboard!\n");
+ }
memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
}
@@ -1908,6 +1993,37 @@ static void reopen_scoreboard(pool *p)
{
}
+#elif defined(USE_TPF_SCOREBOARD)
+
+static void cleanup_scoreboard_heap()
+{
+ int rv;
+ rv = rsysc(ap_scoreboard_image, SCOREBOARD_FRAMES, SCOREBOARD_NAME);
+ if(rv == RSYSC_ERROR) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "rsysc() could not release scoreboard system heap");
+ }
+}
+
+static void setup_shared_mem(pool *p)
+{
+ cinfc(CINFC_WRITE, CINFC_CMMCTK2);
+ ap_scoreboard_image = (scoreboard *) gsysc(SCOREBOARD_FRAMES, SCOREBOARD_NAME);
+
+ if (!ap_scoreboard_image) {
+ fprintf(stderr, "httpd: Could not create scoreboard system heap storage.\n");
+ exit(APEXIT_INIT);
+ }
+
+ ap_register_cleanup(p, NULL, cleanup_scoreboard_heap, ap_null_cleanup);
+ ap_scoreboard_image->global.running_generation = 0;
+}
+
+static void reopen_scoreboard(pool *p)
+{
+ cinfc(CINFC_WRITE, CINFC_CMMCTK2);
+}
+
#else
#define SCOREBOARD_FILE
static scoreboard _scoreboard_image;
@@ -1956,6 +2072,9 @@ void reopen_scoreboard(pool *p)
if (scoreboard_fd != -1)
ap_pclosef(p, scoreboard_fd);
+#ifdef TPF
+ ap_scoreboard_fname = ap_server_root_relative(p, ap_scoreboard_fname);
+#endif /* TPF */
scoreboard_fd = ap_popenf(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0666);
if (scoreboard_fd == -1) {
perror(ap_scoreboard_fname);
@@ -2036,7 +2155,10 @@ static void clean_parent_exit(int code) __attribute__((noreturn));
static void clean_parent_exit(int code)
{
/* Clear the pool - including any registered cleanups */
- ap_destroy_pool(pconf);
+ ap_destroy_pool(pglobal);
+#ifdef EAPI
+ ap_kill_alloc_shared();
+#endif
exit(code);
}
@@ -2048,6 +2170,8 @@ int ap_update_child_status(int child_num, int status, request_rec *r)
if (child_num < 0)
return -1;
+ ap_check_signals();
+
ap_sync_scoreboard_image();
ss = &ap_scoreboard_image->servers[child_num];
old_status = ss->status;
@@ -2585,7 +2709,7 @@ static void usr1_handler(int sig)
static int volatile shutdown_pending;
static int volatile restart_pending;
static int volatile is_graceful;
-ap_generation_t volatile ap_my_generation;
+ap_generation_t volatile ap_my_generation=0;
#ifdef WIN32
/*
@@ -2771,6 +2895,11 @@ static void set_signals(void)
if (sigaction(SIGXFSZ, &sa, NULL) < 0)
ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGXFSZ)");
#endif
+#ifdef SIGPIPE
+ sa.sa_handler = SIG_IGN;
+ if (sigaction(SIGPIPE, &sa, NULL) < 0)
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGPIPE)");
+#endif
/* we want to ignore HUPs and USR1 while we're busy processing one */
sigaddset(&sa.sa_mask, SIGHUP);
@@ -2810,6 +2939,10 @@ static void set_signals(void)
#ifdef SIGUSR1
signal(SIGUSR1, restart);
#endif /* SIGUSR1 */
+#ifdef SIGPIPE
+ signal(SIGPIPE, SIG_IGN);
+#endif /* SIGPIPE */
+
#endif
}
@@ -2849,7 +2982,7 @@ static void detach(void)
exit(1);
}
#elif defined(OS2) || defined(TPF)
- /* OS/2 don't support process group IDs */
+ /* OS/2 and TPF don't support process group IDs */
pgrp = getpid();
#elif defined(MPE)
/* MPE uses negative pid for process group */
@@ -2915,8 +3048,19 @@ static void set_group_privs(void)
else
name = ap_user_name;
-#ifndef OS2
- /* OS/2 dosen't support groups. */
+#if !defined(OS2) && !defined(TPF)
+ /* OS/2 and TPF don't support groups. */
+
+ /*
+ * Set the GID before initgroups(), since on some platforms
+ * setgid() is known to zap the group list.
+ */
+ if (setgid(ap_group_id) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
+ "setgid: unable to set group id to Group %u",
+ (unsigned)ap_group_id);
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
/* Reset `groups' attributes. */
@@ -2932,14 +3076,8 @@ static void set_group_privs(void)
"getgroups: unable to get group list");
clean_child_exit(APEXIT_CHILDFATAL);
}
-#endif
- if (setgid(ap_group_id) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
- "setgid: unable to set group id to Group %u",
- (unsigned)ap_group_id);
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-#endif
+#endif /* MULTIPLE_GROUPS */
+#endif /* !defined(OS2) && !defined(TPF) */
}
#endif /* ndef WIN32 */
}
@@ -2980,6 +3118,8 @@ static conn_rec *new_connection(pool *p, server_rec *server, BUFF *inout,
conn->pool = p;
conn->local_addr = *saddr;
+ conn->local_ip = ap_pstrdup(conn->pool,
+ inet_ntoa(conn->local_addr.sin_addr));
conn->server = server; /* just a guess for now */
ap_update_vhost_given_ip(conn);
conn->base_server = conn->server;
@@ -3010,7 +3150,7 @@ static conn_rec *new_connection(pool *p, server_rec *server, BUFF *inout,
return conn;
}
-#if defined(TCP_NODELAY) && !defined(MPE)
+#if defined(TCP_NODELAY) && !defined(MPE) && !defined(TPF)
static void sock_disable_nagle(int s)
{
/* The Nagle algorithm says that we should delay sending partial
@@ -3077,9 +3217,14 @@ static int make_sock(pool *p, const struct sockaddr_in *server)
#endif
#ifndef WORKAROUND_SOLARIS_BUG
+#ifndef BEOS /* this won't work for BeOS sockets!! */
s = ap_slack(s, AP_SLACK_HIGH);
+#endif
ap_note_cleanups_for_socket(p, s); /* arrange to close on exec or restart */
+#ifdef TPF
+ os_note_additional_cleanups(p, s);
+#endif /* TPF */
#endif
#ifndef MPE
@@ -3088,18 +3233,26 @@ static int make_sock(pool *p, const struct sockaddr_in *server)
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(int)) < 0) {
ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
"make_sock: for %s, setsockopt: (SO_REUSEADDR)", addr);
+#ifdef BEOS
+ closesocket(s);
+#else
close(s);
+#endif
ap_unblock_alarms();
return -1;
}
#endif /*_OSD_POSIX*/
one = 1;
-#ifndef BEOS
-/* BeOS does not support SO_KEEPALIVE */
+#ifdef SO_KEEPALIVE
if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(int)) < 0) {
ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
"make_sock: for %s, setsockopt: (SO_KEEPALIVE)", addr);
+#ifdef BEOS
+ closesocket(s);
+#else
close(s);
+#endif
+
ap_unblock_alarms();
return -1;
}
@@ -3145,6 +3298,7 @@ static int make_sock(pool *p, const struct sockaddr_in *server)
if (ntohs(server->sin_port) < 1024)
GETPRIVMODE();
#endif
+
if (bind(s, (struct sockaddr *) server, sizeof(struct sockaddr_in)) == -1) {
ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
"make_sock: could not bind to %s", addr);
@@ -3152,7 +3306,12 @@ static int make_sock(pool *p, const struct sockaddr_in *server)
if (ntohs(server->sin_port) < 1024)
GETUSERMODE();
#endif
+
+#ifdef BEOS
+ closesocket(s);
+#else
close(s);
+#endif
ap_unblock_alarms();
exit(1);
}
@@ -3164,7 +3323,11 @@ static int make_sock(pool *p, const struct sockaddr_in *server)
if (listen(s, ap_listenbacklog) == -1) {
ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
"make_sock: unable to listen for connections on %s", addr);
+#ifdef BEOS
+ closesocket(s);
+#else
close(s);
+#endif
ap_unblock_alarms();
exit(1);
}
@@ -3176,7 +3339,7 @@ static int make_sock(pool *p, const struct sockaddr_in *server)
#endif
ap_unblock_alarms();
-#ifndef WIN32
+#ifdef CHECK_FD_SETSIZE
/* protect various fd_sets */
if (s >= FD_SETSIZE) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
@@ -3184,7 +3347,11 @@ static int make_sock(pool *p, const struct sockaddr_in *server)
"larger than FD_SETSIZE (%u) "
"found, you probably need to rebuild Apache with a "
"larger FD_SETSIZE", addr, s, FD_SETSIZE);
+#ifdef BEOS
+ closesocket(s);
+#else
close(s);
+#endif
return -1;
}
#endif
@@ -3379,6 +3546,9 @@ static void show_compile_settings(void)
#ifdef EAPI
printf(" -D EAPI\n");
#endif
+#ifdef EAPI_MM
+ printf(" -D EAPI_MM\n");
+#endif
#ifdef BIG_SECURITY_HOLE
printf(" -D BIG_SECURITY_HOLE\n");
#endif
@@ -3465,7 +3635,7 @@ static void show_compile_settings(void)
#ifdef SUEXEC_BIN
printf(" -D SUEXEC_BIN=\"" SUEXEC_BIN "\"\n");
#endif
-#ifdef SHARED_CORE_DIR
+#if defined(SHARED_CORE) && defined(SHARED_CORE_DIR)
printf(" -D SHARED_CORE_DIR=\"" SHARED_CORE_DIR "\"\n");
#endif
#ifdef DEFAULT_PIDLOG
@@ -3514,7 +3684,9 @@ static void common_init(void)
AMCSocketInitialize();
#endif /* WIN32 */
- pconf = ap_init_alloc();
+ pglobal = ap_init_alloc();
+ pconf = ap_make_sub_pool(pglobal);
+ plog = ap_make_sub_pool(pglobal);
ptrans = ap_make_sub_pool(pconf);
ap_util_init();
@@ -3603,7 +3775,7 @@ static void child_main(int child_num_arg)
if (setuid(ap_user_id) == -1) {
GETUSERMODE();
ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
- "setuid: unable to change uid");
+ "setuid: unable to change to uid: %d", ap_user_id);
exit(1);
}
GETUSERMODE();
@@ -3616,7 +3788,7 @@ static void child_main(int child_num_arg)
#endif
setuid(ap_user_id) == -1)) {
ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
- "setuid: unable to change uid");
+ "setuid: unable to change to uid: %ld", (long) ap_user_id);
clean_child_exit(APEXIT_CHILDFATAL);
}
#endif
@@ -3629,8 +3801,7 @@ static void child_main(int child_num_arg)
(void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
/*
- * Setup the jump buffers so that we can return here after
- * a signal or a timeout (yeah, I know, same thing).
+ * Setup the jump buffers so that we can return here after a timeout
*/
ap_setjmp(jmpbuffer);
#ifndef OS2
@@ -3638,8 +3809,12 @@ static void child_main(int child_num_arg)
signal(SIGURG, timeout);
#endif
#endif
- signal(SIGPIPE, timeout);
signal(SIGALRM, alrm_handler);
+#ifdef TPF
+ signal(SIGHUP, just_die);
+ signal(SIGTERM, just_die);
+ signal(SIGUSR1, just_die);
+#endif /* TPF */
#ifdef OS2
/* Stop Ctrl-C/Ctrl-Break signals going to child processes */
@@ -3676,7 +3851,7 @@ static void child_main(int child_num_arg)
#ifndef WIN32
if ((ap_max_requests_per_child > 0
- && ++requests_this_child >= ap_max_requests_per_child)) {
+ && requests_this_child++ >= ap_max_requests_per_child)) {
clean_child_exit(0);
}
#else
@@ -3729,7 +3904,7 @@ static void child_main(int child_num_arg)
usr1_just_die = 0;
for (;;) {
clen = sizeof(sa_client);
- csd = accept(sd, &sa_client, &clen);
+ csd = ap_accept(sd, &sa_client, &clen);
if (csd >= 0 || errno != EINTR)
break;
if (deferred_die) {
@@ -3793,11 +3968,43 @@ static void child_main(int child_num_arg)
case ENETUNREACH:
#endif
break;
+#ifdef ENETDOWN
+ case ENETDOWN:
+ /*
+ * When the network layer has been shut down, there
+ * is not much use in simply exiting: the parent
+ * would simply re-create us (and we'd fail again).
+ * Use the CHILDFATAL code to tear the server down.
+ * @@@ Martin's idea for possible improvement:
+ * A different approach would be to define
+ * a new APEXIT_NETDOWN exit code, the reception
+ * of which would make the parent shutdown all
+ * children, then idle-loop until it detected that
+ * the network is up again, and restart the children.
+ * Ben Hyde noted that temporary ENETDOWN situations
+ * occur in mobile IP.
+ */
+ ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
+ "accept: giving up.");
+ clean_child_exit(APEXIT_CHILDFATAL);
+#endif /*ENETDOWN*/
+#ifdef TPF
+ case EINACT:
+ ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
+ "offload device inactive");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ break;
+ default:
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
+ "select/accept error (%u)", errno);
+ clean_child_exit(APEXIT_CHILDFATAL);
+#else
default:
ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
"accept: (client socket)");
clean_child_exit(1);
+#endif
}
}
@@ -3818,6 +4025,11 @@ static void child_main(int child_num_arg)
SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */
+#ifdef TPF
+ if (csd == 0) /* 0 is invalid socket for TPF */
+ continue;
+#endif
+
/* We've got a socket, let's at least process one request off the
* socket before we accept a graceful restart request.
*/
@@ -3826,6 +4038,7 @@ static void child_main(int child_num_arg)
ap_note_cleanups_for_fd(ptrans, csd);
/* protect various fd_sets */
+#ifdef CHECK_FD_SETSIZE
if (csd >= FD_SETSIZE) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
"[csd] filedescriptor (%u) larger than FD_SETSIZE (%u) "
@@ -3833,6 +4046,7 @@ static void child_main(int child_num_arg)
"larger FD_SETSIZE", csd, FD_SETSIZE);
continue;
}
+#endif
/*
* We now have a connection, so set it up with the appropriate
@@ -3872,6 +4086,7 @@ static void child_main(int child_num_arg)
ap_note_cleanups_for_fd(ptrans, dupped_csd);
/* protect various fd_sets */
+#ifdef CHECK_FD_SETSIZE
if (dupped_csd >= FD_SETSIZE) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
"[dupped_csd] filedescriptor (%u) larger than FD_SETSIZE (%u) "
@@ -3880,6 +4095,7 @@ static void child_main(int child_num_arg)
continue;
}
#endif
+#endif
ap_bpushfd(conn_io, csd, dupped_csd);
current_conn = new_connection(ptrans, server_conf, conn_io,
@@ -3917,6 +4133,9 @@ static void child_main(int child_num_arg)
ap_sync_scoreboard_image();
if (ap_scoreboard_image->global.running_generation != ap_my_generation) {
+#ifdef EAPI
+ ap_call_close_connection_hook(current_conn);
+#endif /* EAPI */
ap_bclose(conn_io);
clean_child_exit(0);
}
@@ -3945,6 +4164,9 @@ static void child_main(int child_num_arg)
*/
#ifdef NO_LINGCLOSE
+#ifdef EAPI
+ ap_call_close_connection_hook(current_conn);
+#endif /* EAPI */
ap_bclose(conn_io); /* just close it */
#else
if (r && r->connection
@@ -3955,6 +4177,9 @@ static void child_main(int child_num_arg)
lingering_close(r);
}
else {
+#ifdef EAPI
+ ap_call_close_connection_hook(current_conn);
+#endif /* EAPI */
ap_bsetflag(conn_io, B_EOUT, 1);
ap_bclose(conn_io);
}
@@ -3962,6 +4187,36 @@ static void child_main(int child_num_arg)
}
}
+#ifdef TPF
+static void reset_tpf_listeners(APACHE_TPF_INPUT *input_parms)
+{
+ int count;
+ listen_rec *lr;
+
+ count = 0;
+ listenmaxfd = -1;
+ FD_ZERO(&listenfds);
+ lr = ap_listeners;
+
+ for(;;) {
+ lr->fd = input_parms->listeners[count];
+ if(lr->fd >= 0) {
+ FD_SET(lr->fd, &listenfds);
+ if(lr->fd > listenmaxfd)
+ listenmaxfd = lr->fd;
+ }
+ if(lr->next == NULL)
+ break;
+ lr = lr->next;
+ count++;
+ }
+ lr->next = ap_listeners;
+ head_listener = ap_listeners;
+ close_unused_listeners();
+}
+
+#endif /* TPF */
+
static int make_child(server_rec *s, int slot, time_t now)
{
int pid;
@@ -3973,7 +4228,9 @@ static int make_child(server_rec *s, int slot, time_t now)
if (one_process) {
signal(SIGHUP, just_die);
signal(SIGINT, just_die);
+#ifdef SIGQUIT
signal(SIGQUIT, SIG_DFL);
+#endif
signal(SIGTERM, just_die);
child_main(slot);
}
@@ -3985,12 +4242,14 @@ static int make_child(server_rec *s, int slot, time_t now)
(void) ap_update_child_status(slot, SERVER_STARTING, (request_rec *) NULL);
-#ifndef _OSD_POSIX
- if ((pid = fork()) == -1) {
-#else /*_OSD_POSIX*/
+#ifdef _OSD_POSIX
/* BS2000 requires a "special" version of fork() before a setuid() call */
- if ((pid = os_fork()) == -1) {
-#endif /*_OSD_POSIX*/
+ if ((pid = os_fork(ap_user_name)) == -1) {
+#elif defined(TPF)
+ if ((pid = os_fork(s, slot)) == -1) {
+#else
+ if ((pid = fork()) == -1) {
+#endif
ap_log_error(APLOG_MARK, APLOG_ERR, s, "fork: Unable to fork new process");
/* fork didn't succeed. Fix the scoreboard or else
@@ -4308,7 +4567,8 @@ static void standalone_main(int argc, char **argv)
server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
setup_listeners(pconf);
- ap_open_logs(server_conf, pconf);
+ ap_clear_pool(plog);
+ ap_open_logs(server_conf, plog);
ap_log_pid(pconf, ap_pid_fname);
ap_set_version(); /* create our server_version string */
ap_init_modules(pconf, server_conf);
@@ -4424,6 +4684,11 @@ static void standalone_main(int argc, char **argv)
}
perform_idle_server_maintenance();
+#ifdef TPF
+ shutdown_pending = os_check_server(tpf_server_name);
+ ap_check_signals();
+ sleep(1);
+#endif /*TPF */
}
if (shutdown_pending) {
@@ -4517,7 +4782,6 @@ extern int optind;
int REALMAIN(int argc, char *argv[])
{
int c;
- int configtestonly = 0;
int sock_in;
int sock_out;
char *s;
@@ -4536,11 +4800,17 @@ int REALMAIN(int argc, char *argv[])
SOCKSinit(argv[0]);
#endif
+#ifdef TPF
+ APACHE_TPF_INPUT input_parms;
+ ecbptr()->ebrout = PRIMECRAS;
+ input_parms = * (APACHE_TPF_INPUT *)(&(ecbptr()->ebw000));
+#endif
+
MONCONTROL(0);
common_init();
- if ((s = strrchr(argv[0], '/')) != NULL) {
+ if ((s = strrchr(argv[0], PATHSEPARATOR)) != NULL) {
ap_server_argv0 = ++s;
}
else {
@@ -4552,9 +4822,8 @@ int REALMAIN(int argc, char *argv[])
ap_setup_prelinked_modules();
-#ifndef TPF
while ((c = getopt(argc, argv,
- "D:C:c:Xd:f:vVlLR:Sth"
+ "D:C:c:xXd:f:vVlLR:StTh"
#ifdef DEBUG_SIGSTOP
"Z:"
#endif
@@ -4597,6 +4866,12 @@ int REALMAIN(int argc, char *argv[])
case 'X':
++one_process; /* Weird debugging mode. */
break;
+#ifdef TPF
+ case 'x':
+ os_tpf_child(&input_parms);
+ set_signals();
+ break;
+#endif
#ifdef DEBUG_SIGSTOP
case 'Z':
raise_sigstop_flags = atoi(optarg);
@@ -4615,7 +4890,12 @@ int REALMAIN(int argc, char *argv[])
ap_dump_settings = 1;
break;
case 't':
- configtestonly = 1;
+ ap_configtestonly = 1;
+ ap_docrootcheck = 1;
+ break;
+ case 'T':
+ ap_configtestonly = 1;
+ ap_docrootcheck = 0;
break;
case 'h':
usage(argv[0]);
@@ -4623,12 +4903,18 @@ int REALMAIN(int argc, char *argv[])
usage(argv[0]);
}
}
-#endif /* TPF */
+#ifdef EAPI
+ ap_init_alloc_shared(TRUE);
+#endif
ap_suexec_enabled = init_suexec();
server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
- if (configtestonly) {
+#ifdef EAPI
+ ap_init_alloc_shared(FALSE);
+#endif
+
+ if (ap_configtestonly) {
fprintf(stderr, "Syntax OK\n");
exit(0);
}
@@ -4638,13 +4924,40 @@ int REALMAIN(int argc, char *argv[])
child_timeouts = !ap_standalone || one_process;
+#ifndef TPF
if (ap_standalone) {
- ap_open_logs(server_conf, pconf);
+ ap_open_logs(server_conf, plog);
ap_set_version();
ap_init_modules(pconf, server_conf);
version_locked++;
STANDALONE_MAIN(argc, argv);
}
+#else
+ if (ap_standalone) {
+ if(!tpf_child) {
+ memcpy(tpf_server_name, input_parms.inetd_server.servname, INETD_SERVNAME_LENGTH);
+ tpf_server_name[INETD_SERVNAME_LENGTH+1] = '\0';
+ ap_open_logs(server_conf, pconf);
+ }
+ ap_set_version();
+ ap_init_modules(pconf, server_conf);
+ version_locked++;
+ if(tpf_child) {
+ copy_listeners(pconf);
+ reset_tpf_listeners(&input_parms);
+ server_conf->error_log = NULL;
+#ifdef SCOREBOARD_FILE
+ scoreboard_fd = input_parms.scoreboard_fd;
+ ap_scoreboard_image = &_scoreboard_image;
+#else /* must be USE_TPF_SCOREBOARD or USE_SHMGET_SCOREBOARD */
+ ap_scoreboard_image = (scoreboard *)input_parms.scoreboard_heap;
+#endif
+ child_main(input_parms.slot);
+ }
+ else
+ STANDALONE_MAIN(argc, argv);
+ }
+#endif
else {
conn_rec *conn;
request_rec *r;
@@ -4656,7 +4969,7 @@ int REALMAIN(int argc, char *argv[])
/* Yes this is called twice. */
ap_init_modules(pconf, server_conf);
version_locked++;
- ap_open_logs(server_conf, pconf);
+ ap_open_logs(server_conf, plog);
ap_init_modules(pconf, server_conf);
set_group_privs();
@@ -4667,7 +4980,7 @@ int REALMAIN(int argc, char *argv[])
if (setuid(ap_user_id) == -1) {
GETUSERMODE();
ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
- "setuid: unable to change uid");
+ "setuid: unable to change to uid: %d", ap_user_id);
exit(1);
}
GETUSERMODE();
@@ -4676,7 +4989,8 @@ int REALMAIN(int argc, char *argv[])
/* Only try to switch if we're running as root */
if (!geteuid() && setuid(ap_user_id) == -1) {
ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
- "setuid: unable to change uid");
+ "setuid: unable to change to uid: %ld",
+ (long) ap_user_id);
exit(1);
}
#endif
@@ -4685,15 +4999,12 @@ int REALMAIN(int argc, char *argv[])
}
#ifdef TPF
- signal(SIGALRM, alrm_handler);
- ecbptr()->ebrout = PRIMECRAS;
-#endif /* TPF */
-
-#ifdef TPF
/* TPF only passes the incoming socket number from the internet daemon
in ebw000 */
sock_in = * (int*)(&(ecbptr()->ebw000));
sock_out = * (int*)(&(ecbptr()->ebw000));
+/* TPF also needs a signal set for alarm in inetd mode */
+ signal(SIGALRM, alrm_handler);
#elif defined(MPE)
/* HP MPE 5.5 inetd only passes the incoming socket as stdin (fd 0), whereas
HPUX inetd passes the incoming socket as stdin (fd 0) and stdout (fd 1).
@@ -4739,6 +5050,10 @@ int REALMAIN(int argc, char *argv[])
ap_destroy_pool(r->pool);
}
+#ifdef EAPI
+ ap_call_close_connection_hook(conn);
+#endif /* EAPI */
+
ap_bclose(cio);
}
exit(0);
@@ -4863,6 +5178,9 @@ void add_job(int sock)
/* TODO: If too many jobs in queue, sleep, check for problems */
ap_acquire_mutex(allowed_globals.jobmutex);
new_job = (joblist *) malloc(sizeof(joblist));
+ if (new_job == NULL) {
+ fprintf(stderr, "Ouch! Out of memory in add_job()!\n");
+ }
new_job->next = NULL;
new_job->sock = sock;
if (allowed_globals.jobtail != NULL)
@@ -4955,8 +5273,7 @@ static void child_sub_main(int child_num)
(void) ap_update_child_status(child_num, SERVER_READY, (request_rec *) NULL);
/*
- * Setup the jump buffers so that we can return here after
- * a signal or a timeout (yeah, I know, same thing).
+ * Setup the jump buffers so that we can return here after a timeout.
*/
#if defined(USE_LONGJMP)
setjmp(jmpbuffer);
@@ -4975,16 +5292,14 @@ static void child_sub_main(int child_num)
* (Re)initialize this child to a pre-connection state.
*/
- ap_set_callback_and_alarm(NULL, 0); /* Cancel any outstanding alarms. */
- timeout_req = NULL; /* No request in progress */
+ ap_set_callback_and_alarm(NULL, 0); /* Cancel any outstanding alarms */
+ timeout_req = NULL; /* No request in progress */
current_conn = NULL;
-#ifdef SIGPIPE
- signal(SIGPIPE, timeout);
-#endif
ap_clear_pool(ptrans);
- (void) ap_update_child_status(child_num, SERVER_READY, (request_rec *) NULL);
+ (void) ap_update_child_status(child_num, SERVER_READY,
+ (request_rec *) NULL);
/* Get job from the job list. This will block until a job is ready.
* If -1 is returned then the main thread wants us to exit.
@@ -5067,6 +5382,9 @@ static void child_sub_main(int child_num)
ap_kill_cleanups_for_socket(ptrans, csd);
#ifdef NO_LINGCLOSE
+#ifdef EAPI
+ ap_call_close_connection_hook(current_conn);
+#endif /* EAPI */
ap_bclose(conn_io); /* just close it */
#else
if (r && r->connection
@@ -5077,6 +5395,9 @@ static void child_sub_main(int child_num)
lingering_close(r);
}
else {
+#ifdef EAPI
+ ap_call_close_connection_hook(current_conn);
+#endif /* EAPI */
ap_bsetflag(conn_io, B_EOUT, 1);
ap_bclose(conn_io);
}
@@ -5118,7 +5439,7 @@ void cleanup_thread(thread **handles, int *thread_cnt, int thread_to_clean)
* we are restricted to a maximum of 64 threads. This is a simplistic
* routine that will increase this size.
*/
-DWORD wait_for_many_objects(DWORD nCount, CONST HANDLE *lpHandles,
+static DWORD wait_for_many_objects(DWORD nCount, CONST HANDLE *lpHandles,
DWORD dwSeconds)
{
time_t tStopTime;
@@ -5182,6 +5503,71 @@ void setup_signal_names(char *prefix)
APD2("signal prefix %s", signal_name_prefix);
}
+static void setup_inherited_listeners(pool *p)
+{
+ HANDLE pipe;
+ listen_rec *lr;
+ int fd;
+ WSAPROTOCOL_INFO WSAProtocolInfo;
+ DWORD BytesRead;
+
+ /* Open the pipe to the parent process to receive the inherited socket
+ * data. The sockets have been set to listening in the parent process.
+ */
+ pipe = GetStdHandle(STD_INPUT_HANDLE);
+
+ /* Setup the listeners */
+ listenmaxfd = -1;
+ FD_ZERO(&listenfds);
+ lr = ap_listeners;
+
+ FD_ZERO(&listenfds);
+
+ for (;;) {
+ fd = find_listener(lr);
+ if (fd < 0) {
+ if (!ReadFile(pipe,
+ &WSAProtocolInfo, sizeof(WSAPROTOCOL_INFO),
+ &BytesRead,
+ (LPOVERLAPPED) NULL)){
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR|APLOG_CRIT, server_conf,
+ "setup_inherited_listeners: Unable to read socket data from parent");
+ exit(1);
+ }
+ fd = WSASocket(FROM_PROTOCOL_INFO,
+ FROM_PROTOCOL_INFO,
+ FROM_PROTOCOL_INFO,
+ &WSAProtocolInfo,
+ 0,
+ 0);
+ if (fd == INVALID_SOCKET) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR|APLOG_CRIT, server_conf,
+ "setup_inherited_listeners: WSASocket failed to get inherit the socket.");
+ exit(1);
+ }
+ APD2("setup_inherited_listeners: WSASocket() returned socket %d", fd);
+ }
+ else {
+ ap_note_cleanups_for_socket(p, fd);
+ }
+ if (fd >= 0) {
+ FD_SET(fd, &listenfds);
+ if (fd > listenmaxfd)
+ listenmaxfd = fd;
+ }
+ lr->fd = fd;
+ if (lr->next == NULL)
+ break;
+ lr = lr->next;
+ }
+ /* turn the list into a ring */
+ lr->next = ap_listeners;
+ head_listener = ap_listeners;
+ close_unused_listeners();
+ CloseHandle(pipe);
+ return;
+}
+
/*
* worker_main() is main loop for the child process. The loop in
* this function becomes the controlling thread for the actually working
@@ -5203,8 +5589,6 @@ void worker_main(void)
int i;
struct timeval tv;
int wait_time = 1;
- int start_exit = 0;
- int start_mutex_released = 0;
int max_jobs_per_exe;
int max_jobs_after_exit_request;
HANDLE hObjects[2];
@@ -5249,7 +5633,7 @@ void worker_main(void)
rv = WaitForMultipleObjects(2, hObjects, FALSE, INFINITE);
if (rv == WAIT_FAILED) {
ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_WIN32ERROR, server_conf,
- "Waiting for start_mutex or exit_event -- process will exit");
+ "Waiting for start_mutex or exit_event -- process will exit");
ap_destroy_pool(pchild);
cleanup_scoreboard();
@@ -5262,8 +5646,13 @@ void worker_main(void)
exit(0);
}
/* start_mutex obtained, continue into the select() loop */
+ if (one_process) {
+ setup_listeners(pconf);
+ } else {
+ /* Get listeners from the parent process */
+ setup_inherited_listeners(pconf);
+ }
- setup_listeners(pconf);
if (listenmaxfd == -1) {
/* Help, no sockets were made, better log something and exit */
ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_NOERRNO, NULL,
@@ -5306,43 +5695,20 @@ void worker_main(void)
}
while (1) {
-#if SEVERELY_VERBOSE
- APD4("child PID %d: thread_main total_jobs=%d start_exit=%d",
- my_pid, total_jobs, start_exit);
-#endif
- if ((max_jobs_per_exe && (total_jobs > max_jobs_per_exe) && !start_exit)) {
- start_exit = 1;
- wait_time = 1;
- ap_release_mutex(start_mutex);
- start_mutex_released = 1;
- APD2("process PID %d: start mutex released\n", my_pid);
- }
- if (!start_exit) {
- rv = WaitForSingleObject(exit_event, 0);
- ap_assert((rv == WAIT_TIMEOUT) || (rv == WAIT_OBJECT_0));
- if (rv == WAIT_OBJECT_0) {
- APD1("child: exit event signalled, exiting");
- start_exit = 1;
- /* Lets not break yet - we may have threads to clean up */
- /* break;*/
- }
- rv = wait_for_many_objects(nthreads, child_handles, 0);
- ap_assert(rv != WAIT_FAILED);
- if (rv != WAIT_TIMEOUT) {
- rv = rv - WAIT_OBJECT_0;
- ap_assert((rv >= 0) && (rv < nthreads));
- cleanup_thread(child_handles, &nthreads, rv);
- break;
- }
+ if (max_jobs_per_exe && (total_jobs > max_jobs_per_exe)) {
+ /* MaxRequestsPerChild hit...
+ */
+ break;
}
+ /* Always check for the exit event being signaled.
+ */
+ rv = WaitForSingleObject(exit_event, 0);
+ ap_assert((rv == WAIT_TIMEOUT) || (rv == WAIT_OBJECT_0));
+ if (rv == WAIT_OBJECT_0) {
+ APD1("child: exit event signalled, exiting");
+ break;
+ }
-#if 0
- /* Um, this made us exit before all the connections in our
- * listen queue were dealt with.
- */
- if (start_exit && max_jobs_after_exit_request && (count_down-- < 0))
- break;
-#endif
tv.tv_sec = wait_time;
tv.tv_usec = 0;
@@ -5361,7 +5727,7 @@ void worker_main(void)
if (errno != EINTR) {
/* A "real" error occurred, log it and increment the count of
* select errors. This count is used to ensure we don't go into
- * a busy loop of continuour errors.
+ * a busy loop of continuous errors.
*/
ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "select: (listen)");
count_select_errors++;
@@ -5375,10 +5741,7 @@ void worker_main(void)
}
count_select_errors = 0; /* reset count of errors */
if (srv == 0) {
- if (start_exit)
- break;
- else
- continue;
+ continue;
}
{
@@ -5421,9 +5784,7 @@ void worker_main(void)
/* Get ready to shutdown and exit */
allowed_globals.exit_now = 1;
- if (!start_mutex_released) {
- ap_release_mutex(start_mutex);
- }
+ ap_release_mutex(start_mutex);
#ifdef UNGRACEFUL_RESTART
SetEvent(allowed_globals.thread_exit_event);
@@ -5485,59 +5846,6 @@ void worker_main(void)
* returned the error will already have been logged by ap_log_error().
*/
-int create_event_and_spawn(int argc, char **argv, event **ev, int *child_num, char *prefix)
-{
- char buf[40], mod[200];
- int i, rv;
- char **pass_argv = (char **) alloca(sizeof(char *) * (argc + 3));
-
- /* We need an event to tell the child process to kill itself when
- * the parent is doing a shutdown/restart. This will be named
- * apPID_CN where PID is the parent Apache process PID and
- * N is a unique child serial number. prefix contains
- * the "apPID" part. The child will get the name of this
- * event as its -Z command line argument.
- */
- ap_snprintf(buf, sizeof(buf), "%s_C%d", prefix, ++(*child_num));
- _flushall();
- *ev = CreateEvent(NULL, TRUE, FALSE, buf);
- if (!*ev) {
- ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
- "could not create event for child process");
- return -1;
- }
- APD2("create_event_and_spawn(): created process kill event %s", buf);
-
- pass_argv[0] = argv[0];
- pass_argv[1] = "-Z";
- pass_argv[2] = buf;
- for (i = 1; i < argc; i++) {
- pass_argv[i + 2] = argv[i];
- }
- pass_argv[argc + 2] = NULL;
-
- rv = GetModuleFileName(NULL, mod, sizeof(mod));
- if (rv == sizeof(mod)) {
- /* mod[] was not big enough for our pathname */
- ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
- "Internal error: path to Apache process too long");
- return -1;
- }
- if (rv == 0) {
- ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
- "GetModuleFileName() for current process");
- return -1;
- }
- rv = spawnv(_P_NOWAIT, mod, pass_argv);
- if (rv == -1) {
- ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
- "spawn of child process %s failed", mod);
- return -1;
- }
-
- return rv;
-}
-
/**********************************************************************
* master_main - this is the parent (main) process. We create a
* child process to do the work, then sit around waiting for either
@@ -5549,7 +5857,7 @@ int create_event_and_spawn(int argc, char **argv, event **ev, int *child_num, ch
#define MAX_PROCESSES 50 /* must be < MAX_WAIT_OBJECTS-1 */
-void cleanup_process(HANDLE *handles, HANDLE *events, int position, int *processes)
+static void cleanup_process(HANDLE *handles, HANDLE *events, int position, int *processes)
{
int i;
int handle = 0;
@@ -5568,31 +5876,192 @@ void cleanup_process(HANDLE *handles, HANDLE *events, int position, int *process
APD4("cleanup_processes: removed child in slot %d handle %d, max=%d", position, handle, *processes);
}
-int create_process(HANDLE *handles, HANDLE *events, int *processes, int *child_num, char *kill_event_name, int argc, char **argv)
+static int create_process(pool *p, HANDLE *handles, HANDLE *events,
+ int *processes, int *child_num, char *kill_event_name, int argc, char **argv)
{
- int i = *processes;
+
+ int rv, i;
HANDLE kill_event;
- int child_handle;
+ char buf[1024];
+ char exit_event_name[40]; /* apPID_C# */
+ char *pCommand;
- child_handle = create_event_and_spawn(argc, argv, &kill_event, child_num, kill_event_name);
- if (child_handle <= 0) {
- return -1;
+ STARTUPINFO si; /* Filled in prior to call to CreateProcess */
+ PROCESS_INFORMATION pi; /* filled in on call to CreateProces */
+ LPWSAPROTOCOL_INFO lpWSAProtocolInfo;
+ listen_rec *lr;
+ DWORD BytesWritten;
+ HANDLE hPipeRead = NULL;
+ HANDLE hPipeWrite = NULL;
+ SECURITY_ATTRIBUTES sa = {0};
+
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = NULL;
+
+ /* Build the command line. Should look something like this:
+ * C:/apache/bin/apache.exe -Z exit_event -f ap_server_confname
+ * First, get the path to the executable...
+ */
+ rv = GetModuleFileName(NULL, buf, sizeof(buf));
+ if (rv == sizeof(buf)) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: Path to Apache process too long");
+ return -1;
+ } else if (rv == 0) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: GetModuleFileName() returned NULL for current process.");
+ return -1;
}
- handles[i] = (HANDLE)child_handle;
- events[i] = kill_event;
- (*processes)++;
+
+ /* Create the exit event (apPID_C#). Parent signals this event to tell the
+ * child to exit
+ */
+ ap_snprintf(exit_event_name, sizeof(exit_event_name), "%s_C%d", kill_event_name, ++(*child_num));
+ kill_event = CreateEvent(NULL, TRUE, FALSE, exit_event_name);
+ if (!kill_event) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: Could not create exit event for child process");
+ return -1;
+ }
+
+ pCommand = ap_psprintf(p, "\"%s\" -Z %s -f \"%s\"", buf, exit_event_name, ap_server_confname);
- APD4("create_processes: created child in slot %d handle %d, max=%d",
- (*processes)-1, handles[(*processes)-1], *processes);
+ for (i = 1; i < argc; i++) {
+ pCommand = ap_pstrcat(p, pCommand, " ", argv[i], NULL);
+ }
+
+ /* Create a pipe to send socket info to the child */
+ if (!CreatePipe(&hPipeRead, &hPipeWrite, &sa, 0)) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: Unable to create pipe to child process.\n");
+ return -1;
+ }
+
+ /* Give the read in of teh pipe (hPipeRead) to the child as stdin. The
+ * parent will write the socket data to the child on this pipe.
+ */
+ memset(&si, 0, sizeof(si));
+ memset(&pi, 0, sizeof(pi));
+ si.cb = sizeof(si);
+ si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
+ si.wShowWindow = SW_HIDE;
+ si.hStdInput = hPipeRead;
+
+ if (!CreateProcess(NULL, pCommand, NULL, NULL,
+ TRUE, /* Inherit handles */
+ 0, /* Creation flags */
+ NULL, NULL,
+ &si, &pi)) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: Not able to create the child process.");
+ /*
+ * We must close the handles to the new process and its main thread
+ * to prevent handle and memory leaks.
+ */
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+
+ return -1;
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_INFO, server_conf,
+ "Parent: Created child process %d", pi.dwProcessId);
+
+ /* Assume the child process lives. Update the process and event tables */
+ handles[*processes] = pi.hProcess;
+ events[*processes] = kill_event;
+ (*processes)++;
+
+ /* We never store the thread's handle, so close it now. */
+ CloseHandle(pi.hThread);
+
+ /* Run the chain of open sockets. For each socket, duplicate it
+ * for the target process then send the WSAPROTOCOL_INFO
+ * (returned by dup socket) to the child */
+ lr = ap_listeners;
+ while (lr != NULL) {
+ lpWSAProtocolInfo = ap_pcalloc(p, sizeof(WSAPROTOCOL_INFO));
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_INFO, server_conf,
+ "Parent: Duplicating socket %d and sending it to child process %d", lr->fd, pi.dwProcessId);
+ if (WSADuplicateSocket(lr->fd,
+ pi.dwProcessId,
+ lpWSAProtocolInfo) == SOCKET_ERROR) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: WSADuplicateSocket failed for socket %d.", lr->fd );
+ return -1;
+ }
+
+ if (!WriteFile(hPipeWrite, lpWSAProtocolInfo, (DWORD) sizeof(WSAPROTOCOL_INFO),
+ &BytesWritten,
+ (LPOVERLAPPED) NULL)) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: Unable to write duplicated socket %d to the child.", lr->fd );
+ return -1;
+ }
+
+ lr = lr->next;
+ if (lr == ap_listeners)
+ break;
+ }
+ }
+ CloseHandle(hPipeRead);
+ CloseHandle(hPipeWrite);
return 0;
}
+/* To share the semaphores with other processes, we need a NULL ACL
+ * Code from MS KB Q106387
+ */
+
+static PSECURITY_ATTRIBUTES GetNullACL()
+{
+ PSECURITY_DESCRIPTOR pSD;
+ PSECURITY_ATTRIBUTES sa;
+
+ sa = (PSECURITY_ATTRIBUTES) LocalAlloc(LPTR, sizeof(SECURITY_ATTRIBUTES));
+ pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,
+ SECURITY_DESCRIPTOR_MIN_LENGTH);
+ if (pSD == NULL || sa == NULL) {
+ return NULL;
+ }
+ /*
+ * We can safely use GetLastError() here without presetting it;
+ * {Initialize,Set}SecurityDescriptor() have been verified as clearing it
+ * on successful completion.
+ */
+ if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)
+ || GetLastError()) {
+ LocalFree( pSD );
+ LocalFree( sa );
+ return NULL;
+ }
+ if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE)
+ || GetLastError()) {
+ LocalFree( pSD );
+ LocalFree( sa );
+ return NULL;
+ }
+ sa->nLength = sizeof(sa);
+ sa->lpSecurityDescriptor = pSD;
+ sa->bInheritHandle = TRUE;
+ return sa;
+}
+
+
+static void CleanNullACL( void *sa ) {
+ if( sa ) {
+ LocalFree( ((PSECURITY_ATTRIBUTES)sa)->lpSecurityDescriptor);
+ LocalFree( sa );
+ }
+}
+
int master_main(int argc, char **argv)
{
+ /* returns NULL if invalid (Win95?) */
+ PSECURITY_ATTRIBUTES sa = GetNullACL();
int nchild = ap_daemons_to_start;
- event **ev;
- int *child;
int child_num = 0;
int rv, cld;
char signal_prefix_string[100];
@@ -5615,163 +6084,141 @@ int master_main(int argc, char **argv)
"ap%d", getpid());
setup_signal_names(signal_prefix_string);
- signal_shutdown_event = CreateEvent(NULL, TRUE, FALSE, signal_shutdown_name);
+ /* Create shutdown event, apPID_shutdown, where PID is the parent
+ * Apache process ID. Shutdown is signaled by 'apache -k shutdown'.
+ */
+ signal_shutdown_event = CreateEvent(sa, TRUE, FALSE, signal_shutdown_name);
if (!signal_shutdown_event) {
ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
- "Cannot create shutdown event %s", signal_shutdown_name);
+ "master_main: Cannot create shutdown event %s", signal_shutdown_name);
+ CleanNullACL((void *)sa);
exit(1);
}
- APD2("master_main: created event %s", signal_shutdown_name);
- signal_restart_event = CreateEvent(NULL, TRUE, FALSE, signal_restart_name);
+
+ /* Create restart event, apPID_restart, where PID is the parent
+ * Apache process ID. Restart is signaled by 'apache -k restart'.
+ */
+ signal_restart_event = CreateEvent(sa, TRUE, FALSE, signal_restart_name);
if (!signal_restart_event) {
CloseHandle(signal_shutdown_event);
ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
- "Cannot create restart event %s", signal_restart_name);
+ "master_main: Cannot create restart event %s", signal_restart_name);
+ CleanNullACL((void *)sa);
exit(1);
}
- APD2("master_main: created event %s", signal_restart_name);
+ CleanNullACL((void *)sa);
+ /* Create the start mutex, apPID, where PID is the parent Apache process ID.
+ * Ths start mutex is used during a restart to prevent more than one
+ * child process from entering the accept loop at once.
+ */
start_mutex = ap_create_mutex(signal_prefix_string);
- ev = (event **) alloca(sizeof(event *) * nchild);
- child = (int *) alloca(sizeof(int) * (nchild+1));
-
- while (processes_to_create--) {
- service_set_status(SERVICE_START_PENDING);
- if (create_process(process_handles, process_kill_events,
- &current_live_processes, &child_num, signal_prefix_string, argc, argv) < 0) {
- goto die_now;
- }
- }
-
- service_set_status(SERVICE_RUNNING);
-
restart_pending = shutdown_pending = 0;
do { /* restart-pending */
if (!is_graceful) {
ap_restart_time = time(NULL);
}
+ copy_listeners(pconf);
ap_clear_pool(pconf);
pparent = ap_make_sub_pool(pconf);
server_conf = ap_read_config(pconf, pparent, ap_server_confname);
- ap_open_logs(server_conf, pconf);
+ setup_listeners(pconf);
+ ap_clear_pool(plog);
+ ap_open_logs(server_conf, plog);
ap_set_version();
ap_init_modules(pconf, server_conf);
version_locked++;
-
+ service_set_status(SERVICE_START_PENDING);
+ /* Create child processes */
+ while (processes_to_create--) {
+ if (create_process(pconf, process_handles, process_kill_events,
+ &current_live_processes, &child_num, signal_prefix_string, argc, argv) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "master_main: create child process failed. Exiting.");
+ goto die_now;
+ }
+ }
+ service_set_status(SERVICE_RUNNING);
restart_pending = shutdown_pending = 0;
- /* Wait for either a child process to die, or for the stop_event
- * to be signalled by the service manager or rpc server */
- while (1) {
- /* Next line will block forever until either a child dies, or we
- * get signalled on the "apache-signal" event (e.g. if the user is
- * requesting a shutdown/restart)
- */
- if (current_live_processes == 0) {
- /* Shouldn't happen, but better safe than sorry */
- ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO, server_conf,
- "master_main: no child processes alive! creating one");
- if (create_process(process_handles, process_kill_events,
- &current_live_processes, &child_num, signal_prefix_string,
- argc, argv) < 0) {
- goto die_now;
- }
- if (processes_to_create) {
- processes_to_create--;
- }
- }
- process_handles[current_live_processes] = signal_shutdown_event;
- process_handles[current_live_processes+1] = signal_restart_event;
- rv = WaitForMultipleObjects(current_live_processes+2, (HANDLE *)process_handles,
- FALSE, INFINITE);
- if (rv == WAIT_FAILED) {
- /* Something serious is wrong */
- ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_WIN32ERROR, server_conf,
- "WaitForMultipeObjects on process handles and apache-signal -- doing shutdown");
- shutdown_pending = 1;
- break;
- }
- if (rv == WAIT_TIMEOUT) {
- /* Hey, this cannot happen */
- ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
- "WaitForMultipeObjects with INFINITE wait exited with WAIT_TIMEOUT");
- shutdown_pending = 1;
- }
+ /* Wait for either the shutdown or restart events to be signaled */
+ process_handles[current_live_processes] = signal_shutdown_event;
+ process_handles[current_live_processes+1] = signal_restart_event;
+ rv = WaitForMultipleObjects(current_live_processes+2, (HANDLE *)process_handles,
+ FALSE, INFINITE);
+ if (rv == WAIT_FAILED) {
+ /* Something serious is wrong */
+ ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_WIN32ERROR, server_conf,
+ "master_main: : WaitForMultipeObjects on process handles and apache-signal -- doing shutdown");
+ shutdown_pending = 1;
+ break;
+ }
+ if (rv == WAIT_TIMEOUT) {
+ /* Hey, this cannot happen */
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "master_main: WaitForMultipeObjects with INFINITE wait exited with WAIT_TIMEOUT");
+ shutdown_pending = 1;
+ }
- cld = rv - WAIT_OBJECT_0;
- APD4("main process: wait finished, cld=%d handle %d (max=%d)", cld, process_handles[cld], current_live_processes);
- if (cld == current_live_processes) {
- /* shutdown event signalled, we should exit now */
- if (ResetEvent(signal_shutdown_event) == 0) {
- ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
- "ResetEvent(signal_shutdown_event)");
- /* Continue -- since we are doing a shutdown anyway */
- }
- shutdown_pending = 1;
- APD3("main process: stop_event signalled: shutdown_pending=%d, restart_pending=%d",
- shutdown_pending, restart_pending);
- break;
+ cld = rv - WAIT_OBJECT_0;
+ APD4("main process: wait finished, cld=%d handle %d (max=%d)", cld, process_handles[cld], current_live_processes);
+ if (cld == current_live_processes) {
+ /* apPID_shutdown event signalled, we should exit now */
+ shutdown_pending = 1;
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
+ "master_main: Shutdown event signaled. Shutting the server down.");
+ if (ResetEvent(signal_shutdown_event) == 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
+ "ResetEvent(signal_shutdown_event)");
+ }
+ /* Signal each child processes to die */
+ for (i = 0; i < current_live_processes; i++) {
+ APD3("master_main: signalling child %d, handle %d to die", i, process_handles[i]);
+ if (SetEvent(process_kill_events[i]) == 0)
+ ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_WIN32ERROR, server_conf,
+ "master_main: SetEvent for child process in slot #%d failed", i);
}
- if (cld == current_live_processes+1) {
- /* restart event signalled, we should exit now */
- if (ResetEvent(signal_restart_event) == 0) {
+ break;
+ } else if (cld == current_live_processes+1) {
+ /* apPID_restart event signalled, restart the child process */
+ int children_to_kill = current_live_processes;
+ restart_pending = 1;
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
+ "master_main: Restart event signaled. Doing a graceful restart.");
+ if (ResetEvent(signal_restart_event) == 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
+ "master_main: ResetEvent(signal_restart_event) failed.");
+ }
+ /* Signal each child process to die */
+ for (i = 0; i < children_to_kill; i++) {
+ APD3("master_main: signalling child #%d handle %d to die", i, process_handles[i]);
+ if (SetEvent(process_kill_events[i]) == 0)
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
- "ResetEvent(signal_restart_event)");
- /* Continue -- hopefully the restart will fix the problem */
- }
- restart_pending = 1;
- APD3("main process: stop_event signalled: shutdown_pending=%d, restart_pending=%d",
- shutdown_pending, restart_pending);
- break;
+ "master_main: SetEvent for child process in slot #%d failed", i);
+ /* Remove the process (and event) from the process table */
+ cleanup_process(process_handles, process_kill_events, i, &current_live_processes);
}
+ processes_to_create = nchild;
+ ++ap_my_generation;
+ continue;
+ } else {
+ /* A child process must have exited because of MaxRequestPerChild being hit
+ * or a fatal error condition (seg fault, etc.). Remove the dead process
+ * from the process_handles and process_kill_events table and create a new
+ * child process.
+ */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
+ "master_main: Child processed exited (due to MaxRequestsPerChild?). Restarting the child process.");
ap_assert(cld < current_live_processes);
cleanup_process(process_handles, process_kill_events, cld, &current_live_processes);
APD2("main_process: child in slot %d died", rv);
- if (processes_to_create) {
- create_process(process_handles, process_kill_events, &current_live_processes,
- &child_num, signal_prefix_string, argc, argv);
- processes_to_create--;
- }
- }
- if (!shutdown_pending && !restart_pending) {
- ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO, server_conf,
- "master_main: no shutdown or restart variables set -- doing shutdown");
- shutdown_pending = 1;
- }
- if (shutdown_pending) {
- /* tell all child processes to die */
- for (i = 0; i < current_live_processes; i++) {
- APD3("main process: signalling child #%d handle %d to die", i, process_handles[i]);
- if (SetEvent(process_kill_events[i]) == 0)
- ap_log_error(APLOG_MARK,APLOG_WIN32ERROR, server_conf,
- "SetEvent for child process in slot #%d", i);
- }
- break;
+ processes_to_create = 1;
+ continue;
}
- if (restart_pending) {
- int children_to_kill = current_live_processes;
- APD1("--- Doing graceful restart ---");
-
- processes_to_create = nchild;
- for (i = 0; i < nchild; ++i) {
- if (current_live_processes >= MAX_PROCESSES)
- break;
- create_process(process_handles, process_kill_events, &current_live_processes,
- &child_num, signal_prefix_string, argc, argv);
- processes_to_create--;
- }
- for (i = 0; i < children_to_kill; i++) {
- APD3("main process: signalling child #%d handle %d to die", i, process_handles[i]);
- if (SetEvent(process_kill_events[i]) == 0)
- ap_log_error(APLOG_MARK,APLOG_WIN32ERROR, server_conf,
- "SetEvent for child process in slot #%d", i);
- }
- }
- ++ap_my_generation;
- } while (restart_pending);
+ } while (1);
/* If we dropped out of the loop we definitly want to die completely. We need to
* make sure we wait for all the child process to exit first.
@@ -5829,7 +6276,7 @@ die_now:
* either "shutdown" or "restart"
*/
-void send_signal(pool *p, char *signal)
+int send_signal(pool *p, char *signal)
{
char prefix[20];
FILE *fp;
@@ -5842,7 +6289,7 @@ void send_signal(pool *p, char *signal)
fp = fopen(fname, "r");
if (!fp) {
printf("Cannot read apache PID file %s\n", fname);
- return;
+ return FALSE;
}
prefix[0] = 'a';
prefix[1] = 'p';
@@ -5851,7 +6298,7 @@ void send_signal(pool *p, char *signal)
if (nread == 0) {
fclose(fp);
printf("PID file %s was empty\n", fname);
- return;
+ return FALSE;
}
fclose(fp);
@@ -5867,11 +6314,38 @@ void send_signal(pool *p, char *signal)
ap_start_shutdown();
else if (!strcasecmp(signal, "restart"))
ap_start_restart(1);
- else
+ else {
printf("Unknown signal name \"%s\". Use either shutdown or restart.\n",
signal);
+ return FALSE;
+ }
+ return TRUE;
+}
- return;
+void post_parse_init()
+{
+ ap_set_version();
+ ap_init_modules(pconf, server_conf);
+ ap_suexec_enabled = init_suexec();
+ version_locked++;
+ ap_open_logs(server_conf, plog);
+ set_group_privs();
+}
+
+int service_init()
+{
+ common_init();
+
+ ap_cpystrn(ap_server_root, HTTPD_ROOT, sizeof(ap_server_root));
+ if (ap_registry_get_service_conf(pconf, ap_server_confname, sizeof(ap_server_confname),
+ ap_server_argv0))
+ return FALSE;
+
+ ap_setup_prelinked_modules();
+ server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
+ ap_log_pid(pconf, ap_pid_fname);
+ post_parse_init();
+ return TRUE;
}
#ifdef WIN32
@@ -5884,41 +6358,44 @@ int REALMAIN(int argc, char *argv[])
int c;
int child = 0;
char *cp;
- int run_as_service = 1;
+ char *s;
+ char *service_name = NULL;
int install = 0;
- int configtestonly = 0;
+ int conf_specified = 0;
char *signal_to_send = NULL;
- char *s;
-
- common_init();
+ char cwd[MAX_STRING_LEN];
- if ((s = strrchr(argv[0], '/')) != NULL) {
- ap_server_argv0 = ++s;
+ /* Service application
+ * Configuration file in registry at:
+ * HKLM\System\CurrentControlSet\Services\[Svc name]\Parameters\ConfPath
+ */
+ if (isProcessService()) {
+ service_main(master_main, argc, argv);
+ clean_parent_exit(0);
+ }
+
+ /* Console application or a child process. */
+
+ if ((s = strrchr(argv[0], PATHSEPARATOR)) != NULL) {
+ ap_server_argv0 = ++s;
}
else {
- ap_server_argv0 = argv[0];
+ ap_server_argv0 = argv[0];
}
- /* Get the serverroot from the registry, if it exists. This can be
- * overridden by a command line -d argument.
- */
- if (ap_registry_get_server_root(pconf, ap_server_root, sizeof(ap_server_root)) < 0) {
- /* The error has already been logged. Actually it won't have been,
- * because we haven't read the config files to find out where our
- * error log is. But we can't just ignore the error since we might
- * end up using totally the wrong server root.
- */
- exit(1);
- }
+ common_init();
+ ap_setup_prelinked_modules();
- if (!*ap_server_root) {
- ap_cpystrn(ap_server_root, HTTPD_ROOT, sizeof(ap_server_root));
+ if(!GetCurrentDirectory(sizeof(cwd),cwd)) {
+ ap_log_error(APLOG_MARK,APLOG_WIN32ERROR, NULL,
+ "GetCurrentDirectory() failure");
+ return -1;
}
- ap_cpystrn(ap_server_confname, SERVER_CONFIG_FILE, sizeof(ap_server_confname));
- ap_setup_prelinked_modules();
+ ap_cpystrn(cwd, ap_os_canonical_filename(pcommands, cwd), sizeof(cwd));
+ ap_cpystrn(ap_server_root, cwd, sizeof(ap_server_root));
- while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLZ:iusSthk:")) != -1) {
+ while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLZ:iusStThk:n:")) != -1) {
char **new;
switch (c) {
case 'c':
@@ -5945,15 +6422,20 @@ int REALMAIN(int argc, char *argv[])
ap_assert(start_mutex);
child = 1;
break;
+ case 'n':
+ service_name = ap_pstrdup(pcommands, optarg);
+ if (isValidService(optarg)) {
+ ap_registry_get_service_conf(pconf, ap_server_confname, sizeof(ap_server_confname),
+ optarg);
+ conf_specified = 1;
+ }
+ break;
case 'i':
install = 1;
break;
case 'u':
install = -1;
break;
- case 's':
- run_as_service = 0;
- break;
case 'S':
ap_dump_settings = 1;
break;
@@ -5962,10 +6444,22 @@ int REALMAIN(int argc, char *argv[])
break;
#endif /* WIN32 */
case 'd':
- ap_cpystrn(ap_server_root, ap_os_canonical_filename(pconf, optarg), sizeof(ap_server_root));
+ optarg = ap_os_canonical_filename(pcommands, optarg);
+ if (!ap_os_is_path_absolute(optarg)) {
+ optarg = ap_pstrcat(pcommands, cwd, optarg, NULL);
+ ap_getparents(optarg);
+ }
+ if (optarg[strlen(optarg)-1] != '/')
+ optarg = ap_pstrcat(pcommands, optarg, "/", NULL);
+ ap_cpystrn(ap_server_root,
+ optarg,
+ sizeof(ap_server_root));
break;
case 'f':
- ap_cpystrn(ap_server_confname, ap_os_canonical_filename(pconf, optarg), sizeof(ap_server_confname));
+ ap_cpystrn(ap_server_confname,
+ ap_os_canonical_filename(pcommands, optarg),
+ sizeof(ap_server_confname));
+ conf_specified = 1;
break;
case 'v':
ap_set_version();
@@ -5986,40 +6480,100 @@ int REALMAIN(int argc, char *argv[])
++one_process; /* Weird debugging mode. */
break;
case 't':
- configtestonly = 1;
+ ap_configtestonly = 1;
+ ap_docrootcheck = 1;
+ break;
+ case 'T':
+ ap_configtestonly = 1;
+ ap_docrootcheck = 0;
break;
case 'h':
- usage(argv[0]);
+ usage(ap_server_argv0);
case '?':
- usage(argv[0]);
- }
+ usage(ap_server_argv0);
+ } /* switch */
+ } /* while */
+
+ /* ServerConfFile is found in this order:
+ * (1) -f or -n
+ * (2) [-d]/SERVER_CONFIG_FILE
+ * (3) ./SERVER_CONFIG_FILE
+ * (4) [Registry: HKLM\Software\[product]\ServerRoot]/SERVER_CONFIG_FILE
+ * (5) /HTTPD_ROOT/SERVER_CONFIG_FILE
+ */
+
+ if (!conf_specified) {
+ ap_cpystrn(ap_server_confname, SERVER_CONFIG_FILE, sizeof(ap_server_confname));
+ if (access(ap_server_root_relative(pcommands, ap_server_confname), 0)) {
+ ap_registry_get_server_root(pconf, ap_server_root, sizeof(ap_server_root));
+ if (!*ap_server_root)
+ ap_cpystrn(ap_server_root, HTTPD_ROOT, sizeof(ap_server_root));
+ ap_cpystrn(ap_server_root, ap_os_canonical_filename(pcommands, ap_server_root),
+ sizeof(ap_server_root));
+ }
}
- if (!child && run_as_service) {
- service_cd();
+#ifdef EAPI
+ ap_init_alloc_shared(TRUE);
+#endif
+
+ if (!ap_os_is_path_absolute(ap_server_confname)) {
+ char *full_conf_path;
+
+ full_conf_path = ap_pstrcat(pcommands, ap_server_root, "/", ap_server_confname, NULL);
+ full_conf_path = ap_os_canonical_filename(pcommands, full_conf_path);
+ ap_cpystrn(ap_server_confname, full_conf_path, sizeof(ap_server_confname));
+ }
+ ap_getparents(ap_server_confname);
+ ap_no2slash(ap_server_confname);
+
+#ifdef WIN32
+ if (install) {
+ if (!service_name)
+ service_name = ap_pstrdup(pconf, DEFAULTSERVICENAME);
+ if (install > 0)
+ InstallService(service_name, ap_server_root_relative(pcommands, ap_server_confname));
+ else
+ RemoveService(service_name);
+ clean_parent_exit(0);
+ }
+
+ if (service_name && signal_to_send) {
+ send_signal_to_service(service_name, signal_to_send);
+ clean_parent_exit(0);
}
+ if (service_name && !conf_specified) {
+ printf("Unknown service: %s\n", service_name);
+ clean_parent_exit(0);
+ }
+#endif
server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
- if (configtestonly) {
- fprintf(stderr, "Syntax OK\n");
- exit(0);
+#ifdef EAPI
+ ap_init_alloc_shared(FALSE);
+#endif
+
+ if (ap_configtestonly) {
+ fprintf(stderr, "%s: Syntax OK\n", ap_server_root_relative(pcommands, ap_server_confname));
+ clean_parent_exit(0);
}
- if (signal_to_send) {
- send_signal(pconf, signal_to_send);
- exit(0);
+ if (ap_dump_settings) {
+ clean_parent_exit(0);
}
- if (!child && !ap_dump_settings && !install) {
- ap_log_pid(pconf, ap_pid_fname);
+ /* Treat -k start confpath as just -f confpath */
+ if (signal_to_send && strcasecmp(signal_to_send, "start")) {
+ send_signal(pconf, signal_to_send);
+ clean_parent_exit(0);
}
- ap_set_version();
- ap_init_modules(pconf, server_conf);
- ap_suexec_enabled = init_suexec();
- version_locked++;
- ap_open_logs(server_conf, pconf);
- set_group_privs();
+
+ if (!child && !ap_dump_settings) {
+ ap_log_pid(pconf, ap_pid_fname);
+ }
+
+ post_parse_init();
#ifdef OS2
printf("%s running...\n", ap_get_server_version());
@@ -6029,7 +6583,6 @@ int REALMAIN(int argc, char *argv[])
printf("%s running...\n", ap_get_server_version());
}
#endif
-
if (one_process && !exit_event)
exit_event = create_event(0, 0, NULL);
if (one_process && !start_mutex)
@@ -6046,10 +6599,8 @@ int REALMAIN(int argc, char *argv[])
ap_destroy_mutex(start_mutex);
destroy_event(exit_event);
}
- else {
- service_main(master_main, argc, argv,
- "Apache", install, run_as_service);
- }
+ else
+ master_main(argc, argv);
clean_parent_exit(0);
return 0; /* purely to avoid a warning */
@@ -6078,6 +6629,18 @@ int main(int argc, char *argv[])
#endif /* ndef SHARED_CORE_TIESTATIC */
#else /* ndef SHARED_CORE_BOOTSTRAP */
+#ifdef OS2
+/* Shared core loader for OS/2 */
+
+int ap_main(int argc, char *argv[]); /* Load time linked from libhttpd.dll */
+
+int main(int argc, char *argv[])
+{
+ return ap_main(argc, argv);
+}
+
+#else
+
/*
** Standalone Bootstrap Program for Shared Core support
**
@@ -6127,7 +6690,7 @@ int main(int argc, char *argv[], char *envp[])
* but only handle the -L option
*/
llp_dir = SHARED_CORE_DIR;
- while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLR:SZ:th")) != -1) {
+ while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLR:SZ:tTh")) != -1) {
switch (c) {
case 'D':
case 'C':
@@ -6142,6 +6705,7 @@ int main(int argc, char *argv[], char *envp[])
case 'S':
case 'Z':
case 't':
+ case 'T':
case 'h':
case '?':
break;
@@ -6154,7 +6718,7 @@ int main(int argc, char *argv[], char *envp[])
/*
* create path to SHARED_CORE_EXECUTABLE_PROGRAM
*/
- sprintf(prog, "%s/%s", llp_dir, SHARED_CORE_EXECUTABLE_PROGRAM);
+ ap_snprintf(prog, sizeof(prog), "%s/%s", llp_dir, SHARED_CORE_EXECUTABLE_PROGRAM);
/*
* adjust process environment therewith the Unix loader
@@ -6171,15 +6735,18 @@ int main(int argc, char *argv[], char *envp[])
}
if (llp_slot == NULL) {
envpnew = (char **)malloc(sizeof(char *)*(i + 2));
+ if (envpnew == NULL) {
+ fprintf(stderr, "Ouch! Out of memory generating envpnew!\n");
+ }
memcpy(envpnew, envp, sizeof(char *)*i);
envp = envpnew;
llp_slot = &envp[i++];
envp[i] = NULL;
}
if (llp_existing != NULL)
- sprintf(llp_buf, "%s=%s:%s", VARNAME, llp_dir, llp_existing);
+ ap_snprintf(llp_buf, sizeof(llp_buf), "%s=%s:%s", VARNAME, llp_dir, llp_existing);
else
- sprintf(llp_buf, "%s=%s", VARNAME, llp_dir);
+ ap_snprintf(llp_buf, sizeof(llp_buf), "%s=%s", VARNAME, llp_dir);
*llp_slot = strdup(llp_buf);
/*
@@ -6196,5 +6763,28 @@ int main(int argc, char *argv[], char *envp[])
return 0;
}
+#endif /* def OS2 */
#endif /* ndef SHARED_CORE_BOOTSTRAP */
+#ifndef SHARED_CORE_BOOTSTRAP
+/*
+ * Force ap_validate_password() into the image so that modules like
+ * mod_auth can use it even if they're dynamically loaded.
+ */
+void suck_in_ap_validate_password(void);
+void suck_in_ap_validate_password(void)
+{
+ ap_validate_password("a", "b");
+}
+#endif
+
+/* force Expat to be linked into the server executable */
+#if defined(USE_EXPAT) && !defined(SHARED_CORE_BOOTSTRAP)
+#include "xmlparse.h"
+const XML_LChar *suck_in_expat(void);
+const XML_LChar *suck_in_expat(void)
+{
+ return XML_ErrorString(XML_ERROR_NONE);
+}
+#endif /* USE_EXPAT */
+
diff --git a/usr.sbin/httpd/src/main/http_protocol.c b/usr.sbin/httpd/src/main/http_protocol.c
index 9c4f831748e..0869708f726 100644
--- a/usr.sbin/httpd/src/main/http_protocol.c
+++ b/usr.sbin/httpd/src/main/http_protocol.c
@@ -144,16 +144,18 @@ API_EXPORT(int) ap_set_byterange(request_rec *r)
return 0;
}
- /* Check the If-Range header for Etag or Date */
-
+ /* Check the If-Range header for Etag or Date.
+ * Note that this check will return false (as required) if either
+ * of the two etags are weak.
+ */
if ((if_range = ap_table_get(r->headers_in, "If-Range"))) {
if (if_range[0] == '"') {
if (!(match = ap_table_get(r->headers_out, "Etag")) ||
- (strcasecmp(if_range, match) != 0))
+ (strcmp(if_range, match) != 0))
return 0;
}
else if (!(match = ap_table_get(r->headers_out, "Last-Modified")) ||
- (strcasecmp(if_range, match) != 0))
+ (strcmp(if_range, match) != 0))
return 0;
}
@@ -398,13 +400,14 @@ API_EXPORT(int) ap_meets_conditions(request_rec *r)
mtime = (r->mtime != 0) ? r->mtime : time(NULL);
/* If an If-Match request-header field was given
- * AND if our ETag does not match any of the entity tags in that field
- * AND the field value is not "*" (meaning match anything), then
+ * AND the field value is not "*" (meaning match anything)
+ * AND if our strong ETag does not match any entity tag in that field,
* respond with a status of 412 (Precondition Failed).
*/
if ((if_match = ap_table_get(r->headers_in, "If-Match")) != NULL) {
- if ((etag == NULL) ||
- ((if_match[0] != '*') && !ap_find_token(r->pool, if_match, etag))) {
+ if (if_match[0] != '*' &&
+ (etag == NULL || etag[0] == 'W' ||
+ !ap_find_list_item(r->pool, if_match, etag))) {
return HTTP_PRECONDITION_FAILED;
}
}
@@ -425,22 +428,38 @@ API_EXPORT(int) ap_meets_conditions(request_rec *r)
}
/* If an If-None-Match request-header field was given
- * AND if our ETag matches any of the entity tags in that field
- * OR if the field value is "*" (meaning match anything), then
- * if the request method was GET or HEAD, the server SHOULD
- * respond with a 304 (Not Modified) response.
- * For all other request methods, the server MUST
- * respond with a status of 412 (Precondition Failed).
+ * AND the field value is "*" (meaning match anything)
+ * OR our ETag matches any of the entity tags in that field, fail.
+ *
+ * If the request method was GET or HEAD, failure means the server
+ * SHOULD respond with a 304 (Not Modified) response.
+ * For all other request methods, failure means the server MUST
+ * respond with a status of 412 (Precondition Failed).
+ *
+ * GET or HEAD allow weak etag comparison, all other methods require
+ * strong comparison. We can only use weak if it's not a range request.
*/
if_nonematch = ap_table_get(r->headers_in, "If-None-Match");
if (if_nonematch != NULL) {
- int rstatus;
-
- if ((if_nonematch[0] == '*')
- || ((etag != NULL) && ap_find_token(r->pool, if_nonematch, etag))) {
- rstatus = (r->method_number == M_GET) ? HTTP_NOT_MODIFIED
- : HTTP_PRECONDITION_FAILED;
- return rstatus;
+ if (r->method_number == M_GET) {
+ if (if_nonematch[0] == '*')
+ return HTTP_NOT_MODIFIED;
+ if (etag != NULL) {
+ if (ap_table_get(r->headers_in, "Range")) {
+ if (etag[0] != 'W' &&
+ ap_find_list_item(r->pool, if_nonematch, etag)) {
+ return HTTP_NOT_MODIFIED;
+ }
+ }
+ else if (strstr(if_nonematch, etag)) {
+ return HTTP_NOT_MODIFIED;
+ }
+ }
+ }
+ else if (if_nonematch[0] == '*' ||
+ (etag != NULL &&
+ ap_find_list_item(r->pool, if_nonematch, etag))) {
+ return HTTP_PRECONDITION_FAILED;
}
}
/* Else if a valid If-Modified-Since request-header field was given
@@ -730,10 +749,6 @@ CORE_EXPORT(void) ap_parse_uri(request_rec *r, const char *uri)
for (x = r->uri; (x = strchr(x, '\\')) != NULL; )
*x = '/';
-#ifndef WIN32 /* for OS/2 only: */
- /* Fix OS/2 HPFS filename case problem. */
- ap_str_tolower(r->uri);
-#endif
}
#endif /* OS2 || WIN32 */
}
@@ -772,6 +787,10 @@ static int read_request_line(request_rec *r)
while ((len = getline(l, sizeof(l), conn->client, 0)) <= 0) {
if ((len < 0) || ap_bgetflag(conn->client, B_EOF)) {
ap_bsetflag(conn->client, B_SAFEREAD, 0);
+ /* this is a hack to make sure that request time is set,
+ * it's not perfect, but it's better than nothing
+ */
+ r->request_time = time(0);
return 0;
}
}
@@ -934,7 +953,6 @@ request_rec *ap_read_request(conn_rec *conn)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
"request failed: URI too long");
ap_send_error_response(r, 0);
- ap_bflush(r->connection->client);
ap_log_transaction(r);
return r;
}
@@ -948,7 +966,6 @@ request_rec *ap_read_request(conn_rec *conn)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
"request failed: error reading the headers");
ap_send_error_response(r, 0);
- ap_bflush(r->connection->client);
ap_log_transaction(r);
return r;
}
@@ -968,7 +985,6 @@ request_rec *ap_read_request(conn_rec *conn)
r->header_only = 0;
r->status = HTTP_BAD_REQUEST;
ap_send_error_response(r, 0);
- ap_bflush(r->connection->client);
ap_log_transaction(r);
return r;
}
@@ -1001,7 +1017,6 @@ request_rec *ap_read_request(conn_rec *conn)
"client sent HTTP/1.1 request without hostname "
"(see RFC2068 section 9, and 14.23): %s", r->uri);
ap_send_error_response(r, 0);
- ap_bflush(r->connection->client);
ap_log_transaction(r);
return r;
}
@@ -1022,7 +1037,6 @@ request_rec *ap_read_request(conn_rec *conn)
"client sent an unrecognized expectation value of "
"Expect: %s", expect);
ap_send_error_response(r, 0);
- ap_bflush(r->connection->client);
(void) ap_discard_request_body(r);
ap_log_transaction(r);
return r;
@@ -1141,7 +1155,13 @@ API_EXPORT(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
return AUTH_REQUIRED;
}
- t = ap_uudecode(r->pool, auth_line);
+ /* CHARSET_EBCDIC Issue's here ?!? Compare with 32/9 instead
+ * as we are operating on an octed stream ?
+ */
+ while (*auth_line== ' ' || *auth_line== '\t')
+ auth_line++;
+
+ t = ap_pbase64decode(r->pool, auth_line);
/* Note that this allocation has to be made from r->connection->pool
* because it has the lifetime of the connection. The other allocations
* are temporary and can be tossed away any time.
@@ -1160,7 +1180,16 @@ API_EXPORT(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
* and must be listed in order.
*/
-static char *status_lines[RESPONSE_CODES] = {
+#ifdef UTS21
+/* The second const triggers an assembler bug on UTS 2.1.
+ * Another workaround is to move some code out of this file into another,
+ * but this is easier. Dave Dykstra, 3/31/99
+ */
+static const char * status_lines[RESPONSE_CODES] =
+#else
+static const char * const status_lines[RESPONSE_CODES] =
+#endif
+{
"100 Continue",
"101 Switching Protocols",
"102 Processing",
@@ -1258,8 +1287,7 @@ API_EXPORT(int) ap_index_of_response(int status)
API_EXPORT_NONSTD(int) ap_send_header_field(request_rec *r,
const char *fieldname, const char *fieldval)
{
- return (0 < ap_bvputs(r->connection->client,
- fieldname, ": ", fieldval, "\015\012", NULL));
+ return (0 < ap_rvputs(r, fieldname, ": ", fieldval, "\015\012", NULL));
}
API_EXPORT(void) ap_basic_http_header(request_rec *r)
@@ -1294,8 +1322,7 @@ API_EXPORT(void) ap_basic_http_header(request_rec *r)
/* Output the HTTP/1.x Status-Line and the Date and Server fields */
- ap_bvputs(r->connection->client,
- protocol, " ", r->status_line, "\015\012", NULL);
+ ap_rvputs(r, protocol, " ", r->status_line, "\015\012", NULL);
ap_send_header_field(r, "Date", ap_gm_timestr_822(r->pool, r->request_time));
ap_send_header_field(r, "Server", ap_get_server_version());
@@ -1380,9 +1407,9 @@ API_EXPORT(int) ap_send_http_trace(request_rec *r)
ap_rvputs(r, r->the_request, "\015\012", NULL);
- ap_table_do((int (*) (void *, const char *, const char *)) ap_send_header_field,
- (void *) r, r->headers_in, NULL);
- ap_bputs("\015\012", r->connection->client);
+ ap_table_do((int (*) (void *, const char *, const char *))
+ ap_send_header_field, (void *) r, r->headers_in, NULL);
+ ap_rputs("\015\012", r);
ap_kill_timeout(r);
return OK;
@@ -1429,6 +1456,84 @@ static int use_range_x(request_rec *r)
&& strstr(ua, "MSIE 3")));
}
+/* This routine is called by ap_table_do and merges all instances of
+ * the passed field values into a single array that will be further
+ * processed by some later routine. Originally intended to help split
+ * and recombine multiple Vary fields, though it is generic to any field
+ * consisting of comma/space-separated tokens.
+ */
+static int uniq_field_values(void *d, const char *key, const char *val)
+{
+ array_header *values;
+ char *start;
+ char *e;
+ char **strpp;
+ int i;
+
+ values = (array_header *)d;
+
+ e = ap_pstrdup(values->pool, val);
+
+ do {
+ /* Find a non-empty fieldname */
+
+ while (*e == ',' || ap_isspace(*e)) {
+ ++e;
+ }
+ if (*e == '\0') {
+ break;
+ }
+ start = e;
+ while (*e != '\0' && *e != ',' && !ap_isspace(*e)) {
+ ++e;
+ }
+ if (*e != '\0') {
+ *e++ = '\0';
+ }
+
+ /* Now add it to values if it isn't already represented.
+ * Could be replaced by a ap_array_strcasecmp() if we had one.
+ */
+ for (i = 0, strpp = (char **) values->elts; i < values->nelts;
+ ++i, ++strpp) {
+ if (*strpp && strcasecmp(*strpp, start) == 0) {
+ break;
+ }
+ }
+ if (i == values->nelts) { /* if not found */
+ *(char **)ap_push_array(values) = start;
+ }
+ } while (*e != '\0');
+
+ return 1;
+}
+
+/*
+ * Since some clients choke violently on multiple Vary fields, or
+ * Vary fields with duplicate tokens, combine any multiples and remove
+ * any duplicates.
+ */
+static void fixup_vary(request_rec *r)
+{
+ array_header *varies;
+
+ varies = ap_make_array(r->pool, 5, sizeof(char *));
+
+ /* Extract all Vary fields from the headers_out, separate each into
+ * its comma-separated fieldname values, and then add them to varies
+ * if not already present in the array.
+ */
+ ap_table_do((int (*)(void *, const char *, const char *))uniq_field_values,
+ (void *) varies, r->headers_out, "Vary", NULL);
+
+ /* If we found any, replace old Vary fields with unique-ified value */
+
+ if (varies->nelts > 0) {
+ ap_table_setn(r->headers_out, "Vary",
+ ap_array_pstrcat(r->pool, varies, ','));
+ }
+}
+
API_EXPORT(void) ap_send_http_header(request_rec *r)
{
int i;
@@ -1453,6 +1558,20 @@ API_EXPORT(void) ap_send_http_header(request_rec *r)
r->headers_out = ap_overlay_tables(r->pool, r->err_headers_out,
r->headers_out);
+ /*
+ * Remove the 'Vary' header field if the client can't handle it.
+ * Since this will have nasty effects on HTTP/1.1 caches, force
+ * the response into HTTP/1.0 mode.
+ */
+ if (ap_table_get(r->subprocess_env, "force-no-vary") != NULL) {
+ ap_table_unset(r->headers_out, "Vary");
+ r->proto_num = HTTP_VERSION(1,0);
+ ap_table_set(r->subprocess_env, "force-response-1.0", "1");
+ }
+ else {
+ fixup_vary(r);
+ }
+
ap_hard_timeout("send headers", r);
ap_basic_http_header(r);
@@ -1533,9 +1652,9 @@ API_EXPORT(void) ap_finalize_request_protocol(request_rec *r)
ap_bsetflag(r->connection->client, B_CHUNK, 0);
ap_soft_timeout("send ending chunk", r);
- ap_bputs("0\015\012", r->connection->client);
+ ap_rputs("0\015\012", r);
/* If we had footer "headers", we'd send them now */
- ap_bputs("\015\012", r->connection->client);
+ ap_rputs("\015\012", r);
ap_kill_timeout(r);
}
}
@@ -1644,10 +1763,9 @@ API_EXPORT(int) ap_should_client_block(request_rec *r)
if (r->expecting_100 && r->proto_num >= HTTP_VERSION(1,1)) {
/* sending 100 Continue interim response */
- ap_bvputs(r->connection->client,
- SERVER_PROTOCOL, " ", status_lines[0], "\015\012\015\012",
- NULL);
- ap_bflush(r->connection->client);
+ ap_rvputs(r, SERVER_PROTOCOL, " ", status_lines[0], "\015\012\015\012",
+ NULL);
+ ap_rflush(r);
}
return 1;
@@ -1657,7 +1775,7 @@ static long get_chunk_size(char *b)
{
long chunksize = 0;
- while (isxdigit(*b)) {
+ while (ap_isxdigit(*b)) {
int xvalue = 0;
if (*b >= '0' && *b <= '9')
@@ -1735,7 +1853,7 @@ API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz)
chunk_start = getline(buffer, bufsiz, r->connection->client, 0);
if ((chunk_start <= 0) || (chunk_start >= (bufsiz - 1))
- || !isxdigit(*buffer)) {
+ || !ap_isxdigit(*buffer)) {
r->connection->keepalive = -1;
return -1;
}
@@ -1854,14 +1972,18 @@ API_EXPORT(int) ap_discard_request_body(request_rec *r)
if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_PASS)))
return rv;
- /* If we are discarding the request body, then we must already know
- * the final status code, therefore disable the sending of 100 continue.
+ /* In order to avoid sending 100 Continue when we already know the
+ * final response status, and yet not kill the connection if there is
+ * no request body to be read, we need to duplicate the test from
+ * ap_should_client_block() here negated rather than call it directly.
*/
- r->expecting_100 = 0;
-
- if (ap_should_client_block(r)) {
+ if ((r->read_length == 0) && (r->read_chunked || (r->remaining > 0))) {
char dumpbuf[HUGE_STRING_LEN];
+ if (r->expecting_100) {
+ r->connection->keepalive = -1;
+ return OK;
+ }
ap_hard_timeout("reading request body", r);
while ((rv = ap_get_client_block(r, dumpbuf, HUGE_STRING_LEN)) > 0)
continue;
@@ -1910,23 +2032,19 @@ API_EXPORT(long) ap_send_fd_length(FILE *f, request_rec *r, long length)
while (n && !r->connection->aborted) {
w = ap_bwrite(r->connection->client, &buf[o], n);
if (w > 0) {
- ap_reset_timeout(r); /* reset timeout after successful write */
- total_bytes_sent += w;
+ ap_reset_timeout(r); /* reset timeout after successful write */
+ total_bytes_sent += w;
n -= w;
o += w;
}
else if (w < 0) {
- if (r->connection->aborted)
- break;
- else if (errno == EAGAIN)
- continue;
- else {
+ if (!r->connection->aborted) {
ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
"client stopped connection before send body completed");
ap_bsetflag(r->connection->client, B_EOUT, 1);
r->connection->aborted = 1;
- break;
}
+ break;
}
}
}
@@ -1956,9 +2074,11 @@ API_EXPORT(long) ap_send_fb_length(BUFF *fb, request_rec *r, long length)
/* Make fb unbuffered and non-blocking */
ap_bsetflag(fb, B_RD, 0);
+#ifndef TPF
ap_bnonblock(fb, B_RD);
+#endif
fd = ap_bfileno(fb, B_RD);
-#ifndef WIN32
+#ifdef CHECK_FD_SETSIZE
if (fd >= FD_SETSIZE) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
"send body: filedescriptor (%u) larger than FD_SETSIZE (%u) "
@@ -1999,10 +2119,15 @@ API_EXPORT(long) ap_send_fb_length(BUFF *fb, request_rec *r, long length)
break;
if (n < 0 && errno != EAGAIN)
break;
+
/* we need to block, so flush the output first */
- ap_bflush(r->connection->client);
- if (r->connection->aborted)
+ if (ap_bflush(r->connection->client) < 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before send body completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
break;
+ }
FD_SET(fd, &fds);
/*
* we don't care what select says, we might as well loop back
@@ -2017,30 +2142,24 @@ API_EXPORT(long) ap_send_fb_length(BUFF *fb, request_rec *r, long length)
if (n < 1 || r->connection->aborted) {
break;
}
-
o = 0;
- total_bytes_sent += n;
while (n && !r->connection->aborted) {
w = ap_bwrite(r->connection->client, &buf[o], n);
if (w > 0) {
- ap_reset_timeout(r); /* reset timeout after successful
- * write */
+ ap_reset_timeout(r); /* reset timeout after successful write */
+ total_bytes_sent += w;
n -= w;
o += w;
}
else if (w < 0) {
- if (r->connection->aborted)
- break;
- else if (errno == EAGAIN)
- continue;
- else {
+ if (!r->connection->aborted) {
ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
- "client stopped connection before send body completed");
+ "client stopped connection before send body completed");
ap_bsetflag(r->connection->client, B_EOUT, 1);
r->connection->aborted = 1;
- break;
}
+ break;
}
}
}
@@ -2089,23 +2208,19 @@ API_EXPORT(size_t) ap_send_mmap(void *mm, request_rec *r, size_t offset,
while (n && !r->connection->aborted) {
w = ap_bwrite(r->connection->client, (char *) mm + offset, n);
if (w > 0) {
- ap_reset_timeout(r); /* reset timeout after successful write */
+ ap_reset_timeout(r); /* reset timeout after successful write */
total_bytes_sent += w;
n -= w;
offset += w;
}
else if (w < 0) {
- if (r->connection->aborted)
- break;
- else if (errno == EAGAIN)
- continue;
- else {
+ if (!r->connection->aborted) {
ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
- "client stopped connection before send mmap completed");
+ "client stopped connection before send mmap completed");
ap_bsetflag(r->connection->client, B_EOUT, 1);
r->connection->aborted = 1;
- break;
}
+ break;
}
}
}
@@ -2119,7 +2234,16 @@ API_EXPORT(int) ap_rputc(int c, request_rec *r)
{
if (r->connection->aborted)
return EOF;
- ap_bputc(c, r->connection->client);
+
+ if (ap_bputc(c, r->connection->client) < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before rputc completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ return EOF;
+ }
SET_BYTES_SENT(r);
return c;
}
@@ -2130,7 +2254,17 @@ API_EXPORT(int) ap_rputs(const char *str, request_rec *r)
if (r->connection->aborted)
return EOF;
+
rcode = ap_bputs(str, r->connection->client);
+ if (rcode < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before rputs completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ return EOF;
+ }
SET_BYTES_SENT(r);
return rcode;
}
@@ -2138,9 +2272,42 @@ API_EXPORT(int) ap_rputs(const char *str, request_rec *r)
API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
{
int n;
+
if (r->connection->aborted)
- return EOF;
+ return -1;
+
n = ap_bwrite(r->connection->client, buf, nbyte);
+ if (n < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before rwrite completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ return -1;
+ }
+ SET_BYTES_SENT(r);
+ return n;
+}
+
+API_EXPORT(int) ap_vrprintf(request_rec *r, const char *fmt, va_list ap)
+{
+ int n;
+
+ if (r->connection->aborted)
+ return -1;
+
+ n = ap_vbprintf(r->connection->client, fmt, ap);
+
+ if (n < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before vrprintf completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ return -1;
+ }
SET_BYTES_SENT(r);
return n;
}
@@ -2151,10 +2318,21 @@ API_EXPORT(int) ap_rprintf(request_rec *r, const char *fmt,...)
int n;
if (r->connection->aborted)
- return EOF;
+ return -1;
+
va_start(vlist, fmt);
n = ap_vbprintf(r->connection->client, fmt, vlist);
va_end(vlist);
+
+ if (n < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before rprintf completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ return -1;
+ }
SET_BYTES_SENT(r);
return n;
}
@@ -2178,7 +2356,13 @@ API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r,...)
i = ap_bwrite(fb, x, j);
if (i != j) {
va_end(args);
- return -1;
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before rvputs completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ return EOF;
}
k += i;
}
@@ -2190,7 +2374,16 @@ API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r,...)
API_EXPORT(int) ap_rflush(request_rec *r)
{
- return ap_bflush(r->connection->client);
+ if (ap_bflush(r->connection->client) < 0) {
+ if (!r->connection->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+ "client stopped connection before rflush completed");
+ ap_bsetflag(r->connection->client, B_EOUT, 1);
+ r->connection->aborted = 1;
+ }
+ return EOF;
+ }
+ return 0;
}
/* We should have named this send_canned_response, since it is used for any
@@ -2201,12 +2394,19 @@ API_EXPORT(int) ap_rflush(request_rec *r)
*/
void ap_send_error_response(request_rec *r, int recursive_error)
{
- BUFF *fd = r->connection->client;
int status = r->status;
int idx = ap_index_of_response(status);
char *custom_response;
const char *location = ap_table_get(r->headers_out, "Location");
+ /*
+ * It's possible that the Location field might be in r->err_headers_out
+ * instead of r->headers_out; use the latter if possible, else the
+ * former.
+ */
+ if (location == NULL) {
+ location = ap_table_get(r->err_headers_out, "Location");
+ }
/* We need to special-case the handling of 204 and 304 responses,
* since they have specific HTTP requirements and do not include a
* message body. Note that being assbackwards here is not an option.
@@ -2258,9 +2458,14 @@ void ap_send_error_response(request_rec *r, int recursive_error)
r->err_headers_out = tmp;
ap_clear_table(r->err_headers_out);
- if (location && *location
- && (ap_is_HTTP_REDIRECT(status) || status == HTTP_CREATED))
- ap_table_setn(r->headers_out, "Location", location);
+ if (ap_is_HTTP_REDIRECT(status) || (status == HTTP_CREATED)) {
+ if ((location != NULL) && *location) {
+ ap_table_setn(r->headers_out, "Location", location);
+ }
+ else {
+ location = ""; /* avoids coredump when printing, below */
+ }
+ }
r->content_language = NULL;
r->content_languages = NULL;
@@ -2275,6 +2480,7 @@ void ap_send_error_response(request_rec *r, int recursive_error)
if (r->header_only) {
ap_finalize_request_protocol(r);
+ ap_rflush(r);
return;
}
}
@@ -2295,9 +2501,10 @@ void ap_send_error_response(request_rec *r, int recursive_error)
* the original error and output that as well.
*/
if (custom_response[0] == '\"') {
- ap_bputs(custom_response + 1, fd);
+ ap_rputs(custom_response + 1, r);
ap_kill_timeout(r);
ap_finalize_request_protocol(r);
+ ap_rflush(r);
return;
}
/*
@@ -2307,8 +2514,8 @@ void ap_send_error_response(request_rec *r, int recursive_error)
r = r->prev;
}
{
- char *title = status_lines[idx];
- char *h1;
+ const char *title = status_lines[idx];
+ const char *h1;
const char *error_notes;
/* Accept a status_line set by a module, but only if it begins
@@ -2327,8 +2534,8 @@ void ap_send_error_response(request_rec *r, int recursive_error)
/* folks decided they didn't want the error code in the H1 text */
h1 = &title[4];
- ap_bvputs(fd,
- "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
+ ap_rvputs(r,
+ DOCTYPE_HTML_2_0
"<HTML><HEAD>\n<TITLE>", title,
"</TITLE>\n</HEAD><BODY>\n<H1>", h1, "</H1>\n",
NULL);
@@ -2337,17 +2544,17 @@ void ap_send_error_response(request_rec *r, int recursive_error)
case HTTP_MOVED_PERMANENTLY:
case HTTP_MOVED_TEMPORARILY:
case HTTP_TEMPORARY_REDIRECT:
- ap_bvputs(fd, "The document has moved <A HREF=\"",
+ ap_rvputs(r, "The document has moved <A HREF=\"",
ap_escape_html(r->pool, location), "\">here</A>.<P>\n",
NULL);
break;
case HTTP_SEE_OTHER:
- ap_bvputs(fd, "The answer to your request is located <A HREF=\"",
+ ap_rvputs(r, "The answer to your request is located <A HREF=\"",
ap_escape_html(r->pool, location), "\">here</A>.<P>\n",
NULL);
break;
case HTTP_USE_PROXY:
- ap_bvputs(fd, "This resource is only accessible "
+ ap_rvputs(r, "This resource is only accessible "
"through the proxy\n",
ap_escape_html(r->pool, location),
"<BR>\nYou will need to ",
@@ -2355,38 +2562,38 @@ void ap_send_error_response(request_rec *r, int recursive_error)
break;
case HTTP_PROXY_AUTHENTICATION_REQUIRED:
case AUTH_REQUIRED:
- ap_bputs("This server could not verify that you\n", fd);
- ap_bputs("are authorized to access the document you\n", fd);
- ap_bputs("requested. Either you supplied the wrong\n", fd);
- ap_bputs("credentials (e.g., bad password), or your\n", fd);
- ap_bputs("browser doesn't understand how to supply\n", fd);
- ap_bputs("the credentials required.<P>\n", fd);
+ ap_rputs("This server could not verify that you\n"
+ "are authorized to access the document\n"
+ "requested. Either you supplied the wrong\n"
+ "credentials (e.g., bad password), or your\n"
+ "browser doesn't understand how to supply\n"
+ "the credentials required.<P>\n", r);
break;
case BAD_REQUEST:
- ap_bputs("Your browser sent a request that\n", fd);
- ap_bputs("this server could not understand.<P>\n", fd);
+ ap_rputs("Your browser sent a request that "
+ "this server could not understand.<P>\n", r);
if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
- ap_bvputs(fd, error_notes, "<P>\n", NULL);
+ ap_rvputs(r, error_notes, "<P>\n", NULL);
}
break;
case HTTP_FORBIDDEN:
- ap_bvputs(fd, "You don't have permission to access ",
+ ap_rvputs(r, "You don't have permission to access ",
ap_escape_html(r->pool, r->uri),
"\non this server.<P>\n", NULL);
break;
case NOT_FOUND:
- ap_bvputs(fd, "The requested URL ",
+ ap_rvputs(r, "The requested URL ",
ap_escape_html(r->pool, r->uri),
" was not found on this server.<P>\n", NULL);
break;
case METHOD_NOT_ALLOWED:
- ap_bvputs(fd, "The requested method ", r->method,
+ ap_rvputs(r, "The requested method ", r->method,
" is not allowed "
"for the URL ", ap_escape_html(r->pool, r->uri),
".<P>\n", NULL);
break;
case NOT_ACCEPTABLE:
- ap_bvputs(fd,
+ ap_rvputs(r,
"An appropriate representation of the "
"requested resource ",
ap_escape_html(r->pool, r->uri),
@@ -2396,44 +2603,47 @@ void ap_send_error_response(request_rec *r, int recursive_error)
{
const char *list;
if ((list = ap_table_get(r->notes, "variant-list")))
- ap_bputs(list, fd);
+ ap_rputs(list, r);
}
break;
case LENGTH_REQUIRED:
- ap_bvputs(fd, "A request of the requested method ", r->method,
+ ap_rvputs(r, "A request of the requested method ", r->method,
" requires a valid Content-length.<P>\n", NULL);
if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
- ap_bvputs(fd, error_notes, "<P>\n", NULL);
+ ap_rvputs(r, error_notes, "<P>\n", NULL);
}
break;
case PRECONDITION_FAILED:
- ap_bvputs(fd, "The precondition on the request for the URL ",
+ ap_rvputs(r, "The precondition on the request for the URL ",
ap_escape_html(r->pool, r->uri),
" evaluated to false.<P>\n", NULL);
break;
case HTTP_NOT_IMPLEMENTED:
- ap_bvputs(fd, ap_escape_html(r->pool, r->method), " to ",
+ ap_rvputs(r, ap_escape_html(r->pool, r->method), " to ",
ap_escape_html(r->pool, r->uri),
" not supported.<P>\n", NULL);
if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
- ap_bvputs(fd, error_notes, "<P>\n", NULL);
+ ap_rvputs(r, error_notes, "<P>\n", NULL);
}
break;
case BAD_GATEWAY:
- ap_bputs("The proxy server received an invalid\015\012", fd);
- ap_bputs("response from an upstream server.<P>\015\012", fd);
+ ap_rputs("The proxy server received an invalid\015\012"
+ "response from an upstream server.<P>\015\012", r);
+ if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
+ ap_rvputs(r, error_notes, "<P>\n", NULL);
+ }
break;
case VARIANT_ALSO_VARIES:
- ap_bvputs(fd, "A variant for the requested resource\n<PRE>\n",
+ ap_rvputs(r, "A variant for the requested resource\n<PRE>\n",
ap_escape_html(r->pool, r->uri),
"\n</PRE>\nis itself a negotiable resource. "
"This indicates a configuration error.<P>\n", NULL);
break;
case HTTP_REQUEST_TIME_OUT:
- ap_bputs("I'm tired of waiting for your request.\n", fd);
+ ap_rputs("I'm tired of waiting for your request.\n", r);
break;
case HTTP_GONE:
- ap_bvputs(fd, "The requested resource<BR>",
+ ap_rvputs(r, "The requested resource<BR>",
ap_escape_html(r->pool, r->uri),
"<BR>\nis no longer available on this server ",
"and there is no forwarding address.\n",
@@ -2441,30 +2651,30 @@ void ap_send_error_response(request_rec *r, int recursive_error)
NULL);
break;
case HTTP_REQUEST_ENTITY_TOO_LARGE:
- ap_bvputs(fd, "The requested resource<BR>",
+ ap_rvputs(r, "The requested resource<BR>",
ap_escape_html(r->pool, r->uri), "<BR>\n",
"does not allow request data with ", r->method,
" requests, or the amount of data provided in\n",
"the request exceeds the capacity limit.\n", NULL);
break;
case HTTP_REQUEST_URI_TOO_LARGE:
- ap_bputs("The requested URL's length exceeds the capacity\n"
- "limit for this server.<P>\n", fd);
+ ap_rputs("The requested URL's length exceeds the capacity\n"
+ "limit for this server.<P>\n", r);
if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
- ap_bvputs(fd, error_notes, "<P>\n", NULL);
+ ap_rvputs(r, error_notes, "<P>\n", NULL);
}
break;
case HTTP_UNSUPPORTED_MEDIA_TYPE:
- ap_bputs("The supplied request data is not in a format\n"
- "acceptable for processing by this resource.\n", fd);
+ ap_rputs("The supplied request data is not in a format\n"
+ "acceptable for processing by this resource.\n", r);
break;
case HTTP_RANGE_NOT_SATISFIABLE:
- ap_bputs("None of the range-specifier values in the Range\n"
+ ap_rputs("None of the range-specifier values in the Range\n"
"request-header field overlap the current extent\n"
- "of the selected resource.\n", fd);
+ "of the selected resource.\n", r);
break;
case HTTP_EXPECTATION_FAILED:
- ap_bvputs(fd, "The expectation given in the Expect request-header"
+ ap_rvputs(r, "The expectation given in the Expect request-header"
"\nfield could not be met by this server.<P>\n"
"The client sent<PRE>\n Expect: ",
ap_table_get(r->headers_in, "Expect"), "\n</PRE>\n"
@@ -2472,42 +2682,55 @@ void ap_send_error_response(request_rec *r, int recursive_error)
NULL);
break;
case HTTP_UNPROCESSABLE_ENTITY:
- ap_bputs("The server understands the media type of the\n"
+ ap_rputs("The server understands the media type of the\n"
"request entity, but was unable to process the\n"
- "contained instructions.\n", fd);
+ "contained instructions.\n", r);
break;
case HTTP_LOCKED:
- ap_bputs("The requested resource is currently locked.\n"
+ ap_rputs("The requested resource is currently locked.\n"
"The lock must be released or proper identification\n"
- "given before the method can be applied.\n", fd);
+ "given before the method can be applied.\n", r);
break;
case HTTP_FAILED_DEPENDENCY:
- ap_bputs("The method could not be performed on the resource\n"
+ ap_rputs("The method could not be performed on the resource\n"
"because the requested action depended on another\n"
- "action and that other action failed.\n", fd);
+ "action and that other action failed.\n", r);
break;
case HTTP_INSUFFICIENT_STORAGE:
- ap_bputs("The method could not be performed on the resource\n"
+ ap_rputs("The method could not be performed on the resource\n"
"because the server is unable to store the\n"
"representation needed to successfully complete the\n"
"request. There is insufficient free space left in\n"
- "your storage allocation.\n", fd);
+ "your storage allocation.\n", r);
break;
case HTTP_SERVICE_UNAVAILABLE:
- ap_bputs("The server is temporarily unable to service your\n"
+ ap_rputs("The server is temporarily unable to service your\n"
"request due to maintenance downtime or capacity\n"
- "problems. Please try again later.\n", fd);
+ "problems. Please try again later.\n", r);
break;
case HTTP_GATEWAY_TIME_OUT:
- ap_bputs("The proxy server did not receive a timely response\n"
- "from the upstream server.\n", fd);
+ ap_rputs("The proxy server did not receive a timely response\n"
+ "from the upstream server.\n", r);
break;
case HTTP_NOT_EXTENDED:
- ap_bputs("A mandatory extension policy in the request is not\n"
- "accepted by the server for this resource.\n", fd);
+ ap_rputs("A mandatory extension policy in the request is not\n"
+ "accepted by the server for this resource.\n", r);
break;
default: /* HTTP_INTERNAL_SERVER_ERROR */
- ap_bvputs(fd, "The server encountered an internal error or\n"
+ /*
+ * This comparison to expose error-notes could be modified to
+ * use a configuration directive and export based on that
+ * directive. For now "*" is used to designate an error-notes
+ * that is totally safe for any user to see (ie lacks paths,
+ * database passwords, etc.)
+ */
+ if (((error_notes = ap_table_get(r->notes, "error-notes")) != NULL)
+ && (h1 = ap_table_get(r->notes, "verbose-error-to")) != NULL
+ && (strcmp(h1, "*") == 0)) {
+ ap_rvputs(r, error_notes, "<P>\n", NULL);
+ }
+ else {
+ ap_rvputs(r, "The server encountered an internal error or\n"
"misconfiguration and was unable to complete\n"
"your request.<P>\n"
"Please contact the server administrator,\n ",
@@ -2517,6 +2740,7 @@ void ap_send_error_response(request_rec *r, int recursive_error)
"caused the error.<P>\n"
"More information about this error may be available\n"
"in the server error log.<P>\n", NULL);
+ }
/*
* It would be nice to give the user the information they need to
* fix the problem directly since many users don't have access to
@@ -2527,21 +2751,22 @@ void ap_send_error_response(request_rec *r, int recursive_error)
* can figure out a way to remove the pathname, leave this commented.
*
* if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
- * ap_bvputs(fd, error_notes, "<P>\n", NULL);
+ * ap_rvputs(r, error_notes, "<P>\n", NULL);
* }
*/
break;
}
if (recursive_error) {
- ap_bvputs(fd, "<P>Additionally, a ",
+ ap_rvputs(r, "<P>Additionally, a ",
status_lines[ap_index_of_response(recursive_error)],
"\nerror was encountered while trying to use an "
"ErrorDocument to handle the request.\n", NULL);
}
- ap_bputs(ap_psignature("<HR>\n", r), fd);
- ap_bputs("</BODY></HTML>\n", fd);
+ ap_rputs(ap_psignature("<HR>\n", r), r);
+ ap_rputs("</BODY></HTML>\n", r);
}
ap_kill_timeout(r);
ap_finalize_request_protocol(r);
+ ap_rflush(r);
}
diff --git a/usr.sbin/httpd/src/main/http_request.c b/usr.sbin/httpd/src/main/http_request.c
index 693cf310648..e6f66316582 100644
--- a/usr.sbin/httpd/src/main/http_request.c
+++ b/usr.sbin/httpd/src/main/http_request.c
@@ -178,8 +178,8 @@ static int get_path_info(request_rec *r)
char *end = &path[strlen(path)];
char *last_cp = NULL;
int rv;
-#ifdef WIN32
- BOOL bStripSlash=TRUE;
+#ifdef HAVE_DRIVE_LETTERS
+ char bStripSlash=1;
#endif
if (r->finfo.st_mode) {
@@ -187,12 +187,12 @@ static int get_path_info(request_rec *r)
return OK;
}
-#ifdef WIN32
+#ifdef HAVE_DRIVE_LETTERS
/* If the directory is x:\, then we don't want to strip
* the trailing slash since x: is not a valid directory.
*/
if (strlen(path) == 3 && path[1] == ':' && path[2] == '/')
- bStripSlash = FALSE;
+ bStripSlash = 0;
/* If UNC name == //machine/share/, do not
@@ -211,7 +211,7 @@ static int get_path_info(request_rec *r)
}
if (iCount == 4)
- bStripSlash = FALSE;
+ bStripSlash = 0;
}
if (bStripSlash)
@@ -265,8 +265,12 @@ static int get_path_info(request_rec *r)
*cp = '\0';
return OK;
}
+ /* must set this to zero, some stat()s may have corrupted it
+ * even if they returned an error.
+ */
+ r->finfo.st_mode = 0;
#if defined(ENOENT) && defined(ENOTDIR)
- else if (errno == ENOENT || errno == ENOTDIR) {
+ if (errno == ENOENT || errno == ENOTDIR) {
last_cp = cp;
while (--cp > path && *cp != '/')
@@ -299,15 +303,13 @@ static int get_path_info(request_rec *r)
* you needed to do this. Please be sure to include the operating
* system you are using.
*/
- else {
- last_cp = cp;
+ last_cp = cp;
- while (--cp > path && *cp != '/')
- continue;
+ while (--cp > path && *cp != '/')
+ continue;
- while (cp > path && cp[-1] == '/')
- --cp;
- }
+ while (cp > path && cp[-1] == '/')
+ --cp;
#endif /* ENOENT && ENOTDIR */
}
return OK;
@@ -368,7 +370,7 @@ static int directory_walk(request_rec *r)
this_conf = NULL;
if (entry_core->r) {
- if (!regexec(entry_core->r, r->filename, 0, NULL, 0))
+ if (!ap_regexec(entry_core->r, r->filename, 0, NULL, 0))
this_conf = entry_config;
}
else if (entry_core->d_is_fnmatch) {
@@ -534,7 +536,7 @@ static int directory_walk(request_rec *r)
ap_get_module_config(entry_config, &core_module);
if (entry_core->r) {
- if (!regexec(entry_core->r, test_dirname, 0, NULL, REG_NOTEOL)) {
+ if (!ap_regexec(entry_core->r, test_dirname, 0, NULL, REG_NOTEOL)) {
per_dir_defaults =
ap_merge_per_dir_configs(r->pool, per_dir_defaults,
entry_config);
@@ -610,7 +612,7 @@ static int location_walk(request_rec *r)
this_conf = NULL;
if (entry_core->r) {
- if (!regexec(entry_core->r, r->uri, 0, NULL, 0))
+ if (!ap_regexec(entry_core->r, r->uri, 0, NULL, 0))
this_conf = entry_config;
}
else if (entry_core->d_is_fnmatch) {
@@ -671,7 +673,7 @@ static int file_walk(request_rec *r)
this_conf = NULL;
if (entry_core->r) {
- if (!regexec(entry_core->r, test_file, 0, NULL, 0))
+ if (!ap_regexec(entry_core->r, test_file, 0, NULL, 0))
this_conf = entry_config;
}
else if (entry_core->d_is_fnmatch) {
@@ -718,8 +720,9 @@ static request_rec *make_sub_request(const request_rec *r)
return rr;
}
-API_EXPORT(request_rec *) ap_sub_req_lookup_uri(const char *new_file,
- const request_rec *r)
+API_EXPORT(request_rec *) ap_sub_req_method_uri(const char *method,
+ const char *new_file,
+ const request_rec *r)
{
request_rec *rnew;
int res;
@@ -736,6 +739,10 @@ API_EXPORT(request_rec *) ap_sub_req_lookup_uri(const char *new_file,
ap_set_sub_req_protocol(rnew, r);
+ /* would be nicer to pass "method" to ap_set_sub_req_protocol */
+ rnew->method = method;
+ rnew->method_number = ap_method_number_of(method);
+
if (new_file[0] == '/')
ap_parse_uri(rnew, new_file);
else {
@@ -796,6 +803,12 @@ API_EXPORT(request_rec *) ap_sub_req_lookup_uri(const char *new_file,
return rnew;
}
+API_EXPORT(request_rec *) ap_sub_req_lookup_uri(const char *new_file,
+ const request_rec *r)
+{
+ return ap_sub_req_method_uri("GET", new_file, r);
+}
+
API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file,
const request_rec *r)
{
@@ -1298,6 +1311,7 @@ static request_rec *internal_internal_redirect(const char *new_uri, request_rec
new->htaccess = r->htaccess;
new->no_cache = r->no_cache;
+ new->expecting_100 = r->expecting_100;
new->no_local_copy = r->no_local_copy;
new->read_length = r->read_length; /* We can only read it once */
new->vlist_validator = r->vlist_validator;
diff --git a/usr.sbin/httpd/src/main/rfc1413.c b/usr.sbin/httpd/src/main/rfc1413.c
index 1c60a7ddab3..65bc6ef4d07 100644
--- a/usr.sbin/httpd/src/main/rfc1413.c
+++ b/usr.sbin/httpd/src/main/rfc1413.c
@@ -147,6 +147,9 @@ static int get_rfc1413(int sock, const struct sockaddr_in *our_sin,
ntohs(our_sin->sin_port));
/* send query to server. Handle short write. */
+#ifdef CHARSET_EBCDIC
+ ebcdic2ascii(&buffer, &buffer, buflen);
+#endif
i = 0;
while(i < strlen(buffer)) {
int j;
@@ -168,8 +171,12 @@ static int get_rfc1413(int sock, const struct sockaddr_in *our_sin,
*/
i = 0;
- memset(buffer, 0, sizeof(buffer));
- while((cp = strchr(buffer, '\n')) == NULL && i < sizeof(buffer) - 1) {
+ memset(buffer, '\0', sizeof(buffer));
+ /*
+ * Note that the strchr function below checks for 10 instead of '\n'
+ * this allows it to work on both ASCII and EBCDIC machines.
+ */
+ while((cp = strchr(buffer, '\012')) == NULL && i < sizeof(buffer) - 1) {
int j;
j = read(sock, buffer+i, (sizeof(buffer) - 1) - i);
if (j < 0 && errno != EINTR) {
@@ -183,6 +190,9 @@ static int get_rfc1413(int sock, const struct sockaddr_in *our_sin,
}
/* RFC1413_USERLEN = 512 */
+#ifdef CHARSET_EBCDIC
+ ascii2ebcdic(&buffer, &buffer, (size_t)i);
+#endif
if (sscanf(buffer, "%u , %u : USERID :%*[^:]:%512s", &rmt_port, &our_port,
user) != 3 || ntohs(rmt_sin->sin_port) != rmt_port
|| ntohs(our_sin->sin_port) != our_port)
diff --git a/usr.sbin/httpd/src/main/util.c b/usr.sbin/httpd/src/main/util.c
index 81b40ca4055..b358501c077 100644
--- a/usr.sbin/httpd/src/main/util.c
+++ b/usr.sbin/httpd/src/main/util.c
@@ -119,6 +119,26 @@ API_EXPORT(char *) ap_get_time()
return (time_string);
}
+/*
+ * Examine a field value (such as a media-/content-type) string and return
+ * it sans any parameters; e.g., strip off any ';charset=foo' and the like.
+ */
+API_EXPORT(char *) ap_field_noparam(pool *p, const char *intype)
+{
+ const char *semi;
+
+ semi = strchr(intype, ';');
+ if (semi == NULL) {
+ return ap_pstrdup(p, intype);
+ }
+ else {
+ while ((semi > intype) && ap_isspace(semi[-1])) {
+ semi--;
+ }
+ return ap_pstrndup(p, intype, semi - intype);
+ }
+}
+
API_EXPORT(char *) ap_ht_time(pool *p, time_t t, const char *fmt, int gmt)
{
char ts[MAX_STRING_LEN];
@@ -281,9 +301,27 @@ API_EXPORT(int) ap_is_matchexp(const char *str)
return 0;
}
+/*
+ * Apache stub function for the regex libraries regexec() to make sure the
+ * whole regex(3) API is available through the Apache (exported) namespace.
+ * This is especially important for the DSO situations of modules.
+ * DO NOT MAKE A MACRO OUT OF THIS FUNCTION!
+ */
+API_EXPORT(int) ap_regexec(const regex_t *preg, const char *string,
+ size_t nmatch, regmatch_t pmatch[], int eflags)
+{
+ return regexec(preg, string, nmatch, pmatch, eflags);
+}
+
+API_EXPORT(size_t) ap_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
+{
+ return regerror(errcode, preg, errbuf, errbuf_size);
+}
+
+
/* This function substitutes for $0-$9, filling in regular expression
* submatches. Pass it the same nmatch and pmatch arguments that you
- * passed regexec(). pmatch should not be greater than the maximum number
+ * passed ap_regexec(). pmatch should not be greater than the maximum number
* of subexpressions - i.e. one more than the re_nsub member of regex_t.
*
* input should be the string with the $-expressions, source should be the
@@ -877,8 +915,8 @@ API_EXPORT(int) ap_cfg_getline(char *buf, size_t bufsize, configfile_t *cfp)
* line continuation requested -
* then remove backslash and continue
*/
- cbuf = cp;
cbufsize -= (cp-cbuf);
+ cbuf = cp;
continue;
}
else {
@@ -978,6 +1016,258 @@ API_EXPORT(int) ap_cfg_getline(char *buf, size_t bufsize, configfile_t *cfp)
}
}
+/* Size an HTTP header field list item, as separated by a comma.
+ * The return value is a pointer to the beginning of the non-empty list item
+ * within the original string (or NULL if there is none) and the address
+ * of field is shifted to the next non-comma, non-whitespace character.
+ * len is the length of the item excluding any beginning whitespace.
+ */
+API_EXPORT(const char *) ap_size_list_item(const char **field, int *len)
+{
+ const unsigned char *ptr = (const unsigned char *)*field;
+ const unsigned char *token;
+ int in_qpair, in_qstr, in_com;
+
+ /* Find first non-comma, non-whitespace byte */
+
+ while (*ptr == ',' || ap_isspace(*ptr))
+ ++ptr;
+
+ token = ptr;
+
+ /* Find the end of this item, skipping over dead bits */
+
+ for (in_qpair = in_qstr = in_com = 0;
+ *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
+ ++ptr) {
+
+ if (in_qpair) {
+ in_qpair = 0;
+ }
+ else {
+ switch (*ptr) {
+ case '\\': in_qpair = 1; /* quoted-pair */
+ break;
+ case '"' : if (!in_com) /* quoted string delim */
+ in_qstr = !in_qstr;
+ break;
+ case '(' : if (!in_qstr) /* comment (may nest) */
+ ++in_com;
+ break;
+ case ')' : if (in_com) /* end comment */
+ --in_com;
+ break;
+ default : break;
+ }
+ }
+ }
+
+ if ((*len = (ptr - token)) == 0) {
+ *field = (const char *)ptr;
+ return NULL;
+ }
+
+ /* Advance field pointer to the next non-comma, non-white byte */
+
+ while (*ptr == ',' || ap_isspace(*ptr))
+ ++ptr;
+
+ *field = (const char *)ptr;
+ return (const char *)token;
+}
+
+/* Retrieve an HTTP header field list item, as separated by a comma,
+ * while stripping insignificant whitespace and lowercasing anything not in
+ * a quoted string or comment. The return value is a new string containing
+ * the converted list item (or NULL if none) and the address pointed to by
+ * field is shifted to the next non-comma, non-whitespace.
+ */
+API_EXPORT(char *) ap_get_list_item(pool *p, const char **field)
+{
+ const char *tok_start;
+ const unsigned char *ptr;
+ unsigned char *pos;
+ char *token;
+ int addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0, tok_len = 0;
+
+ /* Find the beginning and maximum length of the list item so that
+ * we can allocate a buffer for the new string and reset the field.
+ */
+ if ((tok_start = ap_size_list_item(field, &tok_len)) == NULL) {
+ return NULL;
+ }
+ token = ap_palloc(p, tok_len + 1);
+
+ /* Scan the token again, but this time copy only the good bytes.
+ * We skip extra whitespace and any whitespace around a '=', '/',
+ * or ';' and lowercase normal characters not within a comment,
+ * quoted-string or quoted-pair.
+ */
+ for (ptr = (const unsigned char *)tok_start, pos = (unsigned char *)token;
+ *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
+ ++ptr) {
+
+ if (in_qpair) {
+ in_qpair = 0;
+ *pos++ = *ptr;
+ }
+ else {
+ switch (*ptr) {
+ case '\\': in_qpair = 1;
+ if (addspace == 1)
+ *pos++ = ' ';
+ *pos++ = *ptr;
+ addspace = 0;
+ break;
+ case '"' : if (!in_com)
+ in_qstr = !in_qstr;
+ if (addspace == 1)
+ *pos++ = ' ';
+ *pos++ = *ptr;
+ addspace = 0;
+ break;
+ case '(' : if (!in_qstr)
+ ++in_com;
+ if (addspace == 1)
+ *pos++ = ' ';
+ *pos++ = *ptr;
+ addspace = 0;
+ break;
+ case ')' : if (in_com)
+ --in_com;
+ *pos++ = *ptr;
+ addspace = 0;
+ break;
+ case ' ' :
+ case '\t': if (addspace)
+ break;
+ if (in_com || in_qstr)
+ *pos++ = *ptr;
+ else
+ addspace = 1;
+ break;
+ case '=' :
+ case '/' :
+ case ';' : if (!(in_com || in_qstr))
+ addspace = -1;
+ *pos++ = *ptr;
+ break;
+ default : if (addspace == 1)
+ *pos++ = ' ';
+ *pos++ = (in_com || in_qstr) ? *ptr
+ : ap_tolower(*ptr);
+ addspace = 0;
+ break;
+ }
+ }
+ }
+ *pos = '\0';
+
+ return token;
+}
+
+/* Find an item in canonical form (lowercase, no extra spaces) within
+ * an HTTP field value list. Returns 1 if found, 0 if not found.
+ * This would be much more efficient if we stored header fields as
+ * an array of list items as they are received instead of a plain string.
+ */
+API_EXPORT(int) ap_find_list_item(pool *p, const char *line, const char *tok)
+{
+ const unsigned char *pos;
+ const unsigned char *ptr = (const unsigned char *)line;
+ int good = 0, addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0;
+
+ if (!line || !tok)
+ return 0;
+
+ do { /* loop for each item in line's list */
+
+ /* Find first non-comma, non-whitespace byte */
+
+ while (*ptr == ',' || ap_isspace(*ptr))
+ ++ptr;
+
+ if (*ptr)
+ good = 1; /* until proven otherwise for this item */
+ else
+ break; /* no items left and nothing good found */
+
+ /* We skip extra whitespace and any whitespace around a '=', '/',
+ * or ';' and lowercase normal characters not within a comment,
+ * quoted-string or quoted-pair.
+ */
+ for (pos = (const unsigned char *)tok;
+ *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
+ ++ptr) {
+
+ if (in_qpair) {
+ in_qpair = 0;
+ if (good)
+ good = (*pos++ == *ptr);
+ }
+ else {
+ switch (*ptr) {
+ case '\\': in_qpair = 1;
+ if (addspace == 1)
+ good = good && (*pos++ == ' ');
+ good = good && (*pos++ == *ptr);
+ addspace = 0;
+ break;
+ case '"' : if (!in_com)
+ in_qstr = !in_qstr;
+ if (addspace == 1)
+ good = good && (*pos++ == ' ');
+ good = good && (*pos++ == *ptr);
+ addspace = 0;
+ break;
+ case '(' : if (!in_qstr)
+ ++in_com;
+ if (addspace == 1)
+ good = good && (*pos++ == ' ');
+ good = good && (*pos++ == *ptr);
+ addspace = 0;
+ break;
+ case ')' : if (in_com)
+ --in_com;
+ good = good && (*pos++ == *ptr);
+ addspace = 0;
+ break;
+ case ' ' :
+ case '\t': if (addspace || !good)
+ break;
+ if (in_com || in_qstr)
+ good = (*pos++ == *ptr);
+ else
+ addspace = 1;
+ break;
+ case '=' :
+ case '/' :
+ case ';' : if (!(in_com || in_qstr))
+ addspace = -1;
+ good = good && (*pos++ == *ptr);
+ break;
+ default : if (!good)
+ break;
+ if (addspace == 1)
+ good = (*pos++ == ' ');
+ if (in_com || in_qstr)
+ good = good && (*pos++ == *ptr);
+ else
+ good = good && (*pos++ == ap_tolower(*ptr));
+ addspace = 0;
+ break;
+ }
+ }
+ }
+ if (good && *pos)
+ good = 0; /* not good if only a prefix was matched */
+
+ } while (*ptr && !good);
+
+ return good;
+}
+
+
/* Retrieve a token, spacing over it and returning a pointer to
* the first non-white byte afterwards. Note that these tokens
* are delimited by semis and commas; and can also be delimited
@@ -1146,7 +1436,7 @@ API_EXPORT(int) ap_unescape_url(char *url)
if (url[y] != '%')
url[x] = url[y];
else {
- if (!isxdigit(url[y + 1]) || !isxdigit(url[y + 2])) {
+ if (!ap_isxdigit(url[y + 1]) || !ap_isxdigit(url[y + 2])) {
badesc = 1;
url[x] = '%';
}
@@ -1373,8 +1663,10 @@ char *strdup(const char *str)
{
char *sdup;
- if (!(sdup = (char *) malloc(strlen(str) + 1)))
+ if (!(sdup = (char *) malloc(strlen(str) + 1))) {
+ fprintf(stderr, "Ouch! Out of memory in our strdup()!\n");
return NULL;
+ }
sdup = strcpy(sdup, str);
return sdup;
@@ -1454,7 +1746,7 @@ char *strstr(char *s1, char *s2)
#ifdef NEED_INITGROUPS
int initgroups(const char *name, gid_t basegid)
{
-#if defined(QNX) || defined(MPE) || defined(BEOS) || defined(_OSD_POSIX) || defined(TPF)
+#if defined(QNX) || defined(MPE) || defined(BEOS) || defined(_OSD_POSIX) || defined(TPF) || defined(__TANDEM)
/* QNX, MPE and BeOS do not appear to support supplementary groups. */
return 0;
#else /* ndef QNX */
@@ -1646,7 +1938,11 @@ char *ap_get_local_host(pool *a)
char *server_hostname;
struct hostent *p;
+#ifdef BEOS /* BeOS returns zero as an error for gethostname */
+ if (gethostname(str, sizeof(str) - 1) == 0) {
+#else
if (gethostname(str, sizeof(str) - 1) != 0) {
+#endif /* BeOS */
perror("Unable to gethostname");
exit(1);
}
@@ -1661,125 +1957,43 @@ char *ap_get_local_host(pool *a)
return server_hostname;
}
-/* aaaack but it's fast and const should make it shared text page. */
-static const unsigned char pr2six[256] =
-{
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54,
- 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3,
- 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32,
- 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
-};
-
-API_EXPORT(char *) ap_uudecode(pool *p, const char *bufcoded)
+/* simple 'pool' alloc()ing glue to ap_base64.c
+ */
+API_EXPORT(char *) ap_pbase64decode(pool *p, const char *bufcoded)
{
- int nbytesdecoded;
- register const unsigned char *bufin;
- register char *bufplain;
- register unsigned char *bufout;
- register int nprbytes;
+ char *decoded;
+ int l;
- /* Strip leading whitespace. */
+ decoded = (char *) ap_palloc(p, 1 + ap_base64decode_len(bufcoded));
+ l = ap_base64decode(decoded, bufcoded);
+ decoded[l] = '\0'; /* make binary sequence into string */
- while (*bufcoded == ' ' || *bufcoded == '\t')
- bufcoded++;
+ return decoded;
+}
- /* Figure out how many characters are in the input buffer.
- * Allocate this many from the per-transaction pool for the result.
- */
-#ifndef CHARSET_EBCDIC
- bufin = (const unsigned char *) bufcoded;
- while (pr2six[*(bufin++)] <= 63);
- nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
- nbytesdecoded = ((nprbytes + 3) / 4) * 3;
-
- bufplain = ap_palloc(p, nbytesdecoded + 1);
- bufout = (unsigned char *) bufplain;
-
- bufin = (const unsigned char *) bufcoded;
-
- while (nprbytes > 0) {
- *(bufout++) =
- (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
- *(bufout++) =
- (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
- *(bufout++) =
- (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
- bufin += 4;
- nprbytes -= 4;
- }
-
- if (nprbytes & 03) {
- if (pr2six[bufin[-2]] > 63)
- nbytesdecoded -= 2;
- else
- nbytesdecoded -= 1;
- }
- bufplain[nbytesdecoded] = '\0';
-#else /*CHARSET_EBCDIC*/
- bufin = (const unsigned char *) bufcoded;
- while (pr2six[os_toascii[(unsigned char)*(bufin++)]] <= 63);
- nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
- nbytesdecoded = ((nprbytes + 3) / 4) * 3;
-
- bufplain = ap_palloc(p, nbytesdecoded + 1);
- bufout = (unsigned char *) bufplain;
-
- bufin = (const unsigned char *) bufcoded;
-
- while (nprbytes > 0) {
- *(bufout++) = os_toebcdic[
- (unsigned char) (pr2six[os_toascii[*bufin]] << 2 | pr2six[os_toascii[bufin[1]]] >> 4)];
- *(bufout++) = os_toebcdic[
- (unsigned char) (pr2six[os_toascii[bufin[1]]] << 4 | pr2six[os_toascii[bufin[2]]] >> 2)];
- *(bufout++) = os_toebcdic[
- (unsigned char) (pr2six[os_toascii[bufin[2]]] << 6 | pr2six[os_toascii[bufin[3]]])];
- bufin += 4;
- nprbytes -= 4;
- }
-
- if (nprbytes & 03) {
- if (pr2six[os_toascii[bufin[-2]]] > 63)
- nbytesdecoded -= 2;
- else
- nbytesdecoded -= 1;
- }
- bufplain[nbytesdecoded] = '\0';
-#endif /*CHARSET_EBCDIC*/
- return bufplain;
+API_EXPORT(char *) ap_pbase64encode(pool *p, char *string)
+{
+ char *encoded;
+ int l = strlen(string);
+
+ encoded = (char *) ap_palloc(p, 1 + ap_base64encode_len(l));
+ l = ap_base64encode(encoded, string, l);
+ encoded[l] = '\0'; /* make binary sequence into string */
+
+ return encoded;
}
-static const char basis_64[] =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-API_EXPORT(char *) ap_uuencode(pool *a, char *string)
+/* deprecated names for the above two functions, here for compatibility
+ */
+API_EXPORT(char *) ap_uudecode(pool *p, const char *bufcoded)
+{
+ return ap_pbase64decode(p, bufcoded);
+}
+
+API_EXPORT(char *) ap_uuencode(pool *p, char *string)
{
- int i, len = strlen(string);
- char *p;
- char *encoded = (char *) ap_pcalloc(a, (len+2) / 3 * 4);
-
- p = encoded;
- for (i = 0; i < len; i += 3) {
- *p++ = basis_64[string[i] >> 2];
- *p++ = basis_64[((string[i] & 0x3) << 4) | ((int) (string[i + 1] & 0xF0) >> 4)];
- *p++ = basis_64[((string[i + 1] & 0xF) << 2) | ((int) (string[i + 2] & 0xC0) >> 6)];
- *p++ = basis_64[string[i + 2] & 0x3F];
- }
- *p-- = '\0';
- *p-- = '=';
- *p-- = '=';
- return encoded;
-}
+ return ap_pbase64encode(p, string);
+}
#ifdef OS2
void os2pathname(char *path)
@@ -1806,6 +2020,32 @@ void os2pathname(char *path)
strcpy(path, newpath);
};
+
+/* quotes in the string are doubled up.
+ * Used to escape quotes in args passed to OS/2's cmd.exe
+ */
+char *ap_double_quotes(pool *p, char *str)
+{
+ int num_quotes = 0;
+ int len = 0;
+ char *quote_doubled_str, *dest;
+
+ while (str[len]) {
+ num_quotes += str[len++] == '\"';
+ }
+
+ quote_doubled_str = ap_palloc(p, len + num_quotes + 1);
+ dest = quote_doubled_str;
+
+ while (*str) {
+ if (*str == '\"')
+ *(dest++) = '\"';
+ *(dest++) = *(str++);
+ }
+
+ *dest = 0;
+ return quote_doubled_str;
+}
#endif
@@ -1877,6 +2117,7 @@ API_EXPORT(char *) ap_escape_quotes (pool *p, const char *instring)
*/
if ((*inchr == '\\') && (inchr[1] != '\0')) {
inchr++;
+ newlen++;
}
inchr++;
}
diff --git a/usr.sbin/httpd/src/main/util_date.c b/usr.sbin/httpd/src/main/util_date.c
index 933079cc3f3..5111a600f0d 100644
--- a/usr.sbin/httpd/src/main/util_date.c
+++ b/usr.sbin/httpd/src/main/util_date.c
@@ -109,7 +109,7 @@ API_EXPORT(int) ap_checkmask(const char *data, const char *mask)
return 0;
break;
case '&':
- if (!isxdigit(d))
+ if (!ap_isxdigit(d))
return 0;
break;
case '~':
diff --git a/usr.sbin/httpd/src/main/util_md5.c b/usr.sbin/httpd/src/main/util_md5.c
index 7700de7af79..368ddf63b23 100644
--- a/usr.sbin/httpd/src/main/util_md5.c
+++ b/usr.sbin/httpd/src/main/util_md5.c
@@ -100,7 +100,7 @@ API_EXPORT(char *) ap_md5_binary(pool *p, const unsigned char *buf, int length)
*/
ap_MD5Init(&my_md5);
- ap_MD5Update(&my_md5, buf, length);
+ ap_MD5Update(&my_md5, buf, (unsigned int)length);
ap_MD5Final(hash, &my_md5);
for (i = 0, r = result; i < 16; i++) {
@@ -114,7 +114,7 @@ API_EXPORT(char *) ap_md5_binary(pool *p, const unsigned char *buf, int length)
API_EXPORT(char *) ap_md5(pool *p, const unsigned char *string)
{
- return ap_md5_binary(p, string, strlen(string));
+ return ap_md5_binary(p, string, (int) strlen((char *)string));
}
/* these portions extracted from mpack, John G. Myers - jgm+@cmu.edu */
@@ -187,7 +187,9 @@ API_EXPORT(char *) ap_md5contextTo64(pool *a, AP_MD5_CTX * context)
return encodedDigest;
}
-API_EXPORT(char *) ap_md5digest(pool *p, FILE *infile)
+#ifdef CHARSET_EBCDIC
+
+API_EXPORT(char *) ap_md5digest(pool *p, FILE *infile, int convert)
{
AP_MD5_CTX context;
unsigned char buf[1000];
@@ -196,9 +198,32 @@ API_EXPORT(char *) ap_md5digest(pool *p, FILE *infile)
ap_MD5Init(&context);
while ((nbytes = fread(buf, 1, sizeof(buf), infile))) {
+ length += nbytes;
+ if (!convert) {
+ ascii2ebcdic(buf, buf, nbytes);
+ }
+ ap_MD5Update(&context, buf, nbytes);
+ }
+ rewind(infile);
+ return ap_md5contextTo64(p, &context);
+}
+
+#else
+
+API_EXPORT(char *) ap_md5digest(pool *p, FILE *infile)
+{
+ AP_MD5_CTX context;
+ unsigned char buf[1000];
+ long length = 0;
+ unsigned int nbytes;
+
+ ap_MD5Init(&context);
+ while ((nbytes = fread(buf, 1, sizeof(buf), infile))) {
length += nbytes;
ap_MD5Update(&context, buf, nbytes);
}
rewind(infile);
return ap_md5contextTo64(p, &context);
}
+
+#endif /* CHARSET_EBCDIC */
diff --git a/usr.sbin/httpd/src/main/util_script.c b/usr.sbin/httpd/src/main/util_script.c
index 48f7b96cc18..467dd2964c1 100644
--- a/usr.sbin/httpd/src/main/util_script.c
+++ b/usr.sbin/httpd/src/main/util_script.c
@@ -67,6 +67,11 @@
#include "util_script.h"
#include "util_date.h" /* For parseHTTPdate() */
+#ifdef OS2
+#define INCL_DOS
+#include <os2.h>
+#endif
+
/*
* Various utility functions which are common to a whole lot of
* script-type extensions mechanisms, and might as well be gathered
@@ -265,6 +270,7 @@ API_EXPORT(void) ap_add_common_vars(request_rec *r)
ap_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r));
ap_table_addn(e, "SERVER_SOFTWARE", ap_get_server_version());
ap_table_addn(e, "SERVER_NAME", ap_get_server_name(r));
+ ap_table_addn(e, "SERVER_ADDR", r->connection->local_ip); /* Apache */
ap_table_addn(e, "SERVER_PORT",
ap_psprintf(r->pool, "%u", ap_get_server_port(r)));
host = ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST);
@@ -496,6 +502,8 @@ API_EXPORT(int) ap_scan_script_header_err_core(request_rec *r, char *buffer,
ap_overlap_tables(r->err_headers_out, merge,
AP_OVERLAP_TABLES_MERGE);
if (!ap_is_empty_table(cookie_table)) {
+ /* the cookies have already been copied to the cookie_table */
+ ap_table_unset(r->err_headers_out, "Set-Cookie");
r->err_headers_out = ap_overlay_tables(r->pool,
r->err_headers_out, cookie_table);
}
@@ -693,7 +701,7 @@ API_EXPORT(int) ap_call_exec(request_rec *r, child_info *pinfo, char *argv0,
#endif
-#ifndef WIN32
+#if !defined(WIN32) && !defined(OS2)
/* the fd on r->server->error_log is closed, but we need somewhere to
* put the error messages from the log_* functions. So, we use stderr,
* since that is better than allowing errors to go unnoticed. Don't do
@@ -747,174 +755,222 @@ API_EXPORT(int) ap_call_exec(request_rec *r, child_info *pinfo, char *argv0,
#ifdef OS2
{
/* Additions by Alec Kloss, to allow exec'ing of scripts under OS/2 */
- int is_script;
+ int is_script = 0;
char interpreter[2048]; /* hope it's enough for the interpreter path */
+ char error_object[260];
FILE *program;
-
+ char *cmdline = r->filename, *cmdline_pos;
+ int cmdlen;
+ char *args = "", *args_end;
+ ULONG rc;
+ RESULTCODES rescodes;
+ int env_len, e;
+ char *env_block, *env_block_pos;
+
+ if (r->args && r->args[0] && !strchr(r->args, '='))
+ args = r->args;
+
program = fopen(r->filename, "rt");
+
if (!program) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "fopen(%s) failed",
r->filename);
return (pid);
}
+
fgets(interpreter, sizeof(interpreter), program);
fclose(program);
+
if (!strncmp(interpreter, "#!", 2)) {
is_script = 1;
- interpreter[strlen(interpreter) - 1] = '\0';
+ interpreter[strlen(interpreter) - 1] = '\0';
+ if (interpreter[2] != '/' && interpreter[2] != '\\' && interpreter[3] != ':') {
+ char buffer[300];
+ if (DosSearchPath(SEARCH_ENVIRONMENT, "PATH", interpreter+2, buffer, sizeof(buffer)) == 0) {
+ strcpy(interpreter+2, buffer);
+ } else {
+ strcat(interpreter, ".exe");
+ if (DosSearchPath(SEARCH_ENVIRONMENT, "PATH", interpreter+2, buffer, sizeof(buffer)) == 0) {
+ strcpy(interpreter+2, buffer);
+ }
+ }
+ }
}
- else {
- is_script = 0;
+
+ if (is_script) {
+ cmdline = ap_pstrcat(r->pool, interpreter+2, " ", r->filename, NULL);
+ }
+ else if (strstr(strupr(r->filename), ".CMD") > 0) {
+ /* Special case to allow use of REXX commands as scripts. */
+ os2pathname(r->filename);
+ cmdline = ap_pstrcat(r->pool, SHELL_PATH, " /C ", r->filename, NULL);
+ }
+ else {
+ cmdline = r->filename;
}
+
+ args = ap_pstrdup(r->pool, args);
+ ap_unescape_url(args);
+ args = ap_double_quotes(r->pool, args);
+ args_end = args + strlen(args);
+
+ if (args_end - args > 4000) { /* cmd.exe won't handle lines longer than 4k */
+ args_end = args + 4000;
+ *args_end = 0;
+ }
- if ((!r->args) || (!r->args[0]) || strchr(r->args, '=')) {
- int emxloop;
- char *emxtemp;
+ /* +4 = 1 space between progname and args, 2 for double null at end, 2 for possible quote on first arg */
+ cmdlen = strlen(cmdline) + strlen(args) + 4;
+ cmdline_pos = cmdline;
- /* For OS/2 place the variables in the current
- * environment then it will be inherited. This way
- * the program will also get all of OS/2's other SETs.
- */
- for (emxloop = 0; ((emxtemp = env[emxloop]) != NULL); emxloop++) {
- putenv(emxtemp);
- }
+ while (*cmdline_pos) {
+ cmdlen += 2 * (*cmdline_pos == '+'); /* Allow space for each arg to be quoted */
+ cmdline_pos++;
+ }
- /* More additions by Alec Kloss for OS/2 */
- if (is_script) {
- /* here's the stuff to run the interpreter */
- execl(interpreter + 2, interpreter + 2, r->filename, NULL);
- }
- else if (strstr(strupr(r->filename), ".CMD") > 0) {
- /* Special case to allow use of REXX commands as scripts. */
- os2pathname(r->filename);
- execl(SHELL_PATH, SHELL_PATH, "/C", r->filename, NULL);
- }
- else {
- execl(r->filename, argv0, NULL);
- }
+ cmdline = ap_pstrndup(r->pool, cmdline, cmdlen);
+ cmdline_pos = cmdline + strlen(cmdline);
+
+ while (args < args_end) {
+ char *arg;
+
+ arg = ap_getword_nc(r->pool, &args, '+');
+
+ if (strpbrk(arg, "&|<> "))
+ arg = ap_pstrcat(r->pool, "\"", arg, "\"", NULL);
+
+ *(cmdline_pos++) = ' ';
+ strcpy(cmdline_pos, arg);
+ cmdline_pos += strlen(cmdline_pos);
+ }
+
+ *(++cmdline_pos) = 0; /* Add required second terminator */
+ args = strchr(cmdline, ' ');
+
+ if (args) {
+ *args = 0;
+ args++;
}
- else {
- int emxloop;
- char *emxtemp;
- /* For OS/2 place the variables in the current
- * environment so that they will be inherited. This way
- * the program will also get all of OS/2's other SETs.
- */
- for (emxloop = 0; ((emxtemp = env[emxloop]) != NULL); emxloop++) {
- putenv(emxtemp);
- }
+ /* Create environment block from list of envariables */
+ for (env_len=1, e=0; env[e]; e++)
+ env_len += strlen(env[e]) + 1;
- if (strstr(strupr(r->filename), ".CMD") > 0) {
- /* Special case to allow use of REXX commands as scripts. */
- os2pathname(r->filename);
- execv(SHELL_PATH, create_argv_cmd(r->pool, argv0, r->args,
- r->filename));
- }
- else {
- execv(r->filename,
- create_argv(r->pool, NULL, NULL, NULL, argv0, r->args));
- }
+ env_block = ap_palloc(r->pool, env_len);
+ env_block_pos = env_block;
+
+ for (e=0; env[e]; e++) {
+ strcpy(env_block_pos, env[e]);
+ env_block_pos += strlen(env_block_pos) + 1;
+ }
+
+ *env_block_pos = 0; /* environment block is terminated by a double null */
+
+ rc = DosExecPgm(error_object, sizeof(error_object), EXEC_ASYNC, cmdline, env_block, &rescodes, cmdline);
+
+ if (rc) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "DosExecPgm(%s %s) failed, %s - %s",
+ cmdline, args ? args : "", ap_os_error_message(rc), error_object );
+ return -1;
}
- return (pid);
+
+ return rescodes.codeTerminate;
}
#elif defined(WIN32)
{
- /* Adapted from Alec Kloss' work for OS/2 */
- int is_script = 0;
- int is_binary = 0;
- char interpreter[2048]; /* hope it's enough for the interpreter path */
- FILE *program;
- int i, sz;
- char *dot;
- char *exename;
+ /* Adapted from Alec Kloss' work for OS/2 */
+ char *interpreter = NULL;
+ char *arguments = NULL;
+ char *ext = NULL;
+ char *exename = NULL;
+ char *s = NULL;
char *quoted_filename;
- int is_exe = 0;
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
char *pCommand;
char *pEnvBlock, *pNext;
+
+ int i;
int iEnvBlockLen;
- memset(&si, 0, sizeof(si));
- memset(&pi, 0, sizeof(pi));
+ file_type_e fileType;
+
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
- interpreter[0] = 0;
- pid = -1;
+ memset(&si, 0, sizeof(si));
+ memset(&pi, 0, sizeof(pi));
- quoted_filename = ap_pstrcat(r->pool, "\"", r->filename, "\"", NULL);
+ pid = -1;
if (!shellcmd) {
- exename = strrchr(r->filename, '/');
- if (!exename) {
- exename = strrchr(r->filename, '\\');
- }
- if (!exename) {
- exename = r->filename;
- }
- else {
- exename++;
- }
- dot = strrchr(exename, '.');
- if (dot) {
- if (!strcasecmp(dot, ".BAT")
- || !strcasecmp(dot, ".CMD")
- || !strcasecmp(dot, ".EXE")
- || !strcasecmp(dot, ".COM")) {
- is_exe = 1;
- }
+
+ fileType = ap_get_win32_interpreter(r, &interpreter);
+
+ if (fileType == eFileTypeUNKNOWN) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
+ "%s is not executable; ensure interpreted scripts have "
+ "\"#!\" first line",
+ r->filename);
+ return (pid);
}
- if (!is_exe) {
- program = fopen(r->filename, "rb");
- if (!program) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
- "fopen(%s) failed", r->filename);
- return (pid);
- }
- sz = fread(interpreter, 1, sizeof(interpreter) - 1, program);
- if (sz < 0) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
- "fread of %s failed", r->filename);
- fclose(program);
- return (pid);
- }
- interpreter[sz] = 0;
- fclose(program);
- if (!strncmp(interpreter, "#!", 2)) {
- is_script = 1;
- for (i = 2; i < sizeof(interpreter); i++) {
- if ((interpreter[i] == '\r')
- || (interpreter[i] == '\n')) {
- break;
- }
- }
- interpreter[i] = 0;
- for (i = 2; interpreter[i] == ' '; ++i)
- ;
- memmove(interpreter+2,interpreter+i,strlen(interpreter+i)+1);
- }
- else {
- /* Check to see if it's a executable */
- IMAGE_DOS_HEADER *hdr = (IMAGE_DOS_HEADER*)interpreter;
- if (hdr->e_magic == IMAGE_DOS_SIGNATURE && hdr->e_cblp < 512) {
- is_binary = 1;
+ /*
+ * Look at the arguments...
+ */
+ arguments = "";
+ if ((r->args) && (r->args[0]) && !strchr(r->args, '=')) {
+ /* If we are in this leg, there are some other arguments
+ * that we must include in the execution of the CGI.
+ * Because CreateProcess is the way it is, we have to
+ * create a command line like format for the execution
+ * of the CGI. This means we need to create on long
+ * string with the executable and arguments.
+ *
+ * The arguments string comes in the request structure,
+ * and each argument is separated by a '+'. We'll replace
+ * these pluses with spaces.
+ */
+
+ int iStringSize = 0;
+ int x;
+
+ /*
+ * Duplicate the request structure string so we don't change it.
+ */
+ arguments = ap_pstrdup(r->pool, r->args);
+
+ /*
+ * Change the '+' to ' '
+ */
+ for (x=0; arguments[x]; x++) {
+ if ('+' == arguments[x]) {
+ arguments[x] = ' ';
}
}
+
+ /*
+ * We need to unescape any characters that are
+ * in the arguments list.
+ */
+ ap_unescape_url(arguments);
+ arguments = ap_escape_shell_cmd(r->pool, arguments);
}
- /* Bail out if we haven't figured out what kind of
- * file this is by now..
+
+ /*
+ * We have the interpreter (if there is one) and we have
+ * the arguments (if there are any).
+ * Build the command string to pass to CreateProcess.
*/
- if (!is_exe && !is_script && !is_binary) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
- "%s is not executable; ensure interpreted scripts have "
- "\"#!\" first line",
- r->filename);
- return (pid);
+ quoted_filename = ap_pstrcat(r->pool, "\"", r->filename, "\"", NULL);
+ if (interpreter && *interpreter) {
+ pCommand = ap_pstrcat(r->pool, interpreter, " ",
+ quoted_filename, " ", arguments, NULL);
+ }
+ else {
+ pCommand = ap_pstrcat(r->pool, quoted_filename, " ", arguments, NULL);
}
- }
- if (shellcmd) {
+ } else {
+
char *shell_cmd = "CMD.EXE /C ";
OSVERSIONINFO osver;
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
@@ -929,96 +985,17 @@ API_EXPORT(int) ap_call_exec(request_rec *r, child_info *pinfo, char *argv0,
}
pCommand = ap_pstrcat(r->pool, shell_cmd, argv0, NULL);
}
- else if ((!r->args) || (!r->args[0]) || strchr(r->args, '=')) {
- if (is_exe || is_binary) {
- /*
- * When the CGI is a straight binary executable,
- * we can run it as is
- */
- pCommand = quoted_filename;
- }
- else if (is_script) {
- /* When an interpreter is needed, we need to create
- * a command line that has the interpreter name
- * followed by the CGI script name.
- */
- pCommand = ap_pstrcat(r->pool, interpreter + 2, " ",
- quoted_filename, NULL);
- }
- else {
- /* If not an executable or script, just execute it
- * from a command prompt.
- */
- pCommand = ap_pstrcat(r->pool, SHELL_PATH, " /C ",
- quoted_filename, NULL);
- }
- }
- else {
- /* If we are in this leg, there are some other arguments
- * that we must include in the execution of the CGI.
- * Because CreateProcess is the way it is, we have to
- * create a command line like format for the execution
- * of the CGI. This means we need to create on long
- * string with the executable and arguments.
- *
- * The arguments string comes in the request structure,
- * and each argument is separated by a '+'. We'll replace
- * these pluses with spaces.
- */
- char *arguments=NULL;
- int iStringSize = 0;
- int x;
-
- /*
- * Duplicate the request structure string so we don't change it.
- */
- arguments = ap_pstrdup(r->pool, r->args);
-
- /*
- * Change the '+' to ' '
- */
- for (x=0; arguments[x]; x++) {
- if ('+' == arguments[x]) {
- arguments[x] = ' ';
- }
- }
-
- /*
- * We need to unescape any characters that are
- * in the arguments list.
- */
- ap_unescape_url(arguments);
- arguments = ap_escape_shell_cmd(r->pool, arguments);
-
- /*
- * The argument list should now be good to use,
- * so now build the command line.
- */
- if (is_exe || is_binary) {
- pCommand = ap_pstrcat(r->pool, quoted_filename, " ",
- arguments, NULL);
- }
- else if (is_script) {
- pCommand = ap_pstrcat(r->pool, interpreter + 2, " ",
- quoted_filename, " ", arguments, NULL);
- }
- else {
- pCommand = ap_pstrcat(r->pool, SHELL_PATH, " /C ",
- quoted_filename, " ", arguments, NULL);
- }
- }
-
- /*
- * Make child process use hPipeOutputWrite as standard out,
- * and make sure it does not show on screen.
- */
- si.cb = sizeof(si);
- si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
- si.wShowWindow = SW_HIDE;
- si.hStdInput = pinfo->hPipeInputRead;
- si.hStdOutput = pinfo->hPipeOutputWrite;
- si.hStdError = pinfo->hPipeErrorWrite;
+ /*
+ * Make child process use hPipeOutputWrite as standard out,
+ * and make sure it does not show on screen.
+ */
+ si.cb = sizeof(si);
+ si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
+ si.wShowWindow = SW_HIDE;
+ si.hStdInput = pinfo->hPipeInputRead;
+ si.hStdOutput = pinfo->hPipeOutputWrite;
+ si.hStdError = pinfo->hPipeErrorWrite;
/*
* Win32's CreateProcess call requires that the environment
@@ -1042,60 +1019,31 @@ API_EXPORT(int) ap_call_exec(request_rec *r, child_info *pinfo, char *argv0,
i++;
}
- if (CreateProcess(NULL, pCommand, NULL, NULL, TRUE, 0, pEnvBlock,
+ if (CreateProcess(NULL, pCommand, NULL, NULL, TRUE, DETACHED_PROCESS, pEnvBlock,
ap_make_dirstr_parent(r->pool, r->filename),
&si, &pi)) {
- pid = pi.dwProcessId;
- /*
- * We must close the handles to the new process and its main thread
- * to prevent handle and memory leaks.
- */
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- } else {
- if (is_script) {
- /* since we are doing magic to find what we are executing
- * if running a script, log what we think we should have
- * executed
- */
- ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, r,
- "could not run script interpreter: %s", pCommand);
- }
- }
-#if 0
- if ((!r->args) || (!r->args[0]) || strchr(r->args, '=')) {
- if (is_exe || is_binary) {
- pid = spawnle(_P_NOWAIT, r->filename, r->filename, NULL, env);
- }
- else if (is_script) {
- pid = spawnle(_P_NOWAIT, interpreter + 2, interpreter + 2,
- r->filename, NULL, env);
- }
- else {
- pid = spawnle(_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/C",
- r->filename, NULL, env);
- }
- }
- else {
- if (is_exe || is_binary) {
- pid = spawnve(_P_NOWAIT, r->filename,
- create_argv(r->pool, NULL, NULL, NULL, argv0,
- r->args), env);
- }
- else if (is_script) {
- pid = spawnve(_P_NOWAIT, interpreter + 2,
- create_argv(r->pool, interpreter + 2, NULL, NULL,
- r->filename, r->args), env);
- }
- else {
- pid = spawnve(_P_NOWAIT, SHELL_PATH,
- create_argv_cmd(r->pool, argv0, r->args,
- r->filename), env);
- }
- }
-#endif
- return (pid);
+ if (fileType == eFileTypeEXE16) {
+ /* Hack to get 16-bit CGI's working. It works for all the
+ * standard modules shipped with Apache. pi.dwProcessId is 0
+ * for 16-bit CGIs and all the Unix specific code that calls
+ * ap_call_exec interprets this as a failure case. And we can't
+ * use -1 either because it is mapped to 0 by the caller.
+ */
+ pid = -2;
+ }
+ else {
+ pid = pi.dwProcessId;
+ /*
+ * We must close the handles to the new process and its main thread
+ * to prevent handle and memory leaks.
+ */
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ }
+ }
+ return (pid);
}
+
#else
if (ap_suexec_enabled
&& ((r->server->server_uid != ap_user_id)
diff --git a/usr.sbin/httpd/src/main/util_uri.c b/usr.sbin/httpd/src/main/util_uri.c
index d34dbd1852f..10eb5dc0d00 100644
--- a/usr.sbin/httpd/src/main/util_uri.c
+++ b/usr.sbin/httpd/src/main/util_uri.c
@@ -186,11 +186,18 @@ API_EXPORT(char *) ap_unparse_uri_components(pool *p, const uri_components *uptr
/* Construct scheme://site string */
if (uptr->hostname) {
+ int is_default_port;
+
+ is_default_port =
+ (uptr->port_str == NULL ||
+ uptr->port == 0 ||
+ uptr->port == ap_default_port_for_scheme(uptr->scheme));
+
ret = ap_pstrcat (p,
uptr->scheme, "://", ret,
uptr->hostname ? uptr->hostname : "",
- uptr->port_str ? ":" : "",
- uptr->port_str ? uptr->port_str : "",
+ is_default_port ? "" : ":",
+ is_default_port ? "" : uptr->port_str,
NULL);
}
}
@@ -266,8 +273,8 @@ void ap_util_uri_init(void)
/* This is a sub-RE which will break down the hostinfo part,
* i.e., user, password, hostname and port.
* $ 12 3 4 5 6 7 */
- re_str = "^(([^:]*)(:(.*))?@)?([^@:]*)(:(.*))?$";
- /* ^^user^ :pw ^host^ port */
+ re_str = "^(([^:]*)(:(.*))?@)?([^@:]*)(:([0-9]*))?$";
+ /* ^^user^ :pw ^host^ ^:[port]^ */
if ((ret = regcomp(&re_hostpart, re_str, REG_EXTENDED)) != 0) {
char line[1024];
@@ -306,11 +313,11 @@ API_EXPORT(int) ap_parse_uri_components(pool *p, const char *uri, uri_components
memset (uptr, '\0', sizeof(*uptr));
uptr->is_initialized = 1;
- ret = regexec(&re_uri, uri, re_uri.re_nsub + 1, match, 0);
+ ret = ap_regexec(&re_uri, uri, re_uri.re_nsub + 1, match, 0);
if (ret != 0) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL,
- "regexec() could not parse uri (\"%s\")",
+ "ap_regexec() could not parse uri (\"%s\")",
uri);
return HTTP_BAD_REQUEST;
@@ -336,18 +343,18 @@ API_EXPORT(int) ap_parse_uri_components(pool *p, const char *uri, uri_components
if (uptr->hostinfo) {
/* Parse the hostinfo part to extract user, password, host, and port */
- ret = regexec(&re_hostpart, uptr->hostinfo, re_hostpart.re_nsub + 1, match, 0);
+ ret = ap_regexec(&re_hostpart, uptr->hostinfo, re_hostpart.re_nsub + 1, match, 0);
if (ret != 0) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL,
- "regexec() could not parse (\"%s\") as host part",
+ "ap_regexec() could not parse (\"%s\") as host part",
uptr->hostinfo);
return HTTP_BAD_REQUEST;
}
- /* $ 12 3 4 5 6 7 */
- /* = "^(([^:]*)(:(.*))?@)?([^@:]*)(:(.*))?$" */
- /* ^^user^ :pw ^host^ port */
+ /* $ 12 3 4 5 6 7 */
+ /* "^(([^:]*)(:(.*))?@)?([^@:]*)(:([0-9]*))?$" */
+ /* ^^user^ :pw ^host^ ^:[port]^ */
/* empty user is valid, that's why we test $1 but use $2 */
if (match[1].rm_so != match[1].rm_eo)
@@ -371,7 +378,7 @@ API_EXPORT(int) ap_parse_uri_components(pool *p, const char *uri, uri_components
port = strtol(uptr->port_str, &endstr, 10);
uptr->port = port;
- if (*endstr != '\0' || uptr->port != port) {
+ if (*endstr != '\0') {
/* Invalid characters after ':' found */
return HTTP_BAD_REQUEST;
}
diff --git a/usr.sbin/httpd/src/modules/example/mod_example.c b/usr.sbin/httpd/src/modules/example/mod_example.c
index 764b1550a96..68a6b06fe3a 100644
--- a/usr.sbin/httpd/src/modules/example/mod_example.c
+++ b/usr.sbin/httpd/src/modules/example/mod_example.c
@@ -525,7 +525,7 @@ static int example_handler(request_rec *r)
* Now send our actual output. Since we tagged this as being
* "text/html", we need to embed any HTML.
*/
- ap_rputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n", r);
+ ap_rputs(DOCTYPE_HTML_3_2, r);
ap_rputs("<HTML>\n", r);
ap_rputs(" <HEAD>\n", r);
ap_rputs(" <TITLE>mod_example Module Content-Handler Output\n", r);
diff --git a/usr.sbin/httpd/src/modules/experimental/Makefile.tmpl b/usr.sbin/httpd/src/modules/experimental/Makefile.tmpl
index 7b9e1c749de..371167d6cd1 100644
--- a/usr.sbin/httpd/src/modules/experimental/Makefile.tmpl
+++ b/usr.sbin/httpd/src/modules/experimental/Makefile.tmpl
@@ -12,3 +12,12 @@ mod_mmap_static.o: mod_mmap_static.c $(INCDIR)/httpd.h \
$(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
$(INCDIR)/http_log.h $(INCDIR)/http_protocol.h \
$(INCDIR)/http_request.h $(INCDIR)/http_core.h
+mod_digest.o: mod_digest.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/util_md5.h \
+ $(INCDIR)/ap_md5.h
diff --git a/usr.sbin/httpd/src/modules/experimental/mod_auth_digest.c b/usr.sbin/httpd/src/modules/experimental/mod_auth_digest.c
new file mode 100644
index 00000000000..43795221f86
--- /dev/null
+++ b/usr.sbin/httpd/src/modules/experimental/mod_auth_digest.c
@@ -0,0 +1,1919 @@
+/* ====================================================================
+ * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+
+/*
+ * 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
+ * However, it has not been extensively tested yet, and is therefore
+ * currently marked experimental. Send problem reports to me
+ * (ronald@innovation.ch)
+ *
+ * Requires either /dev/random (or equivalent) or the truerand library,
+ * available for instance from
+ * ftp://research.att.com/dist/mab/librand.shar
+ *
+ * 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)
+ * - generating the secret takes a while (~ 8 seconds) if using the
+ * truerand library
+ * - shared-mem not completely tested yet. Seems to work ok for me,
+ * but... (definitely won't work on Windoze)
+ */
+
+/* The section for the Configure script:
+ * MODULE-DEFINITION-START
+ * Name: digest_auth_module
+ * ConfigStart
+
+ RULE_DEV_RANDOM=`./helpers/CutRule DEV_RANDOM $file`
+ if [ "$RULE_DEV_RANDOM" = "default" ]; then
+ if [ -r "/dev/random" ]; then
+ RULE_DEV_RANDOM="/dev/random"
+ elif [ -r "/dev/urandom" ]; then
+ RULE_DEV_RANDOM="/dev/urandom"
+ else
+ RULE_DEV_RANDOM="truerand"
+ if helpers/TestCompile func randbyte; then
+ :
+ elif helpers/TestCompile lib rand randbyte; then
+ :
+ else
+ echo " (mod_auth_digest) truerand library missing!"
+ echo "** This will most probably defeat successful compilation."
+ echo "** See Rule DEV_RANDOM in src/Configuration.tmpl for more information."
+ fi
+ fi
+ fi
+ if [ "$RULE_DEV_RANDOM" = "truerand" ]; then
+ echo " using truerand library (-lrand) for the random seed"
+ LIBS="$LIBS -L/usr/local/lib -lrand"
+ else
+ echo " using $RULE_DEV_RANDOM for the random seed"
+ CFLAGS="$CFLAGS -DDEV_RANDOM=$RULE_DEV_RANDOM"
+ fi
+
+ * ConfigEnd
+ * MODULE-DEFINITION-END
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_conf_globals.h"
+#include "http_core.h"
+#include "http_request.h"
+#include "http_log.h"
+#include "http_protocol.h"
+#include "ap_config.h"
+#include "ap_ctype.h"
+#include "util_uri.h"
+#include "util_md5.h"
+#include "ap_sha1.h"
+#ifdef HAVE_SHMEM_MM
+#include "mm.h"
+#endif /* HAVE_SHMEM_MM */
+
+
+/* struct to hold the configuration info */
+
+typedef struct digest_config_struct {
+ const char *dir_name;
+ const char *pwfile;
+ const char *grpfile;
+ const char *realm;
+ const char **qop_list;
+ AP_SHA1_CTX nonce_ctx;
+ long nonce_lifetime;
+ const char *nonce_format;
+ int check_nc;
+ const char *algorithm;
+ char *uri_list;
+ const char *ha1;
+} digest_config_rec;
+
+
+#define DFLT_ALGORITHM "MD5"
+
+#define DFLT_NONCE_LIFE 300L
+#define NEXTNONCE_DELTA 30
+
+
+#define NONCE_TIME_LEN (((sizeof(time_t)+2)/3)*4)
+#define NONCE_HASH_LEN 40
+#define NONCE_LEN (NONCE_TIME_LEN + NONCE_HASH_LEN)
+
+#define SECRET_LEN 20
+
+
+/* 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 ha1[17]; /* for algorithm=MD5-sess */
+ 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 *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 */
+ time_t nonce_time;
+ enum hdr_sts auth_hdr_sts;
+ uri_components *request_uri;
+ int needed_auth;
+ client_entry *client;
+} digest_header_rec;
+
+
+/* (mostly) nonce stuff */
+
+typedef union time_union {
+ time_t time;
+ unsigned char arr[sizeof(time_t)];
+} time_rec;
+
+
+static unsigned char secret[SECRET_LEN];
+static int call_cnt = 0;
+
+
+#ifdef HAVE_SHMEM_MM
+/* opaque stuff */
+
+static MM *opaque_mm;
+static unsigned long *opaque_cntr;
+
+static MM *client_mm;
+
+static MM *otn_count_mm;
+static time_t *otn_counter; /* one-time-nonce counter */
+
+#define SHMEM_SIZE 1000 /* ~ 12 entries */
+#define NUM_BUCKETS 15UL
+
+#else /* HAVE_SHMEM_MM */
+static void *client_mm = NULL;
+#endif /* HAVE_SHMEM_MM */
+
+module MODULE_VAR_EXPORT digest_auth_module;
+
+/*
+ * initialization code
+ */
+
+#ifdef HAVE_SHMEM_MM
+static void cleanup_tables(void *not_used)
+{
+ fprintf(stderr, "Digest: cleaning up shared memory\n");
+ fflush(stderr);
+
+ if (client_mm) {
+ mm_destroy(client_mm);
+ client_mm = NULL;
+ }
+
+ if (opaque_mm) {
+ mm_destroy(opaque_mm);
+ opaque_mm = NULL;
+ }
+
+ if (otn_count_mm) {
+ mm_destroy(otn_count_mm);
+ otn_count_mm = NULL;
+ }
+}
+#endif /* HAVE_SHMEM_MM */
+
+static void initialize_secret(server_rec *s)
+{
+#ifdef DEV_RANDOM
+ FILE *rnd;
+ size_t got, tot;
+#else
+ extern int randbyte(void); /* from the truerand library */
+ unsigned int idx;
+#endif
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, s,
+ "Digest: generating secret for digest authentication ...");
+
+#ifdef DEV_RANDOM
+#define XSTR(x) #x
+#define STR(x) XSTR(x)
+ if ((rnd = fopen(STR(DEV_RANDOM), "rb")) == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, s,
+ "Digest: Couldn't open " STR(DEV_RANDOM));
+ exit(EXIT_FAILURE);
+ }
+ if (setvbuf(rnd, NULL, _IONBF, 0) != 0) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, s,
+ "Digest: Error trying to disable buffering for " STR(DEV_RANDOM));
+ exit(EXIT_FAILURE);
+ }
+ for (tot=0; tot<sizeof(secret); tot += got) {
+ if ((got = fread(secret+tot, 1, sizeof(secret)-tot, rnd)) < 1) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, s,
+ "Digest: Error reading " STR(DEV_RANDOM));
+ exit(EXIT_FAILURE);
+ }
+ }
+ fclose(rnd);
+#undef STR
+#undef XSTR
+#else /* use truerand */
+ /* this will increase the startup time of the server, unfortunately...
+ * (generating 20 bytes takes about 8 seconds)
+ */
+ for (idx=0; idx<sizeof(secret); idx++)
+ secret[idx] = (unsigned char) randbyte();
+#endif /* DEV_RANDOM */
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, s, "Digest: done");
+}
+
+#ifdef HAVE_SHMEM_MM
+static void initialize_tables(server_rec *s)
+{
+ unsigned long idx;
+
+ /* set up client list */
+
+ client_mm = mm_create(SHMEM_SIZE, tmpnam(NULL));
+ if (client_mm == NULL)
+ goto failed;
+#ifdef MPE
+ if (geteuid() == 1) {
+#else
+ if (geteuid() == 0) {
+#endif
+ if (mm_permission(client_mm, 0600, ap_user_id, ap_group_id))
+ goto failed;
+ }
+ client_list = mm_malloc(client_mm, sizeof(*client_list) +
+ sizeof(client_entry*)*NUM_BUCKETS);
+ if (!client_list) goto failed;
+ 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;
+
+
+ /* setup opaque */
+
+ opaque_mm = mm_create(sizeof(*opaque_cntr), tmpnam(NULL));
+ if (opaque_mm == NULL)
+ goto failed;
+#ifdef MPE
+ if (geteuid() == 1) {
+#else
+ if (geteuid() == 0) {
+#endif
+ if (mm_permission(opaque_mm, 0600, ap_user_id, ap_group_id))
+ goto failed;
+ }
+ opaque_cntr = mm_malloc(opaque_mm, sizeof(*opaque_cntr));
+ if (opaque_cntr == NULL)
+ goto failed;
+ *opaque_cntr = 1UL;
+
+
+ /* setup one-time-nonce counter */
+
+ otn_count_mm = mm_create(sizeof(*otn_counter), tmpnam(NULL));
+ if (otn_count_mm == NULL)
+ goto failed;
+#ifdef MPE
+ if (geteuid() == 1) {
+#else
+ if (geteuid() == 0) {
+#endif
+ if (mm_permission(otn_count_mm, 0600, ap_user_id, ap_group_id))
+ goto failed;
+ }
+ otn_counter = mm_malloc(otn_count_mm, sizeof(*otn_counter));
+ if (otn_counter == NULL)
+ goto failed;
+ *otn_counter = 0;
+
+
+ /* success */
+ return;
+
+failed:
+ if (!client_mm || (client_list && client_list->table && !opaque_mm)
+ || (opaque_cntr && !otn_count_mm))
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+ "Digest: failed to create shared memory segments; reason "
+ "was `%s' - all nonce-count checking, one-time nonces, "
+ "and MD5-sess algorithm disabled", mm_error());
+ else
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+ "Digest: failed to allocate shared mem; reason was `%s' "
+ "- all nonce-count checking, one-time nonces, and "
+ "MD5-sess algorithm disabled", mm_error());
+
+ cleanup_tables(NULL);
+}
+#endif /* HAVE_SHMEM_MM */
+
+static void initialize_module(server_rec *s, pool *p)
+{
+ /* keep from doing the init more than once at startup, and delay
+ * the init until the second round
+ */
+ if (++call_cnt < 2)
+ return;
+
+ /* only initialize the secret on startup, not on restarts */
+ if (call_cnt == 2)
+ initialize_secret(s);
+
+#ifdef HAVE_SHMEM_MM
+ /* 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 mm_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.
+ */
+ initialize_tables(s);
+ /* atexit(cleanup_tables); */
+ ap_register_cleanup(p, NULL, cleanup_tables, ap_null_cleanup);
+#endif /* HAVE_SHMEM_MM */
+}
+
+
+/*
+ * configuration code
+ */
+
+static void *create_digest_dir_config(pool *p, char *dir)
+{
+ digest_config_rec *conf;
+
+ if (dir == NULL) return NULL;
+
+ conf = (digest_config_rec *) ap_pcalloc(p, sizeof(digest_config_rec));
+ if (conf) {
+ conf->qop_list = ap_palloc(p, sizeof(char*));
+ conf->qop_list[0] = NULL;
+ conf->nonce_lifetime = DFLT_NONCE_LIFE;
+ conf->dir_name = ap_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;
+
+ /* 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)
+ */
+ ap_SHA1Init(&conf->nonce_ctx);
+ ap_SHA1Update_binary(&conf->nonce_ctx, (const unsigned char *) realm,
+ strlen(realm));
+ ap_SHA1Update_binary(&conf->nonce_ctx, secret, sizeof(secret));
+
+ return DECLINE_CMD;
+}
+
+static const char *set_digest_file(cmd_parms *cmd, void *config,
+ const char *file)
+{
+ ((digest_config_rec *) config)->pwfile = file;
+ return NULL;
+}
+
+static const char *set_group_file(cmd_parms *cmd, void *config,
+ const char *file)
+{
+ ((digest_config_rec *) config)->grpfile = file;
+ return NULL;
+}
+
+static const char *set_qop(cmd_parms *cmd, void *config, const char *op)
+{
+ digest_config_rec *conf = (digest_config_rec *) config;
+ const char **tmp;
+ int cnt;
+
+ if (!strcasecmp(op, "none")) {
+ if (conf->qop_list[0] == NULL) {
+ conf->qop_list = ap_palloc(cmd->pool, 2 * sizeof(char*));
+ conf->qop_list[1] = NULL;
+ }
+ conf->qop_list[0] = "none";
+ return NULL;
+ }
+
+ if (!strcasecmp(op, "auth-int"))
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, cmd->server,
+ "Digest: WARNING: qop `auth-int' currently only works "
+ "correctly for responses with no entity");
+ else if (strcasecmp(op, "auth"))
+ return ap_pstrcat(cmd->pool, "Unrecognized qop: ", op, NULL);
+
+ for (cnt=0; conf->qop_list[cnt] != NULL; cnt++)
+ ;
+ tmp = ap_palloc(cmd->pool, (cnt+2)*sizeof(char*));
+ memcpy(tmp, conf->qop_list, cnt*sizeof(char*));
+ tmp[cnt] = ap_pstrdup(cmd->pool, op);
+ tmp[cnt+1] = NULL;
+ conf->qop_list = tmp;
+
+ 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)) && !ap_isspace(*endptr))
+ return ap_pstrcat(cmd->pool, "Invalid time in AuthDigestNonceLifetime: ", t, NULL);
+
+ ((digest_config_rec *) config)->nonce_lifetime = lifetime;
+ return NULL;
+}
+
+static const char *set_nonce_format(cmd_parms *cmd, void *config,
+ const char *fmt)
+{
+ ((digest_config_rec *) config)->nonce_format = fmt;
+ return "AuthDigestNonceFormat is not implemented (yet)";
+}
+
+static const char *set_nc_check(cmd_parms *cmd, void *config, int flag)
+{
+ ((digest_config_rec *) config)->check_nc = flag;
+ return NULL;
+}
+
+static const char *set_algorithm(cmd_parms *cmd, void *config, const char *alg)
+{
+ if (!strcasecmp(alg, "MD5-sess"))
+#ifdef HAVE_SHMEM_MM
+ ;
+#else /* HAVE_SHMEM_MM */
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, cmd->server,
+ "Digest: WARNING: algorithm `MD5-sess' is currently not "
+ "correctly implemented");
+#endif /* HAVE_SHMEM_MM */
+ else if (strcasecmp(alg, "MD5"))
+ return ap_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 = ap_pstrcat(cmd->pool, c->uri_list, " ", uri, "\"", NULL);
+ }
+ else
+ c->uri_list = ap_pstrcat(cmd->pool, ", domain=\"", uri, "\"", NULL);
+ return NULL;
+}
+
+static const command_rec digest_cmds[] =
+{
+ {"AuthName", set_realm, NULL, OR_AUTHCFG, TAKE1,
+ "The authentication realm (e.g. \"Members Only\")"},
+ {"AuthDigestFile", set_digest_file, NULL, OR_AUTHCFG, TAKE1,
+ "The name of the file containing the usernames and password hashes"},
+ {"AuthDigestGroupFile", set_group_file, NULL, OR_AUTHCFG, TAKE1,
+ "The name of the file containing the group names and members"},
+ {"AuthDigestQop", set_qop, NULL, OR_AUTHCFG, ITERATE,
+ "A list of quality-of-protection options"},
+ {"AuthDigestNonceLifetime", set_nonce_lifetime, NULL, OR_AUTHCFG, TAKE1,
+ "Maximum lifetime of the server nonce (seconds)"},
+ {"AuthDigestNonceFormat", set_nonce_format, NULL, OR_AUTHCFG, TAKE1,
+ "The format to use when generating the server nonce"},
+ {"AuthDigestNcCheck", set_nc_check, NULL, OR_AUTHCFG, FLAG,
+ "Whether or not to check the nonce-count sent by the client"},
+ {"AuthDigestAlgorithm", set_algorithm, NULL, OR_AUTHCFG, TAKE1,
+ "The algorithm used for the hash calculation"},
+ {"AuthDigestDomain", set_uri_list, NULL, OR_AUTHCFG, ITERATE,
+ "A list of URI's which belong to the same protection space as the current URI"},
+ {NULL}
+};
+
+
+#ifdef HAVE_SHMEM_MM
+/*
+ * client list code
+ *
+ * Each client is assigned a number, which is transfered 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 its 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_mm) return NULL;
+
+ bucket = key % client_list->tbl_len;
+ entry = client_list->table[bucket];
+
+ mm_lock(client_mm, MM_LOCK_RD);
+
+ 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;
+ }
+
+ mm_unlock(client_mm);
+
+ if (entry)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
+ "get_client(): client %lu found", key);
+ else
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
+ "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(void)
+{
+ 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;
+ 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 */
+ mm_free(client_mm, entry);
+ num_removed++;
+ }
+ }
+
+ /* 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 is memory is low.
+ */
+static client_entry *add_client(unsigned long key, client_entry *new,
+ server_rec *s)
+{
+ int bucket;
+ client_entry *entry;
+
+
+ if (!key || !client_mm) return NULL;
+
+ bucket = key % client_list->tbl_len;
+ entry = client_list->table[bucket];
+
+ mm_lock(client_mm, MM_LOCK_RW);
+
+ /* try to allocate a new entry */
+
+ entry = mm_malloc(client_mm, sizeof(client_entry));
+ if (!entry) {
+ long num_removed = gc();
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, s,
+ "Digest: 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 = mm_malloc(client_mm, sizeof(client_entry));
+ if (!entry) return NULL; /* give up */
+ }
+
+ /* now add the entry */
+
+ memcpy(entry, new, 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++;
+
+ mm_unlock(client_mm);
+
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
+ "allocated new client %lu", key);
+
+ return entry;
+}
+#else /* HAVE_SHMEM_MM */
+static client_entry *get_client(unsigned long key, const request_rec *r)
+{
+ return NULL;
+}
+#endif /* HAVE_SHMEM_MM */
+
+
+/*
+ * 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 = ap_table_get(r->headers_in,
+ r->proxyreq ? "Proxy-Authorization"
+ : "Authorization");
+ size_t l;
+ int vk = 0, vv = 0;
+ char *key, *value;
+
+
+ if (!auth_line) {
+ resp->auth_hdr_sts = NO_HEADER;
+ return !OK;
+ }
+
+ resp->scheme = ap_getword_white(r->pool, &auth_line);
+ if (strcasecmp(resp->scheme, "Digest")) {
+ resp->auth_hdr_sts = NOT_DIGEST;
+ return !OK;
+ }
+
+ l = strlen(auth_line);
+
+ key = ap_palloc(r->pool, l+1);
+ value = ap_palloc(r->pool, l+1);
+
+ while (auth_line[0] != '\0') {
+
+ /* find key */
+
+ while (ap_isspace(auth_line[0])) auth_line++;
+ vk = 0;
+ while (auth_line[0] != '=' && auth_line[0] != ','
+ && auth_line[0] != '\0' && !ap_isspace(auth_line[0]))
+ key[vk++] = *auth_line++;
+ key[vk] = '\0';
+ while (ap_isspace(auth_line[0])) auth_line++;
+
+ /* find value */
+
+ if (auth_line[0] == '=') {
+ auth_line++;
+ while (ap_isspace(auth_line[0])) auth_line++;
+
+ vv = 0;
+ 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'
+ && !ap_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 (!strcasecmp(key, "username"))
+ resp->username = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "realm"))
+ resp->realm = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "nonce"))
+ resp->nonce = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "uri"))
+ resp->uri = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "response"))
+ resp->digest = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "algorithm"))
+ resp->algorithm = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "cnonce"))
+ resp->cnonce = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "opaque"))
+ resp->opaque = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "qop"))
+ resp->message_qop = ap_pstrdup(r->pool, value);
+ else if (!strcasecmp(key, "nc"))
+ resp->nonce_count = ap_pstrdup(r->pool, value);
+ }
+
+ if (!resp->username || !resp->realm || !resp->nonce || !resp->uri
+ || !resp->digest) {
+ 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 update_nonce_count(request_rec *r)
+{
+ digest_header_rec *resp;
+ int res;
+
+ if (!ap_is_initial_req(r))
+ return DECLINED;
+
+ resp = ap_pcalloc(r->pool, sizeof(digest_header_rec));
+ resp->request_uri = &r->parsed_uri;
+ resp->needed_auth = 0;
+ ap_set_module_config(r->request_config, &digest_auth_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, 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)
+{
+ const char *hex = "0123456789abcdef";
+ unsigned char sha1[SHA_DIGESTSIZE];
+ AP_SHA1_CTX ctx;
+ int idx;
+
+ memcpy(&ctx, &conf->nonce_ctx, sizeof(ctx));
+ ap_SHA1Update_binary(&ctx, (const unsigned char *) server->server_hostname,
+ strlen(server->server_hostname));
+ ap_SHA1Update_binary(&ctx, (const unsigned char *) &server->port,
+ sizeof(server->port));
+ ap_SHA1Update_binary(&ctx, (const unsigned char *) timestr, strlen(timestr));
+ if (opaque)
+ ap_SHA1Update_binary(&ctx, (const unsigned char *) opaque,
+ strlen(opaque));
+ ap_SHA1Final(sha1, &ctx);
+
+ for (idx=0; idx<SHA_DIGESTSIZE; idx++) {
+ *hash++ = hex[sha1[idx] >> 4];
+ *hash++ = hex[sha1[idx] & 0xF];
+ }
+
+ *hash++ = '\0';
+}
+
+
+/* The nonce has the format b64(time)+hash .
+ */
+static const char *gen_nonce(pool *p, time_t now, const char *opaque,
+ const server_rec *server,
+ const digest_config_rec *conf)
+{
+ char *nonce = ap_palloc(p, NONCE_LEN+1);
+ time_rec t;
+
+ if (conf->nonce_lifetime != 0)
+ t.time = now;
+ else
+#ifdef HAVE_SHMEM_MM
+ /* this counter is not synch'd, because it doesn't really matter
+ * if it counts exactly.
+ */
+ t.time = (*otn_counter)++;
+#else /* HAVE_SHMEM_MM */
+ t.time = 42;
+#endif /* HAVE_SHMEM_MM */
+ ap_base64encode_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
+ */
+
+#ifdef HAVE_SHMEM_MM
+/*
+ * 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 = { 0, NULL, 0, "", "" }, *entry;
+
+ if (!opaque_mm) return 0;
+
+ mm_lock(opaque_mm, MM_LOCK_RW);
+ op = (*opaque_cntr)++;
+ mm_unlock(opaque_mm);
+
+ if (!(entry = add_client(op, &new, r->server))) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "Digest: failed to allocate client entry - ignoring "
+ "client");
+ return NULL;
+ }
+
+ return entry;
+}
+#else /* HAVE_SHMEM_MM */
+static client_entry *gen_client(const request_rec *r) { return NULL; }
+#endif /* HAVE_SHMEM_MM */
+
+
+
+/*
+ * MD5-sess code.
+ *
+ * If you want to use algorithm=MD5-sess you must write get_userpw_hash()
+ * yourself (see below). The dummy provided here just returns the hash
+ * from the auth-file, i.e. it is only useful for testing client
+ * implementations of MD5-sess .
+ */
+
+/*
+ * get_userpw_hash() will be called each time a new session needs to be
+ * generated and is expected to return the equivalent of
+ *
+ * ap_md5(r->pool,
+ * ap_pstrcat(r->pool, username, ":", ap_auth_name(r), ":", passwd))
+ *
+ * You must implement this yourself, and will probably consist of code
+ * contacting the password server and retrieving the hash from it.
+ *
+ * TBD: This function should probably be in a seperate source file so that
+ * people need not modify mod_auth_digest.c each time they install a new version
+ * of apache.
+ */
+static const char *get_userpw_hash(const request_rec *r,
+ const digest_header_rec *resp,
+ const digest_config_rec *conf)
+{
+ /* for now, just get it from pwfile */
+ return conf->ha1;
+}
+
+
+static const char *get_session(const request_rec *r,
+ digest_header_rec *resp,
+ const digest_config_rec *conf)
+{
+ const char *ha1 = NULL, *urp;
+
+ /* get ha1 from client list */
+ if (resp->opaque && resp->client)
+ ha1 = resp->client->ha1;
+
+ /* generate new session if necessary */
+ if (ha1 == NULL || ha1[0] == '\0') {
+ urp = get_userpw_hash(r, resp, conf);
+ ha1 = ap_md5(r->pool,
+ (unsigned char *) ap_pstrcat(r->pool, ha1, ":", resp->nonce,
+ ":", resp->cnonce, NULL));
+ if (!resp->client)
+ resp->client = gen_client(r);
+ if (resp->client)
+ memcpy(resp->client->ha1, ha1, 17);
+ }
+
+ return ha1;
+}
+
+
+static void clear_session(const digest_header_rec *resp)
+{
+ if (resp->client)
+ resp->client->ha1[0] = '\0';
+}
+
+
+/*
+ * Authorization challenge generation code (for WWW-Authenticate)
+ */
+
+static const char *guess_domain(pool *p, const char *uri, const char *filename,
+ const char *dir)
+{
+ size_t u_len = strlen(uri), f_len = strlen(filename), d_len = strlen(dir);
+ const char *u, *f;
+
+
+ /* Because of things like mod_alias and mod_rewrite and the fact that
+ * protection is often on a directory basis (not a location basis) it
+ * is hard to determine the uri to put in the domain attribute.
+ *
+ * What we do is the following: first we see if the directory is
+ * a prefix for the uri - if this is the case we assume that therefore
+ * a <Location> directive was protecting this uri and we can use it
+ * for the domain.
+ */
+ if (u_len >= d_len && !memcmp(uri, dir, d_len))
+ return dir;
+
+ /* Now we check for <Files ...>, and if we find one we send back a
+ * dummy uri - this is the only way to specify that the protection
+ * space only covers a single uri.
+ */
+ if (dir[0] != '/')
+ /* This doesn't work for Amaya (ok, it's of arguable validity in
+ * the first place), so just return the file name instead
+ return "http://0.0.0.0/";
+ */
+ return dir;
+
+ /* Next we find the largest common common suffix of the request-uri
+ * and the final file name, ignoring any extensions; this gives us a
+ * hint as to where any rewriting could've occured (assuming that some
+ * prefix of the uri is rewritten, not a suffix).
+ */
+ u = uri + u_len - 1; /* strip any extension */
+ while (u > uri && *u != '/') u--;
+ while (*u && *u != '.') u++;
+ if (*u == '.') u--;
+ if (*u == '/') u--;
+
+ f = filename + f_len - 1; /* strip any extension */
+ while (f > filename && *f != '/') f--;
+ while (*f && *f != '.') f++;
+ if (*f == '.') f--;
+ if (*f == '/') f--;
+
+ while (*f == *u && f > filename && u > uri) u--, f--;
+ f++; u++;
+
+ while (*f && *f != '/') f++, u++; /* suffix must start with / */
+
+ /* Now, if the directory reaches into this common suffix then we can
+ * take the uri with the same reach.
+ */
+ if ((unsigned long) (f-filename) < d_len) {
+ char *tmp = ap_pstrdup(p, uri);
+ tmp[(u-uri)+(d_len-(f-filename))] = '\0';
+ return tmp;
+ }
+
+ return ""; /* give up */
+}
+
+
+static const char *ltox(pool *p, unsigned long num)
+{
+ if (num != 0)
+ return ap_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;
+ int cnt;
+
+
+ /* Setup qop */
+
+ if (conf->qop_list[0] == NULL)
+ qop = ", qop=\"auth\"";
+ else if (!strcasecmp(conf->qop_list[0], "none"))
+ qop = "";
+ else {
+ qop = ap_pstrcat(r->pool, ", qop=\"", conf->qop_list[0], NULL);
+ for (cnt=1; conf->qop_list[cnt] != NULL; cnt++)
+ qop = ap_pstrcat(r->pool, qop, ",", conf->qop_list[cnt], NULL);
+ qop = ap_pstrcat(r->pool, qop, "\"", NULL);
+ }
+
+ /* MD5-sess stuff */
+
+ if (!stale && !strcasecmp(conf->algorithm, "MD5-sess"))
+ clear_session(resp);
+
+ /* Setup opaque */
+
+ if (resp->opaque == NULL) {
+ /* new client */
+ if ((conf->check_nc || conf->nonce_lifetime == 0
+ || !strcasecmp(conf->algorithm, "MD5-sess"))
+ && (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 = ap_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
+ * unneccessarily (it's usually > 200 bytes!).
+ */
+
+ if (conf->uri_list)
+ domain = conf->uri_list;
+ else {
+ /* They didn't specify any domain, so let's guess at it */
+ domain = guess_domain(r->pool, resp->request_uri->path, r->filename,
+ conf->dir_name);
+ if (domain[0] == '/' && domain[1] == '\0')
+ domain = ""; /* "/" is the default, so no need to send it */
+ else
+ domain = ap_pstrcat(r->pool, ", domain=\"", domain, "\"", NULL);
+ }
+
+ ap_table_mergen(r->err_headers_out,
+ r->proxyreq ? "Proxy-Authenticate" : "WWW-Authenticate",
+ ap_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));
+}
+
+
+/*
+ * Authorization header verification code
+ */
+
+static const char *get_hash(request_rec *r, const char *user,
+ const char *realm, const char *auth_pwfile)
+{
+ configfile_t *f;
+ char l[MAX_STRING_LEN];
+ const char *rpw;
+ char *w, *x;
+
+ if (!(f = ap_pcfg_openfile(r->pool, auth_pwfile))) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "Digest: Could not open password file: %s", auth_pwfile);
+ return NULL;
+ }
+ while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
+ 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)) {
+ ap_cfg_closefile(f);
+ return ap_pstrdup(r->pool, rpw);
+ }
+ }
+ ap_cfg_closefile(f);
+ return NULL;
+}
+
+static int check_nc(const request_rec *r, const digest_header_rec *resp,
+ const digest_config_rec *conf)
+{
+ if (conf->check_nc && client_mm) {
+ unsigned long nc;
+
+ const char *snc = resp->nonce_count;
+ char *endptr;
+
+ nc = strtol(snc, &endptr, 16);
+ if (endptr < (snc+strlen(snc)) && !ap_isspace(*endptr)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: 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_NOERRNO|APLOG_DEBUG, r,
+ "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)
+{
+ double dt;
+ time_rec nonce_time;
+ char tmp, hash[NONCE_HASH_LEN+1];
+
+ if (strlen(resp->nonce) != NONCE_LEN) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: invalid nonce %s received - length is not %d",
+ resp->nonce, NONCE_LEN);
+ note_digest_auth_failure(r, conf, resp, 1);
+ return AUTH_REQUIRED;
+ }
+
+ tmp = resp->nonce[NONCE_TIME_LEN];
+ resp->nonce[NONCE_TIME_LEN] = '\0';
+ ap_base64decode_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_NOERRNO|APLOG_ERR, r,
+ "Digest: invalid nonce %s received - hash is not %s",
+ resp->nonce, hash);
+ note_digest_auth_failure(r, conf, resp, 1);
+ return AUTH_REQUIRED;
+ }
+
+ dt = difftime(r->request_time, nonce_time.time);
+ if (conf->nonce_lifetime > 0 && dt < 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: invalid nonce %s received - user attempted "
+ "time travel", resp->nonce);
+ note_digest_auth_failure(r, conf, resp, 1);
+ return AUTH_REQUIRED;
+ }
+
+ if (conf->nonce_lifetime > 0) {
+ if (dt > conf->nonce_lifetime) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
+ "Digest: user %s: nonce expired - sending new nonce",
+ r->connection->user);
+ note_digest_auth_failure(r, conf, resp, 1);
+ return AUTH_REQUIRED;
+ }
+ }
+ else if (conf->nonce_lifetime == 0 && resp->client) {
+ if (memcmp(resp->client->last_nonce, resp->nonce, NONCE_LEN)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
+ "Digest: user %s: one-time-nonce mismatch - sending "
+ "new nonce", r->connection->user);
+ note_digest_auth_failure(r, conf, resp, 1);
+ return AUTH_REQUIRED;
+ }
+ }
+ /* else (lifetime < 0) => never expires */
+
+ return OK;
+}
+
+/* The actual MD5 code... whee */
+
+static const char *old_digest(const request_rec *r,
+ const digest_header_rec *resp, const char *ha1)
+{
+ const char *ha2;
+
+ /* rfc-2069 */
+ ha2 = ap_md5(r->pool, (unsigned char *)ap_pstrcat(r->pool, r->method, ":",
+ resp->uri, NULL));
+ return ap_md5(r->pool,
+ (unsigned char *)ap_pstrcat(r->pool, ha1, ":", resp->nonce,
+ ":", ha2, NULL));
+}
+
+static const char *new_digest(const request_rec *r,
+ digest_header_rec *resp,
+ const digest_config_rec *conf)
+{
+ const char *ha1, *ha2, *a2;
+
+ /* draft-ietf-http-authentication-03 */
+ if (resp->algorithm && !strcasecmp(resp->algorithm, "MD5-sess"))
+ ha1 = get_session(r, resp, conf);
+ else
+ ha1 = conf->ha1;
+
+ if (resp->message_qop && !strcasecmp(resp->message_qop, "auth-int"))
+ a2 = ap_pstrcat(r->pool, r->method, ":", resp->uri, ":",
+ ap_md5(r->pool, (const unsigned char*) ""), NULL); /* TBD */
+ else
+ a2 = ap_pstrcat(r->pool, r->method, ":", resp->uri, NULL);
+ ha2 = ap_md5(r->pool, (const unsigned char *)a2);
+
+ return ap_md5(r->pool,
+ (unsigned char *)ap_pstrcat(r->pool, ha1, ":", resp->nonce,
+ ":", resp->nonce_count, ":",
+ resp->cnonce, ":",
+ resp->message_qop, ":", ha2,
+ NULL));
+}
+
+
+/* These functions return 0 if client is OK, and proper error status
+ * if not... either AUTH_REQUIRED, if we made a check, and it failed, or
+ * 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;
+ conn_rec *conn = r->connection;
+ const char *t;
+ int res;
+
+
+ /* do we require Digest auth for this URI? */
+
+ if (!(t = ap_auth_type(r)) || strcasecmp(t, "Digest"))
+ return DECLINED;
+
+ if (!ap_auth_name(r)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: need AuthName: %s", r->uri);
+ return 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,
+ &digest_auth_module);
+ resp->needed_auth = 1;
+
+
+ /* get our conf */
+
+ conf = (digest_config_rec *) ap_get_module_config(r->per_dir_config,
+ &digest_auth_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_NOERRNO|APLOG_ERR, r,
+ "Digest: client used wrong authentication scheme "
+ "`%s': %s", resp->scheme, r->uri);
+ else if (resp->auth_hdr_sts == INVALID)
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: missing user, realm, nonce, uri, or digest "
+ "in authorization header: %s", r->uri);
+ /* else (resp->auth_hdr_sts == NO_HEADER) */
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+
+ r->connection->user = (char *) resp->username;
+ r->connection->ap_auth_type = (char *) "Digest";
+
+
+ /* check the auth attributes */
+
+ if (strcmp(resp->uri, resp->request_uri->path)) {
+ uri_components *r_uri = resp->request_uri, d_uri;
+ ap_parse_uri_components(r->pool, resp->uri, &d_uri);
+
+ if ((d_uri.hostname && d_uri.hostname[0] != '\0'
+ && strcasecmp(d_uri.hostname, r->server->server_hostname))
+ || (d_uri.port_str && d_uri.port != r->server->port)
+ || (!d_uri.port_str && r->server->port != 80)
+ || strcmp(d_uri.path, r_uri->path)
+ || (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_NOERRNO|APLOG_ERR, r,
+ "Digest: uri mismatch - <%s> does not match "
+ "request-uri <%s>", resp->uri,
+ ap_unparse_uri_components(r->pool, r_uri, 0));
+ return BAD_REQUEST;
+ }
+ }
+
+ if (resp->opaque && resp->opaque_num == 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: received invalid opaque - got `%s'",
+ resp->opaque);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+
+ if (strcmp(resp->realm, conf->realm)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: realm mismatch - got `%s' but expected `%s'",
+ resp->realm, conf->realm);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+
+ if (resp->algorithm != NULL
+ && strcasecmp(resp->algorithm, "MD5")
+ && strcasecmp(resp->algorithm, "MD5-sess")) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: unknown algorithm `%s' received: %s",
+ resp->algorithm, r->uri);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+
+ if (!conf->pwfile)
+ return DECLINED;
+
+ if (!(conf->ha1 = get_hash(r, conn->user, conf->realm, conf->pwfile))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: user `%s' in realm `%s' not found: %s",
+ conn->user, conf->realm, r->uri);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+
+ if (resp->message_qop == NULL) {
+ /* old (rfc-2069) style digest */
+ if (strcmp(resp->digest, old_digest(r, resp, conf->ha1))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: user %s: password mismatch: %s", conn->user,
+ r->uri);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+ }
+ else {
+ int match = 0, idx;
+ for (idx=0; conf->qop_list[idx] != NULL; idx++) {
+ if (!strcasecmp(conf->qop_list[idx], resp->message_qop)) {
+ match = 1;
+ break;
+ }
+ }
+
+ if (!match
+ && !(conf->qop_list[0] == NULL
+ && !strcasecmp(resp->message_qop, "auth"))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: invalid qop `%s' received: %s",
+ resp->message_qop, r->uri);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+
+ if (strcmp(resp->digest, new_digest(r, resp, conf))) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: user %s: password mismatch: %s", conn->user,
+ r->uri);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+ }
+
+ if (check_nc(r, resp, conf) != OK) {
+ note_digest_auth_failure(r, conf, resp, 0);
+ return AUTH_REQUIRED;
+ }
+
+ /* 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;
+}
+
+
+/*
+ * Checking ID
+ */
+
+static table *groups_for_user(request_rec *r, const char *user,
+ const char *grpfile)
+{
+ configfile_t *f;
+ table *grps = ap_make_table(r->pool, 15);
+ pool *sp;
+ char l[MAX_STRING_LEN];
+ const char *group_name, *ll, *w;
+
+ if (!(f = ap_pcfg_openfile(r->pool, grpfile))) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "Digest: Could not open group file: %s", grpfile);
+ return NULL;
+ }
+
+ sp = ap_make_sub_pool(r->pool);
+
+ while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
+ if ((l[0] == '#') || (!l[0]))
+ continue;
+ ll = l;
+ ap_clear_pool(sp);
+
+ group_name = ap_getword(sp, &ll, ':');
+
+ while (ll[0]) {
+ w = ap_getword_conf(sp, &ll);
+ if (!strcmp(w, user)) {
+ ap_table_setn(grps, ap_pstrdup(r->pool, group_name), "in");
+ break;
+ }
+ }
+ }
+
+ ap_cfg_closefile(f);
+ ap_destroy_pool(sp);
+ return grps;
+}
+
+
+static int digest_check_auth(request_rec *r)
+{
+ const digest_config_rec *conf =
+ (digest_config_rec *) ap_get_module_config(r->per_dir_config,
+ &digest_auth_module);
+ const char *user = r->connection->user;
+ int m = r->method_number;
+ int method_restricted = 0;
+ register int x;
+ const char *t, *w;
+ table *grpstatus;
+ const array_header *reqs_arr;
+ require_line *reqs;
+
+ if (!(t = ap_auth_type(r)) || strcasecmp(t, "Digest"))
+ return DECLINED;
+
+ reqs_arr = ap_requires(r);
+ /* If there is no "requires" directive, then any user will do.
+ */
+ if (!reqs_arr)
+ return OK;
+ reqs = (require_line *) reqs_arr->elts;
+
+ if (conf->grpfile)
+ grpstatus = groups_for_user(r, user, conf->grpfile);
+ else
+ grpstatus = NULL;
+
+ for (x = 0; x < reqs_arr->nelts; x++) {
+
+ if (!(reqs[x].method_mask & (1 << m)))
+ continue;
+
+ method_restricted = 1;
+
+ t = reqs[x].requirement;
+ w = ap_getword_white(r->pool, &t);
+ if (!strcasecmp(w, "valid-user"))
+ return OK;
+ else if (!strcasecmp(w, "user")) {
+ while (t[0]) {
+ w = ap_getword_conf(r->pool, &t);
+ if (!strcmp(user, w))
+ return OK;
+ }
+ }
+ else if (!strcasecmp(w, "group")) {
+ if (!grpstatus)
+ return DECLINED;
+
+ while (t[0]) {
+ w = ap_getword_conf(r->pool, &t);
+ if (ap_table_get(grpstatus, w))
+ return OK;
+ }
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: access to %s failed, reason: unknown require "
+ "directive \"%s\"", r->uri, reqs[x].requirement);
+ return DECLINED;
+ }
+ }
+
+ if (!method_restricted)
+ return OK;
+
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Digest: access to %s failed, reason: user %s not allowed access",
+ r->uri, user);
+
+ note_digest_auth_failure(r, conf,
+ (digest_header_rec *) ap_get_module_config(r->request_config,
+ &digest_auth_module),
+ 0);
+ return AUTH_REQUIRED;
+}
+
+
+/*
+ * Authorization-Info header code
+ */
+
+#ifdef SEND_DIGEST
+static const char *hdr(const table *tbl, const char *name)
+{
+ const char *val = ap_table_get(tbl, name);
+ if (val)
+ return val;
+ else
+ return "";
+}
+#endif
+
+static int add_auth_info(request_rec *r)
+{
+ const digest_config_rec *conf =
+ (digest_config_rec *) ap_get_module_config(r->per_dir_config,
+ &digest_auth_module);
+ digest_header_rec *resp =
+ (digest_header_rec *) ap_get_module_config(r->request_config,
+ &digest_auth_module);
+ const char *ai = NULL, *digest = NULL, *nextnonce = "";
+
+ if (resp == NULL || !resp->needed_auth || conf == NULL)
+ return OK;
+
+
+ /* rfc-2069 digest
+ */
+ if (resp->message_qop == NULL) {
+ /* old client, so calc rfc-2069 digest */
+
+#ifdef SEND_DIGEST
+ /* most of this totally bogus because the handlers don't set the
+ * headers until the final handler phase (I wonder why this phase
+ * is called fixup when there's almost nothing you can fix up...)
+ *
+ * Because it's basically impossible to get this right (e.g. the
+ * Content-length is never set yet when we get here, and we can't
+ * calc the entity hash) it's best to just leave this #def'd out.
+ */
+ char *entity_info =
+ ap_md5(r->pool,
+ (unsigned char *) ap_pstrcat(r->pool,
+ ap_unparse_uri_components(r->pool,
+ resp->request_uri, 0), ":",
+ r->content_type ? r->content_type : ap_default_type(r), ":",
+ hdr(r->headers_out, "Content-Length"), ":",
+ r->content_encoding ? r->content_encoding : "", ":",
+ hdr(r->headers_out, "Last-Modified"), ":",
+ r->no_cache && !ap_table_get(r->headers_out, "Expires") ?
+ ap_gm_timestr_822(r->pool, r->request_time) :
+ hdr(r->headers_out, "Expires"),
+ NULL));
+ digest =
+ ap_md5(r->pool,
+ (unsigned char *)ap_pstrcat(r->pool, conf->ha1, ":",
+ resp->nonce, ":",
+ r->method, ":",
+ ap_gm_timestr_822(r->pool, r->request_time), ":",
+ entity_info, ":",
+ ap_md5(r->pool, (unsigned char *) ""), /* H(entity) - TBD */
+ NULL));
+#endif
+ }
+
+
+ /* setup nextnonce
+ */
+ if (conf->nonce_lifetime > 0) {
+ /* send nextnonce if current nonce will expire in less than 30 secs */
+ if (difftime(r->request_time, resp->nonce_time) > (conf->nonce_lifetime-NEXTNONCE_DELTA)) {
+ nextnonce = ap_pstrcat(r->pool, ", nextnonce=\"",
+ gen_nonce(r->pool, r->request_time,
+ resp->opaque, r->server, conf),
+ "\"", NULL);
+ 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 = ap_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 (conf->qop_list[0] && !strcasecmp(conf->qop_list[0], "none")
+ && resp->message_qop == NULL) {
+ /* use only RFC-2069 format */
+ if (digest)
+ ai = ap_pstrcat(r->pool, "digest=\"", digest, "\"", nextnonce,NULL);
+ else
+ ai = nextnonce;
+ }
+ else {
+ const char *resp_dig, *ha1, *a2, *ha2;
+
+ /* calculate rspauth attribute
+ */
+ if (resp->algorithm && !strcasecmp(resp->algorithm, "MD5-sess"))
+ ha1 = get_session(r, resp, conf);
+ else
+ ha1 = conf->ha1;
+
+ if (resp->message_qop && !strcasecmp(resp->message_qop, "auth-int"))
+ a2 = ap_pstrcat(r->pool, ":", resp->uri, ":",
+ ap_md5(r->pool, (const unsigned char *) ""), NULL); /* TBD */
+ else
+ a2 = ap_pstrcat(r->pool, ":", resp->uri, NULL);
+ ha2 = ap_md5(r->pool, (const unsigned char *)a2);
+
+ resp_dig = ap_md5(r->pool,
+ (unsigned char *)ap_pstrcat(r->pool, ha1, ":",
+ resp->nonce, ":",
+ resp->nonce_count, ":",
+ resp->cnonce, ":",
+ resp->message_qop ?
+ resp->message_qop : "",
+ ":", ha2, NULL));
+
+ /* assemble Authentication-Info header
+ */
+ ai = ap_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 : "",
+ digest ? "digest=\"" : "",
+ digest ? digest : "",
+ digest ? "\"" : "",
+ NULL);
+ }
+
+ if (ai && ai[0])
+ ap_table_mergen(r->headers_out,
+ r->proxyreq ? "Proxy-Authentication-Info" :
+ "Authentication-Info",
+ ai);
+ return OK;
+}
+
+
+module MODULE_VAR_EXPORT digest_auth_module =
+{
+ STANDARD_MODULE_STUFF,
+ initialize_module, /* initializer */
+ 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 */
+ NULL, /* handlers */
+ NULL, /* filename translation */
+ authenticate_digest_user, /* check_user_id */
+ digest_check_auth, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ add_auth_info, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ update_nonce_count /* post read-request */
+};
+
diff --git a/usr.sbin/httpd/src/modules/extra/mod_define.c b/usr.sbin/httpd/src/modules/extra/mod_define.c
new file mode 100644
index 00000000000..149eb12a89d
--- /dev/null
+++ b/usr.sbin/httpd/src/modules/extra/mod_define.c
@@ -0,0 +1,446 @@
+/* ====================================================================
+ * Copyright (c) 1995-1998 The Apache Group. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+
+/*
+** mod_define.c -- Apache module for configuration defines ($xxx)
+** v1.0: Originally written in December 1998 by
+** Ralf S. Engelschall <rse@engelschall.com> and
+** Christian Reiber <chrei@en.muc.de>
+** v1.1: Completely Overhauled in August 1999 by
+** Ralf S. Engelschall <rse@engelschall.com>
+*/
+
+#include "ap_config.h"
+#include "ap_ctype.h"
+#include "httpd.h"
+#include "http_config.h"
+#include "http_conf_globals.h"
+#include "http_core.h"
+#include "http_log.h"
+
+#ifndef EAPI
+#error "This module requires the Extended API (EAPI) facilities."
+#endif
+
+/*
+ * The global table of defines
+ */
+
+static table *tDefines = NULL; /* global table of defines */
+static int bOnceSeenADefine = FALSE; /* optimization flag */
+
+/*
+ * Forward declaration
+ */
+static int DefineIndex (pool *, char *, int *, int *, char **);
+static char *DefineFetch (pool *, char *);
+static char *DefineExpand (pool *, char *, int, char *);
+static void DefineInit (pool *);
+static void DefineCleanup (void *);
+static char *DefineRewriteHook(cmd_parms *, void *, const char *);
+
+/*
+ * Character classes for scanner function
+ */
+typedef enum {
+ CC_ESCAPE, CC_DOLLAR, CC_BRACEOPEN, CC_BRACECLOSE,
+ CC_IDCHAR1, CC_IDCHAR, CC_OTHER, CC_EOS
+} CharClass;
+
+/*
+ * Scanner states for scanner function
+ */
+typedef enum {
+ SS_NONE, SS_SKIP, SS_DOLLAR, SS_TOKEN_BRACED,
+ SS_TOKEN_UNBRACED, SS_ERROR, SS_FOUND
+} ScanState;
+
+/*
+ * Default meta characters
+ */
+#define DEFAULT_MC_ESCAPE "\\"
+#define DEFAULT_MC_DOLLAR "$"
+#define DEFAULT_MC_BRACEOPEN "{"
+#define DEFAULT_MC_BRACECLOSE "}"
+
+/*
+ * Scanner for variable constructs $xxx and ${xxx}
+ */
+static int DefineIndex(pool *p, char *cpLine, int *pos, int *len, char **cpVar)
+{
+ int rc;
+ char *cp;
+ char *cp2;
+ CharClass cc;
+ char cEscape;
+ char cDefine;
+ char cBraceOpen;
+ char cBraceClose;
+ char *cpError;
+ ScanState s;
+
+ cEscape = DEFAULT_MC_ESCAPE[0];
+ if ((cp = DefineFetch(p, "mod_define::escape")) != NULL)
+ cEscape = cp[0];
+ cDefine = DEFAULT_MC_DOLLAR[0];
+ if ((cp = DefineFetch(p, "mod_define::dollar")) != NULL)
+ cDefine = cp[0];
+ cBraceOpen = DEFAULT_MC_BRACEOPEN[0];
+ if ((cp = DefineFetch(p, "mod_define::braceopen")) != NULL)
+ cBraceOpen = cp[0];
+ cBraceClose = DEFAULT_MC_BRACECLOSE[0];
+ if ((cp = DefineFetch(p, "mod_define::braceclose")) != NULL)
+ cBraceClose = cp[0];
+
+ rc = 0;
+ *len = 0;
+ cc = CC_OTHER;
+ s = SS_NONE;
+ for (cp = cpLine+(*pos); cc != CC_EOS; cp++) {
+ if (*cp == cEscape)
+ cc = CC_ESCAPE;
+ else if (*cp == cDefine)
+ cc = CC_DOLLAR;
+ else if (*cp == cBraceOpen)
+ cc = CC_BRACEOPEN;
+ else if (*cp == cBraceClose)
+ cc = CC_BRACECLOSE;
+ else if (ap_isalpha(*cp))
+ cc = CC_IDCHAR1;
+ else if (ap_isdigit(*cp) || *cp == '_' || *cp == ':')
+ cc = CC_IDCHAR;
+ else if (*cp == '\0')
+ cc = CC_EOS;
+ else
+ cc = CC_OTHER;
+ switch (s) {
+ case SS_NONE:
+ switch (cc) {
+ case CC_ESCAPE:
+ s = SS_SKIP;
+ break;
+ case CC_DOLLAR:
+ s = SS_DOLLAR;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SS_SKIP:
+ s = SS_NONE;
+ continue;
+ break;
+ case SS_DOLLAR:
+ switch (cc) {
+ case CC_BRACEOPEN:
+ s = SS_TOKEN_BRACED;
+ *pos = cp-cpLine-1;
+ (*len) = 2;
+ *cpVar = cp+1;
+ break;
+ case CC_IDCHAR1:
+ s = SS_TOKEN_UNBRACED;
+ *pos = cp-cpLine-1;
+ (*len) = 2;
+ *cpVar = cp;
+ break;
+ case CC_ESCAPE:
+ s = SS_SKIP;
+ break;
+ default:
+ s = SS_NONE;
+ break;
+ }
+ break;
+ case SS_TOKEN_BRACED:
+ switch (cc) {
+ case CC_IDCHAR1:
+ case CC_IDCHAR:
+ (*len)++;
+ break;
+ case CC_BRACECLOSE:
+ (*len)++;
+ cp2 = ap_palloc(p, cp-*cpVar+1);
+ ap_cpystrn(cp2, *cpVar, cp-*cpVar+1);
+ *cpVar = cp2;
+ s = SS_FOUND;
+ break;
+ default:
+ cpError = ap_psprintf(p, "Illegal character '%c' in identifier", *cp);
+ s = SS_ERROR;
+ break;
+ }
+ break;
+ case SS_TOKEN_UNBRACED:
+ switch (cc) {
+ case CC_IDCHAR1:
+ case CC_IDCHAR:
+ (*len)++;
+ break;
+ default:
+ cp2 = ap_palloc(p, cp-*cpVar+1);
+ ap_cpystrn(cp2, *cpVar, cp-*cpVar+1);
+ *cpVar = cp2;
+ s = SS_FOUND;
+ break;
+ }
+ break;
+ case SS_FOUND:
+ case SS_ERROR:
+ break;
+ }
+ if (s == SS_ERROR) {
+ fprintf(stderr, "Error\n");
+ break;
+ }
+ else if (s == SS_FOUND) {
+ rc = 1;
+ break;
+ }
+ }
+ return rc;
+}
+
+/*
+ * Determine the value of a variable
+ */
+static char *DefineFetch(pool *p, char *cpVar)
+{
+ char *cpVal;
+
+ /* first try out table */
+ if ((cpVal = (char *)ap_table_get(tDefines, (char *)cpVar)) != NULL)
+ return cpVal;
+ /* second try the environment */
+ if ((cpVal = getenv(cpVar)) != NULL)
+ return cpVal;
+ return NULL;
+}
+
+/*
+ * Expand a variable
+ */
+static char *DefineExpand(pool *p, char *cpToken, int tok_len, char *cpVal)
+{
+ char *cp;
+ int val_len, rest_len;
+
+ val_len = strlen(cpVal);
+ rest_len = strlen(cpToken+tok_len);
+ if (val_len < tok_len)
+ memcpy(cpToken+val_len, cpToken+tok_len, rest_len+1);
+ else if (val_len > tok_len)
+ for (cp = cpToken+strlen(cpToken); cp > cpToken+tok_len-1; cp--)
+ *(cp+(val_len-tok_len)) = *cp;
+ memcpy(cpToken, cpVal, val_len);
+ return NULL;
+}
+
+/*
+ * The EAPI hook which is called after Apache has read a
+ * configuration line and before it's actually processed
+ */
+static char *DefineRewriteHook(cmd_parms *cmd, void *config, const char *line)
+{
+ pool *p;
+ char *cpBuf;
+ char *cpLine;
+ int pos;
+ int len;
+ char *cpError;
+ char *cpVar;
+ char *cpVal;
+ server_rec *s;
+
+ /* runtime optimization */
+ if (!bOnceSeenADefine)
+ return NULL;
+
+ p = cmd->pool;
+ s = cmd->server;
+
+ /*
+ * Search for:
+ * ....\$[a-zA-Z][:_a-zA-Z0-9]*....
+ * ....\${[a-zA-Z][:_a-zA-Z0-9]*}....
+ */
+ cpBuf = NULL;
+ cpLine = (char *)line;
+ pos = 0;
+ while (DefineIndex(p, cpLine, &pos, &len, &cpVar)) {
+#ifdef DEFINE_DEBUG
+ {
+ char prefix[1024];
+ char marker[1024];
+ int i;
+ for (i = 0; i < pos; i++)
+ prefix[i] = ' ';
+ prefix[i] = '\0';
+ for (i = 0; i < len; i++)
+ marker[i] = '^';
+ marker[i] = '\0';
+ fprintf(stderr,
+ "Found variable `%s' (pos: %d, len: %d)\n"
+ " %s\n"
+ " %s%s\n",
+ cpVar, pos, len, cpLine, prefix, marker);
+ }
+#endif
+ if (cpBuf == NULL) {
+ cpBuf = ap_palloc(p, MAX_STRING_LEN);
+ ap_cpystrn(cpBuf, line, MAX_STRING_LEN);
+ cpLine = cpBuf;
+ }
+ if ((cpVal = DefineFetch(p, cpVar)) == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "mod_define: Variable '%s' not defined: file %s, line %d",
+ cpVar, cmd->config_file->name,
+ cmd->config_file->line_number);
+ cpBuf = NULL;
+ break;
+ }
+ if ((cpError = DefineExpand(p, cpLine+pos, len, cpVal)) != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, s,
+ "mod_define: %s: file %s, line %d",
+ cpError, cmd->config_file->name,
+ cmd->config_file->line_number);
+ cpBuf = NULL;
+ break;
+ }
+ }
+ return cpBuf;
+}
+
+/*
+ * Implementation of the `Define' configuration directive
+ */
+static const char *cmd_define(cmd_parms *cmd, void *config,
+ char *cpVar, char *cpVal)
+{
+ if (tDefines == NULL)
+ DefineInit(cmd->pool);
+ ap_table_set(tDefines, cpVar, cpVal);
+ bOnceSeenADefine = TRUE;
+ return NULL;
+}
+
+/*
+ * Module Initialization
+ */
+
+static void DefineInit(pool *p)
+{
+ tDefines = ap_make_table(p, 10);
+ /* predefine delimiters */
+ ap_table_set(tDefines, "mod_define::escape", DEFAULT_MC_ESCAPE);
+ ap_table_set(tDefines, "mod_define::dollar", DEFAULT_MC_DOLLAR);
+ ap_table_set(tDefines, "mod_define::open", DEFAULT_MC_BRACEOPEN);
+ ap_table_set(tDefines, "mod_define::close", DEFAULT_MC_BRACECLOSE);
+ ap_register_cleanup(p, NULL, DefineCleanup, ap_null_cleanup);
+ return;
+}
+
+/*
+ * Module Cleanup
+ */
+
+static void DefineCleanup(void *data)
+{
+ /* reset private variables when config pool is cleared */
+ tDefines = NULL;
+ bOnceSeenADefine = FALSE;
+ return;
+}
+
+/*
+ * Module Directive lists
+ */
+static const command_rec DefineDirectives[] = {
+ { "Define", cmd_define, NULL, RSRC_CONF|ACCESS_CONF, TAKE2,
+ "Define a configuration variable" },
+ { NULL }
+};
+
+/*
+ * Module API dispatch list
+ */
+module MODULE_VAR_EXPORT define_module = {
+ STANDARD_MODULE_STUFF,
+ NULL, /* module initializer */
+ NULL, /* create per-dir config structures */
+ NULL, /* merge per-dir config structures */
+ NULL, /* create per-server config structures */
+ NULL, /* merge per-server config structures */
+ DefineDirectives, /* table of config file commands */
+ NULL, /* [#8] MIME-typed-dispatched handlers */
+ NULL, /* [#1] URI to filename translation */
+ NULL, /* [#4] validate user id from request */
+ NULL, /* [#5] check if the user is ok _here_ */
+ NULL, /* [#2] check access by host address */
+ NULL, /* [#6] determine MIME type */
+ NULL, /* [#7] pre-run fixups */
+ NULL, /* [#9] log a transaction */
+ NULL, /* [#3] header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL, /* [#0] post read-request */
+ NULL, /* EAPI: add_module */
+ NULL, /* EAPI: del_module */
+ DefineRewriteHook, /* EAPI: rewrite_command */
+ NULL /* EAPI: new_connection */
+};
+
diff --git a/usr.sbin/httpd/src/modules/proxy/ApacheModuleProxy.dsp b/usr.sbin/httpd/src/modules/proxy/ApacheModuleProxy.dsp
index 9c94df590e9..6ee5cf30ddd 100644
--- a/usr.sbin/httpd/src/modules/proxy/ApacheModuleProxy.dsp
+++ b/usr.sbin/httpd/src/modules/proxy/ApacheModuleProxy.dsp
@@ -45,7 +45,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
@@ -55,7 +55,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
-# ADD LINK32 ..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 ..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:windows /dll /machine:I386
!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug"
@@ -71,7 +71,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
@@ -81,7 +81,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
-# ADD LINK32 ..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 ..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:windows /dll /debug /machine:I386
!ENDIF
diff --git a/usr.sbin/httpd/src/modules/proxy/ApacheModuleProxy.mak b/usr.sbin/httpd/src/modules/proxy/ApacheModuleProxy.mak
index 95541504be3..b7074715e8d 100644
--- a/usr.sbin/httpd/src/modules/proxy/ApacheModuleProxy.mak
+++ b/usr.sbin/httpd/src/modules/proxy/ApacheModuleProxy.mak
@@ -30,6 +30,10 @@ NULL=
NULL=nul
!ENDIF
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release"
OUTDIR=.\Release
@@ -63,53 +67,20 @@ CLEAN :
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-CPP=cl.exe
CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\
- "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleProxy.pch" /YX\
- /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+ "_WINDOWS" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN"\
+ /Fp"$(INTDIR)\ApacheModuleProxy.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD\
+ /c
CPP_OBJS=.\Release/
CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleProxy.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\
- winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo\
+ winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo\
/subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleProxy.pdb"\
/machine:I386 /out:"$(OUTDIR)\ApacheModuleProxy.dll"\
/implib:"$(OUTDIR)\ApacheModuleProxy.lib"
@@ -162,12 +133,37 @@ CLEAN :
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-CPP=cl.exe
CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\
- "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleProxy.pch"\
- /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+ "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN"\
+ /Fp"$(INTDIR)\ApacheModuleProxy.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD\
+ /c
CPP_OBJS=.\Debug/
CPP_SBRS=.
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleProxy.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\
+ winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo\
+ /subsystem:windows /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleProxy.pdb"\
+ /debug /machine:I386 /out:"$(OUTDIR)\ApacheModuleProxy.dll"\
+ /implib:"$(OUTDIR)\ApacheModuleProxy.lib"
+LINK32_OBJS= \
+ "$(INTDIR)\mod_proxy.obj" \
+ "$(INTDIR)\proxy_cache.obj" \
+ "$(INTDIR)\proxy_connect.obj" \
+ "$(INTDIR)\proxy_ftp.obj" \
+ "$(INTDIR)\proxy_http.obj" \
+ "$(INTDIR)\proxy_util.obj"
+
+"$(OUTDIR)\ApacheModuleProxy.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
.c{$(CPP_OBJS)}.obj::
$(CPP) @<<
@@ -199,34 +195,6 @@ CPP_SBRS=.
$(CPP_PROJ) $<
<<
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleProxy.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\
- winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo\
- /subsystem:windows /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleProxy.pdb"\
- /debug /machine:I386 /out:"$(OUTDIR)\ApacheModuleProxy.dll"\
- /implib:"$(OUTDIR)\ApacheModuleProxy.lib"
-LINK32_OBJS= \
- "$(INTDIR)\mod_proxy.obj" \
- "$(INTDIR)\proxy_cache.obj" \
- "$(INTDIR)\proxy_connect.obj" \
- "$(INTDIR)\proxy_ftp.obj" \
- "$(INTDIR)\proxy_http.obj" \
- "$(INTDIR)\proxy_util.obj"
-
-"$(OUTDIR)\ApacheModuleProxy.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" || "$(CFG)" ==\
"ApacheModuleProxy - Win32 Debug"
@@ -239,6 +207,7 @@ DEP_CPP_MOD_P=\
"..\..\include\ap.h"\
"..\..\include\ap_config.h"\
"..\..\include\ap_ctype.h"\
+ "..\..\include\ap_mmn.h"\
"..\..\include\buff.h"\
"..\..\include\explain.h"\
"..\..\include\hsregex.h"\
@@ -264,12 +233,14 @@ DEP_CPP_MOD_P=\
"..\..\include\ap.h"\
"..\..\include\ap_config.h"\
"..\..\include\ap_ctype.h"\
+ "..\..\include\ap_mmn.h"\
"..\..\include\buff.h"\
"..\..\include\explain.h"\
"..\..\include\hsregex.h"\
"..\..\include\http_config.h"\
"..\..\include\http_log.h"\
"..\..\include\http_protocol.h"\
+ "..\..\include\http_request.h"\
"..\..\include\http_vhost.h"\
"..\..\include\httpd.h"\
"..\..\include\util_uri.h"\
@@ -293,9 +264,11 @@ DEP_CPP_PROXY=\
"..\..\include\ap_config.h"\
"..\..\include\ap_ctype.h"\
"..\..\include\ap_md5.h"\
+ "..\..\include\ap_mmn.h"\
"..\..\include\buff.h"\
"..\..\include\explain.h"\
"..\..\include\hsregex.h"\
+ "..\..\include\http_conf_globals.h"\
"..\..\include\http_config.h"\
"..\..\include\http_log.h"\
"..\..\include\http_main.h"\
@@ -320,9 +293,11 @@ DEP_CPP_PROXY=\
"..\..\include\ap_config.h"\
"..\..\include\ap_ctype.h"\
"..\..\include\ap_md5.h"\
+ "..\..\include\ap_mmn.h"\
"..\..\include\buff.h"\
"..\..\include\explain.h"\
"..\..\include\hsregex.h"\
+ "..\..\include\http_conf_globals.h"\
"..\..\include\http_config.h"\
"..\..\include\http_log.h"\
"..\..\include\http_main.h"\
@@ -350,6 +325,7 @@ DEP_CPP_PROXY_=\
"..\..\include\ap.h"\
"..\..\include\ap_config.h"\
"..\..\include\ap_ctype.h"\
+ "..\..\include\ap_mmn.h"\
"..\..\include\buff.h"\
"..\..\include\explain.h"\
"..\..\include\hsregex.h"\
@@ -374,6 +350,7 @@ DEP_CPP_PROXY_=\
"..\..\include\ap.h"\
"..\..\include\ap_config.h"\
"..\..\include\ap_ctype.h"\
+ "..\..\include\ap_mmn.h"\
"..\..\include\buff.h"\
"..\..\include\explain.h"\
"..\..\include\hsregex.h"\
@@ -402,10 +379,12 @@ DEP_CPP_PROXY_F=\
"..\..\include\ap.h"\
"..\..\include\ap_config.h"\
"..\..\include\ap_ctype.h"\
+ "..\..\include\ap_mmn.h"\
"..\..\include\buff.h"\
"..\..\include\explain.h"\
"..\..\include\hsregex.h"\
"..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
"..\..\include\http_log.h"\
"..\..\include\http_main.h"\
"..\..\include\http_protocol.h"\
@@ -426,10 +405,12 @@ DEP_CPP_PROXY_F=\
"..\..\include\ap.h"\
"..\..\include\ap_config.h"\
"..\..\include\ap_ctype.h"\
+ "..\..\include\ap_mmn.h"\
"..\..\include\buff.h"\
"..\..\include\explain.h"\
"..\..\include\hsregex.h"\
"..\..\include\http_config.h"\
+ "..\..\include\http_core.h"\
"..\..\include\http_log.h"\
"..\..\include\http_main.h"\
"..\..\include\http_protocol.h"\
@@ -454,6 +435,7 @@ DEP_CPP_PROXY_H=\
"..\..\include\ap.h"\
"..\..\include\ap_config.h"\
"..\..\include\ap_ctype.h"\
+ "..\..\include\ap_mmn.h"\
"..\..\include\buff.h"\
"..\..\include\explain.h"\
"..\..\include\hsregex.h"\
@@ -480,6 +462,7 @@ DEP_CPP_PROXY_H=\
"..\..\include\ap.h"\
"..\..\include\ap_config.h"\
"..\..\include\ap_ctype.h"\
+ "..\..\include\ap_mmn.h"\
"..\..\include\buff.h"\
"..\..\include\explain.h"\
"..\..\include\hsregex.h"\
@@ -511,6 +494,7 @@ DEP_CPP_PROXY_U=\
"..\..\include\ap_config.h"\
"..\..\include\ap_ctype.h"\
"..\..\include\ap_md5.h"\
+ "..\..\include\ap_mmn.h"\
"..\..\include\buff.h"\
"..\..\include\explain.h"\
"..\..\include\hsregex.h"\
@@ -520,6 +504,7 @@ DEP_CPP_PROXY_U=\
"..\..\include\http_protocol.h"\
"..\..\include\httpd.h"\
"..\..\include\multithread.h"\
+ "..\..\include\util_date.h"\
"..\..\include\util_uri.h"\
"..\..\os\win32\os.h"\
"..\..\os\win32\readdir.h"\
@@ -537,6 +522,7 @@ DEP_CPP_PROXY_U=\
"..\..\include\ap_config.h"\
"..\..\include\ap_ctype.h"\
"..\..\include\ap_md5.h"\
+ "..\..\include\ap_mmn.h"\
"..\..\include\buff.h"\
"..\..\include\explain.h"\
"..\..\include\hsregex.h"\
@@ -546,6 +532,7 @@ DEP_CPP_PROXY_U=\
"..\..\include\http_protocol.h"\
"..\..\include\httpd.h"\
"..\..\include\multithread.h"\
+ "..\..\include\util_date.h"\
"..\..\include\util_uri.h"\
"..\..\os\win32\os.h"\
"..\..\os\win32\readdir.h"\
diff --git a/usr.sbin/httpd/src/modules/proxy/Makefile.OS2 b/usr.sbin/httpd/src/modules/proxy/Makefile.OS2
new file mode 100644
index 00000000000..260f0050809
--- /dev/null
+++ b/usr.sbin/httpd/src/modules/proxy/Makefile.OS2
@@ -0,0 +1,6 @@
+# Extra rules for making DLLs for OS/2
+
+%.def : %.c
+ echo "LIBRARY $* INITINSTANCE" > $@
+ echo "EXPORTS" >> $@
+ grep "^module .*=" $< | sed "s/module .* \(.*\) =/ \1/" >> $@
diff --git a/usr.sbin/httpd/src/modules/proxy/Makefile.tmpl b/usr.sbin/httpd/src/modules/proxy/Makefile.tmpl
index f7d560ad909..906de39cf8a 100644
--- a/usr.sbin/httpd/src/modules/proxy/Makefile.tmpl
+++ b/usr.sbin/httpd/src/modules/proxy/Makefile.tmpl
@@ -21,7 +21,12 @@ libproxy.so: $(OBJS_PIC)
rm -f $@
$(LD_SHLIB) $(LDFLAGS_SHLIB) -o $@ $(OBJS_PIC) $(LIBS_SHLIB)
-.SUFFIXES: .o .lo
+libproxy.dll: $(OBJS_PIC) mod_proxy.def
+ $(LD_SHLIB) $(LDFLAGS_SHLIB) -o $* $(OBJS_PIC) $(LIBS_SHLIB)
+ emxbind -b -q -s -h0 -dmod_proxy.def $* && \
+ rm $*
+
+.SUFFIXES: .o .lo .dll
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $<
diff --git a/usr.sbin/httpd/src/modules/proxy/mod_proxy.c b/usr.sbin/httpd/src/modules/proxy/mod_proxy.c
index f5fcf29af6b..cfd3aa1d372 100644
--- a/usr.sbin/httpd/src/modules/proxy/mod_proxy.c
+++ b/usr.sbin/httpd/src/modules/proxy/mod_proxy.c
@@ -607,7 +607,7 @@ static const char *
ap_get_module_config(s->module_config, &proxy_module);
int *New;
- if (!isdigit(arg[0]))
+ if (!ap_isdigit(arg[0]))
return "AllowCONNECT: port number must be numeric";
New = ap_push_array(conf->allowed_connect_ports);
diff --git a/usr.sbin/httpd/src/modules/proxy/mod_proxy.h b/usr.sbin/httpd/src/modules/proxy/mod_proxy.h
index 61760c4c21a..9eb3428d80c 100644
--- a/usr.sbin/httpd/src/modules/proxy/mod_proxy.h
+++ b/usr.sbin/httpd/src/modules/proxy/mod_proxy.h
@@ -301,7 +301,7 @@ void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength);
int ap_proxy_hex2sec(const char *x);
void ap_proxy_sec2hex(int t, char *y);
cache_req *ap_proxy_cache_error(cache_req *r);
-int ap_proxyerror(request_rec *r, const char *message);
+int ap_proxyerror(request_rec *r, int statuscode, const char *message);
const char *ap_proxy_host2addr(const char *host, struct hostent *reqhp);
int ap_proxy_is_ipaddr(struct dirconn_entry *This, pool *p);
int ap_proxy_is_domainname(struct dirconn_entry *This, pool *p);
diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_cache.c b/usr.sbin/httpd/src/modules/proxy/proxy_cache.c
index 46951f62ba9..90de9a057e1 100644
--- a/usr.sbin/httpd/src/modules/proxy/proxy_cache.c
+++ b/usr.sbin/httpd/src/modules/proxy/proxy_cache.c
@@ -69,6 +69,10 @@
#endif /* WIN32 */
#include "multithread.h"
#include "ap_md5.h"
+#ifdef __TANDEM
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
DEF_Explain
@@ -102,8 +106,7 @@ typedef struct {
#define ROUNDUP2BLOCKS(_bytes) (((_bytes)+block_size-1) & ~(block_size-1))
static long block_size = 512; /* this must be a power of 2 */
static long61_t curbytes, cachesize;
-static time_t every, garbage_now, garbage_expire;
-static char *filename;
+static time_t garbage_now, garbage_expire;
static mutex *garbage_mutex = NULL;
@@ -119,6 +122,7 @@ int ap_proxy_garbage_init(server_rec *r, pool *p)
static int sub_garbage_coll(request_rec *r, array_header *files,
const char *cachedir, const char *cachesubdir);
static void help_proxy_garbage_coll(request_rec *r);
+static int should_proxy_garbage_coll(request_rec *r);
#if !defined(WIN32) && !defined(MPE) && !defined(OS2)
static void detached_proxy_garbage_coll(request_rec *r);
#endif
@@ -138,10 +142,11 @@ void ap_proxy_garbage_coll(request_rec *r)
(void) ap_release_mutex(garbage_mutex);
ap_block_alarms(); /* avoid SIGALRM on big cache cleanup */
+ if (should_proxy_garbage_coll(r))
#if !defined(WIN32) && !defined(MPE) && !defined(OS2)
- detached_proxy_garbage_coll(r);
+ detached_proxy_garbage_coll(r);
#else
- help_proxy_garbage_coll(r);
+ help_proxy_garbage_coll(r);
#endif
ap_unblock_alarms();
@@ -205,6 +210,10 @@ static void detached_proxy_garbage_coll(request_rec *r)
int status;
pid_t pgrp;
+#if 0
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, r->server,
+ "proxy: Guess what; we fork() again...");
+#endif
switch (pid = fork()) {
case -1:
ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
@@ -264,27 +273,27 @@ static void detached_proxy_garbage_coll(request_rec *r)
}
#endif /* ndef WIN32 */
-static void help_proxy_garbage_coll(request_rec *r)
+#define DOT_TIME "/.time" /* marker */
+
+static int should_proxy_garbage_coll(request_rec *r)
{
- const char *cachedir;
void *sconf = r->server->module_config;
proxy_server_conf *pconf =
(proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
const struct cache_conf *conf = &pconf->cache;
- array_header *files;
- struct stat buf;
- struct gc_ent *fent;
- int i, timefd;
- static time_t lastcheck = BAD_DATE; /* static (per-process) data!!! */
- cachedir = conf->root;
- /* configured size is given in kB. Make it bytes, convert to long61_t: */
- cachesize.lower = cachesize.upper = 0;
- add_long61(&cachesize, conf->space << 10);
- every = conf->gcinterval;
+ const char *cachedir = conf->root;
+ char *filename;
+ struct stat buf;
+ int timefd;
+ time_t every = conf->gcinterval;
+ static time_t lastcheck = BAD_DATE; /* static (per-process) data!!! */
if (cachedir == NULL || every == -1)
- return;
+ return 0;
+
+ filename = ap_palloc(r->pool, strlen(cachedir) + strlen( DOT_TIME ) +1);
+
garbage_now = time(NULL);
/* Usually, the modification time of <cachedir>/.time can only increase.
* Thus, even with several child processes having their own copy of
@@ -292,41 +301,68 @@ static void help_proxy_garbage_coll(request_rec *r)
* for GC yet.
*/
if (garbage_now != -1 && lastcheck != BAD_DATE && garbage_now < lastcheck + every)
- return;
-
- ap_block_alarms(); /* avoid SIGALRM on big cache cleanup */
-
- filename = ap_palloc(r->pool, strlen(cachedir) + HASH_LEN + 2);
- strcpy(filename, cachedir);
- strcat(filename, "/.time");
- if (stat(filename, &buf) == -1) { /* does not exist */
- if (errno != ENOENT) {
- ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
- "proxy: stat(%s)", filename);
- ap_unblock_alarms();
- return;
- }
- if ((timefd = creat(filename, 0666)) == -1) {
- if (errno != EEXIST)
- ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
- "proxy: creat(%s)", filename);
- else
- lastcheck = garbage_now; /* someone else got in there */
- ap_unblock_alarms();
- return;
- }
- close(timefd);
+ return 0;
+
+ strcpy(filename,cachedir);
+ strcat(filename,DOT_TIME);
+
+ /* At this point we have a bit of an engineering compromise. We could either
+ * create and/or mark the .time file (prior to the fork which might
+ * fail on a resource issue) or wait until we are safely forked. The
+ * advantage of doing it now in this process is that we get some
+ * usefull live out of the global last check variable. (XXX which
+ * should go scoreboard IMHO.) Note that the actual counting is
+ * at a later moment.
+ */
+ if (stat(filename, &buf) == -1) { /* does not exist */
+ if (errno != ENOENT) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy: stat(%s)", filename);
+ return 0;
+ }
+ if ((timefd = creat(filename, 0666)) == -1) {
+ if (errno != EEXIST)
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy: creat(%s)", filename);
+ else
+ lastcheck = garbage_now; /* someone else got in there */
+ return 0;
+ }
+ close(timefd);
}
else {
- lastcheck = buf.st_mtime; /* save the time */
- if (garbage_now < lastcheck + every) {
- ap_unblock_alarms();
- return;
- }
- if (utime(filename, NULL) == -1)
- ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
- "proxy: utimes(%s)", filename);
+ lastcheck = buf.st_mtime; /* save the time */
+ if (garbage_now < lastcheck + every) {
+ return 0;
+ }
+ if (utime(filename, NULL) == -1)
+ ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+ "proxy: utimes(%s)", filename);
}
+
+ return 1;
+}
+
+static void help_proxy_garbage_coll(request_rec *r)
+{
+ const char *cachedir;
+ void *sconf = r->server->module_config;
+ proxy_server_conf *pconf =
+ (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
+ const struct cache_conf *conf = &pconf->cache;
+ array_header *files;
+ struct gc_ent *fent;
+ char *filename;
+ int i;
+
+ cachedir = conf->root;
+ filename = ap_palloc(r->pool, strlen(cachedir) + HASH_LEN + 2);
+ /* configured size is given in kB. Make it bytes, convert to long61_t: */
+ cachesize.lower = cachesize.upper = 0;
+ add_long61(&cachesize, conf->space << 10);
+
+ ap_block_alarms(); /* avoid SIGALRM on big cache cleanup */
+
files = ap_make_array(r->pool, 100, sizeof(struct gc_ent));
curbytes.upper = curbytes.lower = 0L;
@@ -385,8 +421,10 @@ static int sub_garbage_coll(request_rec *r, array_header *files,
#endif
struct gc_ent *fent;
int nfiles = 0;
+ char *filename;
ap_snprintf(cachedir, sizeof(cachedir), "%s%s", cachebasedir, cachesubdir);
+ filename = ap_palloc(r->pool, strlen(cachedir) + HASH_LEN + 2);
Explain1("GC Examining directory %s", cachedir);
dir = opendir(cachedir);
if (dir == NULL) {
@@ -777,7 +815,7 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf,
int ap_proxy_cache_update(cache_req *c, table *resp_hdrs,
const int is_HTTP1, int nocache)
{
-#ifdef ULTRIX_BRAIN_DEATH
+#if defined(ULTRIX_BRAIN_DEATH) || defined(SINIX_D_RESOLVER_BUG)
extern char *mktemp(char *template);
#endif
request_rec *r = c->req;
@@ -826,7 +864,7 @@ int ap_proxy_cache_update(cache_req *c, table *resp_hdrs,
* requests with an Authorization header, or
* protocol requests nocache (e.g. ftp with user/password)
*/
-/* @@@ XXX FIXME: is the test "r->status != HTTP_MOVED_PERMANENTLY" corerct?
+/* @@@ XXX FIXME: is the test "r->status != HTTP_MOVED_PERMANENTLY" correct?
* or shouldn't it be "ap_is_HTTP_REDIRECT(r->status)" ? -MnKr */
if ((r->status != HTTP_OK && r->status != HTTP_MOVED_PERMANENTLY && r->status != HTTP_NOT_MODIFIED) ||
(expire != NULL && expc == BAD_DATE) ||
@@ -999,14 +1037,19 @@ int ap_proxy_cache_update(cache_req *c, table *resp_hdrs,
strcpy(c->tempfile, conf->cache.root);
strcat(c->tempfile, TMPFILESTR);
#undef TMPFILESTR
- i = mkstemp(c->tempfile);
+ p = mktemp(c->tempfile);
+ if (p == NULL)
+ return DECLINED;
+
+ Explain1("Create temporary file %s", c->tempfile);
+
+ i = open(c->tempfile, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0622);
if (i == -1) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
"proxy: error creating cache file %s",
c->tempfile);
return DECLINED;
}
-
ap_note_cleanups_for_fd(r->pool, i);
c->fp = ap_bcreate(r->pool, B_WR);
ap_bpushfd(c->fp, -1, i);
@@ -1101,6 +1144,8 @@ void ap_proxy_cache_tidy(cache_req *c)
*p = '\0';
#ifdef WIN32
if (mkdir(c->filename) < 0 && errno != EEXIST)
+#elif defined(__TANDEM)
+ if (mkdir(c->filename, S_IRWXU | S_IRWXG | S_IRWXO) < 0 && errno != EEXIST)
#else
if (mkdir(c->filename, S_IREAD | S_IWRITE | S_IEXEC) < 0 && errno != EEXIST)
#endif /* WIN32 */
diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_connect.c b/usr.sbin/httpd/src/modules/proxy/proxy_connect.c
index 9a19313c828..82203f2c9ef 100644
--- a/usr.sbin/httpd/src/modules/proxy/proxy_connect.c
+++ b/usr.sbin/httpd/src/modules/proxy/proxy_connect.c
@@ -148,7 +148,8 @@ int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url,
for (i = 0; i < conf->noproxies->nelts; i++) {
if ((npent[i].name != NULL && strstr(host, npent[i].name) != NULL)
|| destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*')
- return ap_proxyerror(r, "Connect to remote machine blocked");
+ return ap_proxyerror(r, HTTP_FORBIDDEN,
+ "Connect to remote machine blocked");
}
/* Check if it is an allowed port */
@@ -175,7 +176,9 @@ int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url,
err = ap_proxy_host2addr(proxyhost ? proxyhost : host, &server_hp);
if (err != NULL)
- return ap_proxyerror(r, err); /* give up */
+ return ap_proxyerror(r,
+ proxyhost ? HTTP_BAD_GATEWAY : HTTP_INTERNAL_SERVER_ERROR,
+ err);
sock = ap_psocket(r->pool, PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == -1) {
@@ -184,7 +187,7 @@ int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url,
return HTTP_INTERNAL_SERVER_ERROR;
}
-#ifndef WIN32
+#ifdef CHECK_FD_SETSIZE
if (sock >= FD_SETSIZE) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
"proxy_connect_handler: filedescriptor (%u) "
@@ -207,7 +210,7 @@ int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url,
}
if (i == -1) {
ap_pclosesocket(r->pool, sock);
- return ap_proxyerror(r, ap_pstrcat(r->pool,
+ return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, ap_pstrcat(r->pool,
"Could not connect to remote machine:<br>",
strerror(errno), NULL));
}
diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c b/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c
index 1cdade07730..47ca9daf9d4 100644
--- a/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c
+++ b/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c
@@ -60,6 +60,7 @@
#include "mod_proxy.h"
#include "http_main.h"
#include "http_log.h"
+#include "http_core.h"
#define AUTODETECT_PWD
@@ -77,7 +78,7 @@ static int decodeenc(char *x)
for (i = 0, j = 0; x[i] != '\0'; i++, j++) {
/* decode it if not already done */
ch = x[i];
- if (ch == '%' && isxdigit(x[i + 1]) && isxdigit(x[i + 2])) {
+ if (ch == '%' && ap_isxdigit(x[i + 1]) && ap_isxdigit(x[i + 2])) {
ch = ap_proxy_hex2c(&x[i + 1]);
i += 2;
}
@@ -97,7 +98,7 @@ static int ftp_check_string(const char *x)
for (i = 0; x[i] != '\0'; i++) {
ch = x[i];
- if (ch == '%' && isxdigit(x[i + 1]) && isxdigit(x[i + 2])) {
+ if (ch == '%' && ap_isxdigit(x[i + 1]) && ap_isxdigit(x[i + 2])) {
ch = ap_proxy_hex2c(&x[i + 1]);
i += 2;
}
@@ -290,7 +291,7 @@ static long int send_dir(BUFF *f, request_rec *r, cache_req *c, char *cwd)
path[n-1] = '\0';
/* print "ftp://host/" */
- n = ap_snprintf(buf, sizeof(buf), "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n"
+ n = ap_snprintf(buf, sizeof(buf), DOCTYPE_HTML_3_2
"<HTML><HEAD><TITLE>%s%s</TITLE>\n"
"<BASE HREF=\"%s%s\"></HEAD>\n"
"<BODY><H2>Directory of "
@@ -322,8 +323,11 @@ static long int send_dir(BUFF *f, request_rec *r, cache_req *c, char *cwd)
while (!con->aborted) {
n = ap_bgets(buf, sizeof buf, f);
if (n == -1) { /* input error */
- if (c != NULL)
+ if (c != NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error reading from %s", c->url);
c = ap_proxy_cache_error(c);
+ }
break;
}
if (n == 0)
@@ -382,8 +386,11 @@ static long int send_dir(BUFF *f, request_rec *r, cache_req *c, char *cwd)
o = 0;
total_bytes_sent += n;
- if (c != NULL && c->fp && ap_bwrite(c->fp, buf, n) != n)
+ if (c != NULL && c->fp && ap_bwrite(c->fp, buf, n) != n) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error writing to %s", c->tempfile);
c = ap_proxy_cache_error(c);
+ }
while (n && !r->connection->aborted) {
w = ap_bwrite(con->client, &buf[o], n);
@@ -503,7 +510,7 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
*/
if ((password = ap_table_get(r->headers_in, "Authorization")) != NULL
&& strcasecmp(ap_getword(r->pool, &password, ' '), "Basic") == 0
- && (password = ap_uudecode(r->pool, password))[0] != ':') {
+ && (password = ap_pbase64decode(r->pool, password))[0] != ':') {
/* Note that this allocation has to be made from r->connection->pool
* because it has the lifetime of the connection. The other allocations
* are temporary and can be tossed away any time.
@@ -533,7 +540,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
for (i = 0; i < conf->noproxies->nelts; i++) {
if ((npent[i].name != NULL && strstr(host, npent[i].name) != NULL)
|| destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*')
- return ap_proxyerror(r, /*HTTP_FORBIDDEN*/ "Connect to remote machine blocked");
+ return ap_proxyerror(r, HTTP_FORBIDDEN,
+ "Connect to remote machine blocked");
}
Explain2("FTP: connect to %s:%d", host, port);
@@ -547,7 +555,7 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
server.sin_port = htons(port);
err = ap_proxy_host2addr(host, &server_hp);
if (err != NULL)
- return ap_proxyerror(r, err); /* give up */
+ return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err);
sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == -1) {
@@ -598,7 +606,7 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
#endif
if (i == -1) {
ap_pclosesocket(p, sock);
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ ap_pstrcat(r->pool,
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool,
"Could not connect to remote machine: ",
strerror(errno), NULL));
}
@@ -620,7 +628,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
Explain1("FTP: returned status %d", i);
if (i == -1) {
ap_kill_timeout(r);
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server");
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
}
#if 0
if (i == 120) {
@@ -636,12 +645,12 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
* Retry-After = "Retry-After" ":" ( HTTP-date | delta-seconds )
*/
ap_set_header("Retry-After", ap_psprintf(p, "%u", 60*wait_mins);
- return ap_proxyerror(r, /*HTTP_SERVICE_UNAVAILABLE*/ resp);
+ return ap_proxyerror(r, HTTP_SERVICE_UNAVAILABLE, resp);
}
#endif
if (i != 220) {
ap_kill_timeout(r);
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ resp);
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY, resp);
}
Explain0("FTP: connected.");
@@ -664,7 +673,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
Explain1("FTP: returned status %d", i);
if (i == -1) {
ap_kill_timeout(r);
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server");
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
}
if (i == 530) {
ap_kill_timeout(r);
@@ -694,11 +704,13 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
Explain1("FTP: returned status %d", i);
if (i == -1) {
ap_kill_timeout(r);
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server");
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
}
if (i == 332) {
ap_kill_timeout(r);
- return ap_proxyerror(r, /*HTTP_UNAUTHORIZED*/ "Need account for login");
+ return ap_proxyerror(r, HTTP_UNAUTHORIZED,
+ "Need account for login");
}
/* @@@ questionable -- we might as well return a 403 Forbidden here */
if (i == 530) {
@@ -738,7 +750,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
Explain1("FTP: returned status %d", i);
if (i == -1) {
ap_kill_timeout(r);
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server");
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
}
if (i == 550) {
ap_kill_timeout(r);
@@ -781,7 +794,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
Explain1("FTP: returned status %d", i);
if (i == -1) {
ap_kill_timeout(r);
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server");
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
}
if (i != 200 && i != 504) {
ap_kill_timeout(r);
@@ -862,9 +876,10 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
if (i == -1) {
ap_kill_timeout(r);
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ ap_pstrcat(r->pool,
- "Could not connect to remote machine: ",
- strerror(errno), NULL));
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ ap_pstrcat(r->pool,
+ "Could not connect to remote machine: ",
+ strerror(errno), NULL));
}
else {
pasvmode = 1;
@@ -952,7 +967,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
Explain1("FTP: returned status %d", i);
if (i == -1) {
ap_kill_timeout(r);
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server");
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
}
if (i == 550) {
ap_kill_timeout(r);
@@ -990,7 +1006,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
Explain1("FTP: PWD returned status %d", i);
if (i == -1 || i == 421) {
ap_kill_timeout(r);
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server");
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
}
if (i == 550) {
ap_kill_timeout(r);
@@ -1034,7 +1051,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
Explain1("FTP: returned status %d", rc);
if (rc == -1) {
ap_kill_timeout(r);
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server");
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
}
if (rc == 550) {
Explain0("FTP: RETR failed, trying LIST instead");
@@ -1054,7 +1072,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
Explain1("FTP: returned status %d", rc);
if (rc == -1) {
ap_kill_timeout(r);
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server");
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
}
if (rc == 550) {
ap_kill_timeout(r);
@@ -1080,7 +1099,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
Explain1("FTP: PWD returned status %d", i);
if (i == -1 || i == 421) {
ap_kill_timeout(r);
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server");
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
}
if (i == 550) {
ap_kill_timeout(r);
@@ -1098,7 +1118,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
rc = ftp_getrc(f);
Explain1("FTP: returned status %d", rc);
if (rc == -1)
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server");
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
}
ap_kill_timeout(r);
if (rc != 125 && rc != 150 && rc != 226 && rc != 250)
@@ -1110,15 +1131,18 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
resp_hdrs = ap_make_table(p, 2);
c->hdrs = resp_hdrs;
+ ap_table_setn(resp_hdrs, "Date", ap_gm_timestr_822(r->pool, r->request_time));
+ ap_table_setn(resp_hdrs, "Server", ap_get_server_version());
+
if (parms[0] == 'd')
- ap_table_set(resp_hdrs, "Content-Type", "text/html");
+ ap_table_setn(resp_hdrs, "Content-Type", "text/html");
else {
if (r->content_type != NULL) {
- ap_table_set(resp_hdrs, "Content-Type", r->content_type);
+ ap_table_setn(resp_hdrs, "Content-Type", r->content_type);
Explain1("FTP: Content-Type set to %s", r->content_type);
}
else {
- ap_table_set(resp_hdrs, "Content-Type", "text/plain");
+ ap_table_setn(resp_hdrs, "Content-Type", ap_default_type(r));
}
if (parms[0] != 'a' && size != NULL) {
/* We "trust" the ftp server to really serve (size) bytes... */
@@ -1126,6 +1150,10 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
Explain1("FTP: Content-Length set to %s", size);
}
}
+ if (r->content_encoding != NULL && r->content_encoding[0] != '\0') {
+ Explain1("FTP: Content-Encoding set to %s", r->content_encoding);
+ ap_table_setn(resp_hdrs, "Content-Encoding", r->content_encoding);
+ }
/* check if NoCache directive on this host */
for (i = 0; i < conf->nocaches->nelts; i++) {
@@ -1168,18 +1196,17 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
ap_bpushfd(data, dsock, dsock);
}
-#ifdef CHARSET_EBCDIC
-/* bsetflag(data, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);*/
-#endif /*CHARSET_EBCDIC*/
-
ap_hard_timeout("proxy receive", r);
/* send response */
/* write status line */
if (!r->assbackwards)
ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL);
if (c != NULL && c->fp != NULL
- && ap_bvputs(c->fp, "HTTP/1.0 ", r->status_line, CRLF, NULL) == -1)
- c = ap_proxy_cache_error(c);
+ && ap_bvputs(c->fp, "HTTP/1.0 ", r->status_line, CRLF, NULL) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error writing CRLF to %s", c->tempfile);
+ c = ap_proxy_cache_error(c);
+ }
/* send headers */
tdo.req = r;
@@ -1188,8 +1215,11 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
if (!r->assbackwards)
ap_rputs(CRLF, r);
- if (c != NULL && c->fp != NULL && ap_bputs(CRLF, c->fp) == -1)
+ if (c != NULL && c->fp != NULL && ap_bputs(CRLF, c->fp) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error writing CRLF to %s", c->tempfile);
c = ap_proxy_cache_error(c);
+ }
ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
r->sent_bodyct = 1;
@@ -1208,6 +1238,7 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
/* XXX: we checked for 125||150||226||250 above. This is redundant. */
if (rc != 226 && rc != 250)
+ /* XXX: we no longer log an "error writing to c->tempfile" - should we? */
c = ap_proxy_cache_error(c);
}
else {
diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_http.c b/usr.sbin/httpd/src/modules/proxy/proxy_http.c
index d43dd1ee112..b5cb31358c6 100644
--- a/usr.sbin/httpd/src/modules/proxy/proxy_http.c
+++ b/usr.sbin/httpd/src/modules/proxy/proxy_http.c
@@ -239,7 +239,8 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
for (i = 0; i < conf->noproxies->nelts; i++) {
if ((npent[i].name != NULL && strstr(desthost, npent[i].name) != NULL)
|| destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*')
- return ap_proxyerror(r, "Connect to remote machine blocked");
+ return ap_proxyerror(r, HTTP_FORBIDDEN,
+ "Connect to remote machine blocked");
}
if (proxyhost != NULL) {
@@ -252,7 +253,7 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
server.sin_port = htons(destport);
err = ap_proxy_host2addr(desthost, &server_hp);
if (err != NULL)
- return ap_proxyerror(r, err); /* give up */
+ return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err);
}
sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP);
@@ -297,7 +298,7 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
if (proxyhost != NULL)
return DECLINED; /* try again another way */
else
- return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ ap_pstrcat(r->pool,
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool,
"Could not connect to remote machine: ",
strerror(errno), NULL));
}
@@ -315,7 +316,7 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
AP_HOOK_DECLINE(NULL),
&errmsg, r, f);
if (errmsg != NULL)
- return ap_proxyerror(r, errmsg);
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY, errmsg);
}
#endif /* EAPI */
@@ -385,7 +386,7 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
}
ap_bputs(CRLF, f);
-/* send the request data, if any. N.B. should we trap SIGPIPE ? */
+/* send the request data, if any. */
if (ap_should_client_block(r)) {
while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0)
@@ -397,13 +398,19 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
ap_hard_timeout("proxy receive", r);
len = ap_bgets(buffer, sizeof buffer - 1, f);
- if (len == -1 || len == 0) {
+ if (len == -1) {
ap_bclose(f);
ap_kill_timeout(r);
ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
- "ap_bgets() - proxy receive - Error reading from remote server %s",
- proxyhost ? proxyhost : desthost);
- return ap_proxyerror(r, "Error reading from remote server");
+ "ap_bgets() - proxy receive - Error reading from remote server %s (length %d)",
+ proxyhost ? proxyhost : desthost, len);
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
+ } else if (len == 0) {
+ ap_bclose(f);
+ ap_kill_timeout(r);
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Document contains no data");
}
/* Is it an HTTP/1 response? This is buggy if we ever see an HTTP/1.10 */
@@ -512,8 +519,11 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
if (!r->assbackwards)
ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL);
if (c != NULL && c->fp != NULL &&
- ap_bvputs(c->fp, "HTTP/1.0 ", r->status_line, CRLF, NULL) == -1)
- c = ap_proxy_cache_error(c);
+ ap_bvputs(c->fp, "HTTP/1.0 ", r->status_line, CRLF, NULL) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error writing status line to %s", c->tempfile);
+ c = ap_proxy_cache_error(c);
+ }
/* send headers */
tdo.req = r;
@@ -522,16 +532,22 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
if (!r->assbackwards)
ap_rputs(CRLF, r);
- if (c != NULL && c->fp != NULL && ap_bputs(CRLF, c->fp) == -1)
+ if (c != NULL && c->fp != NULL && ap_bputs(CRLF, c->fp) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error writing CRLF to %s", c->tempfile);
c = ap_proxy_cache_error(c);
+ }
ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
r->sent_bodyct = 1;
/* Is it an HTTP/0.9 respose? If so, send the extra data */
if (backasswards) {
ap_bwrite(r->connection->client, buffer, len);
- if (c != NULL && c->fp != NULL && ap_bwrite(c->fp, buffer, len) != len)
+ if (c != NULL && c->fp != NULL && ap_bwrite(c->fp, buffer, len) != len) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error writing extra data to %s", c->tempfile);
c = ap_proxy_cache_error(c);
+ }
}
ap_kill_timeout(r);
diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_util.c b/usr.sbin/httpd/src/modules/proxy/proxy_util.c
index 257b78bc848..c1258f14995 100644
--- a/usr.sbin/httpd/src/modules/proxy/proxy_util.c
+++ b/usr.sbin/httpd/src/modules/proxy/proxy_util.c
@@ -178,7 +178,7 @@ char *
}
/* decode it if not already done */
if (isenc && ch == '%') {
- if (!isxdigit(x[i + 1]) || !isxdigit(x[i + 2]))
+ if (!ap_isxdigit(x[i + 1]) || !ap_isxdigit(x[i + 2]))
return NULL;
ch = ap_proxy_hex2c(&x[i + 1]);
i += 2;
@@ -491,15 +491,15 @@ table *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF *f)
long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c)
{
- int ok = 1;
+ int ok;
char buf[IOBUFSIZE];
- long total_bytes_rcv;
+ long total_bytes_rcvd;
register int n, o, w;
conn_rec *con = r->connection;
- int alt_to = 1;
+ int alternate_timeouts = 1; /* 1 if we alternate between soft & hard timeouts */
- total_bytes_rcv = 0;
- if (c)
+ total_bytes_rcvd = 0;
+ if (c != NULL)
c->written = 0;
#ifdef CHARSET_EBCDIC
@@ -520,65 +520,71 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c)
#ifdef WIN32
/* works fine under win32, so leave it */
ap_hard_timeout("proxy send body", r);
- alt_to = 0;
+ alternate_timeouts = 0;
#else
/* CHECKME! Since hard_timeout won't work in unix on sends with partial
* cache completion, we have to alternate between hard_timeout
* for reads, and soft_timeout for send. This is because we need
* to get a return from ap_bwrite to be able to continue caching.
* BUT, if we *can't* continue anyway, just use hard_timeout.
+ * (Also, if no cache file is written, use hard timeouts)
*/
- if (c) {
- if (c->len <= 0 || c->cache_completion == 1) {
- ap_hard_timeout("proxy send body", r);
- alt_to = 0;
- }
- } else {
+ if (c == NULL || c->len <= 0 || c->cache_completion == 1.0) {
ap_hard_timeout("proxy send body", r);
- alt_to = 0;
+ alternate_timeouts = 0;
}
#endif
- while (ok) {
- if (alt_to)
- ap_hard_timeout("proxy send body", r);
+ /* Loop and ap_bread() while we can successfully read and write,
+ * or (after the client aborted) while we can successfully
+ * read and finish the configured cache_completion.
+ */
+ for (ok = 1; ok; ) {
+ if (alternate_timeouts)
+ ap_hard_timeout("proxy recv body from upstream server", r);
/* Read block from server */
n = ap_bread(f, buf, IOBUFSIZE);
- if (alt_to)
+ if (alternate_timeouts)
ap_kill_timeout(r);
else
ap_reset_timeout(r);
if (n == -1) { /* input error */
- if (c != NULL)
+ if (c != NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error reading from %s", c->url);
c = ap_proxy_cache_error(c);
+ }
break;
}
if (n == 0)
break; /* EOF */
o = 0;
- total_bytes_rcv += n;
+ total_bytes_rcvd += n;
/* Write to cache first. */
+ /*@@@ XXX FIXME: Assuming that writing the cache file won't time out?!!? */
if (c != NULL && c->fp != NULL) {
if (ap_bwrite(c->fp, &buf[0], n) != n) {
- c = ap_proxy_cache_error(c);
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error writing to %s", c->tempfile);
+ c = ap_proxy_cache_error(c);
} else {
c->written += n;
}
}
/* Write the block to the client, detect aborted transfers */
- while (n && !con->aborted) {
- if (alt_to)
+ while (!con->aborted && n > 0) {
+ if (alternate_timeouts)
ap_soft_timeout("proxy send body", r);
w = ap_bwrite(con->client, &buf[o], n);
- if (alt_to)
+ if (alternate_timeouts)
ap_kill_timeout(r);
else
ap_reset_timeout(r);
@@ -591,7 +597,7 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c)
*/
ok = (c->len > 0) &&
(c->cache_completion > 0) &&
- (c->len * c->cache_completion < total_bytes_rcv);
+ (c->len * c->cache_completion < total_bytes_rcvd);
if (! ok) {
ap_pclosef(c->req->pool, c->fp->fd);
@@ -605,14 +611,14 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c)
}
n -= w;
o += w;
- }
- }
+ } /* while client alive and more data to send */
+ } /* loop and ap_bread while "ok" */
if (!con->aborted)
ap_bflush(con->client);
ap_kill_timeout(r);
- return total_bytes_rcv;
+ return total_bytes_rcvd;
}
/*
@@ -628,14 +634,11 @@ void ap_proxy_send_headers(request_rec *r, const char *respline, table *t)
BUFF *fp = r->connection->client;
table_entry *elts = (table_entry *) ap_table_elts(t)->elts;
- ap_bputs(respline, fp);
- ap_bputs(CRLF, fp);
+ ap_bvputs(fp, respline, CRLF, NULL);
for (i = 0; i < ap_table_elts(t)->nelts; ++i) {
if (elts[i].key != NULL) {
ap_bvputs(fp, elts[i].key, ": ", elts[i].val, CRLF, NULL);
- /* FIXME: @@@ This used to be ap_table_set(), but I think
- * ap_table_addn() is correct. MnKr */
ap_table_addn(r->headers_out, elts[i].key, elts[i].val);
}
}
@@ -826,15 +829,17 @@ void ap_proxy_sec2hex(int t, char *y)
cache_req *ap_proxy_cache_error(cache_req *c)
{
- ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
- "proxy: error writing to cache file %s", c->tempfile);
- ap_pclosef(c->req->pool, c->fp->fd);
- c->fp = NULL;
- unlink(c->tempfile);
+ if (c != NULL) {
+ if (c->fp != NULL) {
+ ap_pclosef(c->req->pool, c->fp->fd);
+ c->fp = NULL;
+ }
+ if (c->tempfile) unlink(c->tempfile);
+ }
return NULL;
}
-int ap_proxyerror(request_rec *r, const char *message)
+int ap_proxyerror(request_rec *r, int statuscode, const char *message)
{
ap_table_setn(r->notes, "error-notes",
ap_pstrcat(r->pool,
@@ -842,8 +847,12 @@ int ap_proxyerror(request_rec *r, const char *message)
"<EM><A HREF=\"", r->uri, "\">",
r->method, "&nbsp;", r->uri, "</A></EM>.<P>\n"
"Reason: <STRONG>", message, "</STRONG>", NULL));
- r->status_line = "500 Proxy Error";
- return HTTP_INTERNAL_SERVER_ERROR;
+
+ /* Allow the "error-notes" string to be printed by ap_send_error_response() */
+ ap_table_setn(r->notes, "verbose-error-to", ap_pstrdup(r->pool, "*"));
+
+ r->status_line = ap_psprintf(r->pool, "%3.3u Proxy Error", statuscode);
+ return statuscode;
}
/*
@@ -1260,8 +1269,11 @@ int ap_proxy_send_hdr_line(void *p, const char *key, const char *value)
if (!parm->req->assbackwards)
ap_rvputs(parm->req, key, ": ", value, CRLF, NULL);
if (parm->cache != NULL && parm->cache->fp != NULL &&
- ap_bvputs(parm->cache->fp, key, ": ", value, CRLF, NULL) == -1)
+ ap_bvputs(parm->cache->fp, key, ": ", value, CRLF, NULL) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, parm->cache->req,
+ "proxy: error writing header to %s", parm->cache->tempfile);
parm->cache = ap_proxy_cache_error(parm->cache);
+ }
return 1; /* tell ap_table_do() to continue calling us for more headers */
}
diff --git a/usr.sbin/httpd/src/modules/ssl/Makefile.libdir b/usr.sbin/httpd/src/modules/ssl/Makefile.libdir
index 499ce4a3d95..a4a4c32080a 100644
--- a/usr.sbin/httpd/src/modules/ssl/Makefile.libdir
+++ b/usr.sbin/httpd/src/modules/ssl/Makefile.libdir
@@ -1,8 +1,8 @@
## _ _
-## _ __ ___ ___ __| | ___ ___| |
-## | '_ ` _ \ / _ \ / _` | / __/ __| |
-## | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-## |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+## _ __ ___ ___ __| | ___ ___| | mod_ssl
+## | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+## | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+## |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
## |_____|
## Makefile.libdir
## Apache 1.3 Configuration mechanism indicator file
diff --git a/usr.sbin/httpd/src/modules/ssl/Makefile.tmpl b/usr.sbin/httpd/src/modules/ssl/Makefile.tmpl
index 2181e709fe6..25d23f1eed0 100644
--- a/usr.sbin/httpd/src/modules/ssl/Makefile.tmpl
+++ b/usr.sbin/httpd/src/modules/ssl/Makefile.tmpl
@@ -1,8 +1,8 @@
## _ _
-## _ __ ___ ___ __| | ___ ___| |
-## | '_ ` _ \ / _ \ / _` | / __/ __| |
-## | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-## |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+## _ __ ___ ___ __| | ___ ___| | mod_ssl
+## | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+## | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+## |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
## |_____|
## Makefile.tmpl
## Apache 1.3 Makefile template for SSL module (Unix environment)
@@ -27,7 +27,7 @@
## software must display the following acknowledgment:
## "This product includes software developed by
## Ralf S. Engelschall <rse@engelschall.com> for use in the
-## mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+## mod_ssl project (http://www.modssl.org/)."
##
## 4. The names "mod_ssl" must not be used to endorse or promote
## products derived from this software without prior written
@@ -42,7 +42,7 @@
## acknowledgment:
## "This product includes software developed by
## Ralf S. Engelschall <rse@engelschall.com> for use in the
-## mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+## mod_ssl project (http://www.modssl.org/)."
##
## THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
## EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -71,6 +71,7 @@ OBJS=\
ssl_engine_config.o\
ssl_engine_compat.o\
ssl_engine_ds.o\
+ ssl_engine_dh.o\
ssl_engine_init.o\
ssl_engine_kernel.o\
ssl_engine_rand.o\
@@ -87,13 +88,16 @@ OBJS=\
ssl_expr_eval.o\
ssl_util.o\
ssl_util_ssl.o\
- ssl_util_sdbm.o
+ ssl_util_sdbm.o\
+ ssl_util_table.o\
+ $(SSL_VENDOR_OBJS)
OBJS_PIC=\
mod_ssl.lo\
ssl_engine_config.lo\
ssl_engine_compat.lo\
ssl_engine_ds.lo\
+ ssl_engine_dh.lo\
ssl_engine_init.lo\
ssl_engine_kernel.lo\
ssl_engine_rand.lo\
@@ -110,7 +114,9 @@ OBJS_PIC=\
ssl_expr_eval.lo\
ssl_util.lo\
ssl_util_ssl.lo\
- ssl_util_sdbm.lo
+ ssl_util_sdbm.lo\
+ ssl_util_table.lo\
+ $(SSL_VENDOR_OBJS_PIC)
##
## END-USER AREA
@@ -158,8 +164,10 @@ ssl_expr_scan.c: ssl_expr_scan.l ssl_expr_parse.h
sed -e '/$$Header:/d' <lex.ssl_expr_yy.c >ssl_expr_scan.c && rm -f lex.ssl_expr_yy.c
ssl_expr_parse.c ssl_expr_parse.h: ssl_expr_parse.y
- yacc -d -l ssl_expr_parse.y
- sed -e 's;yy;ssl_expr_yy;g' -e '/yysccsid/d' \
+ yacc -d ssl_expr_parse.y
+ sed -e 's;yy;ssl_expr_yy;g' \
+ -e '/#ifndef lint/,/#endif/d' \
+ -e '/#if defined(c_plusplus) || defined(__cplusplus)/,/#endif/d' \
<y.tab.c >ssl_expr_parse.c && rm -f y.tab.c
sed -e 's;yy;ssl_expr_yy;g' \
<y.tab.h >ssl_expr_parse.h && rm -f y.tab.h
@@ -195,219 +203,274 @@ $(OBJS) $(OBJS_PIC): Makefile
mod_ssl.o mod_ssl.lo: mod_ssl.c mod_ssl.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
$(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_engine_compat.o ssl_engine_compat.lo: ssl_engine_compat.c mod_ssl.h \
$(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
$(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
$(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_engine_config.o ssl_engine_config.lo: ssl_engine_config.c mod_ssl.h \
$(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
$(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
$(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
+ssl_engine_dh.o ssl_engine_dh.lo: ssl_engine_dh.c mod_ssl.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_engine_ds.o ssl_engine_ds.lo: ssl_engine_ds.c mod_ssl.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
$(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_engine_ext.o ssl_engine_ext.lo: ssl_engine_ext.c mod_ssl.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
$(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_engine_init.o ssl_engine_init.lo: ssl_engine_init.c mod_ssl.h \
$(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
$(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
$(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_engine_io.o ssl_engine_io.lo: ssl_engine_io.c mod_ssl.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
$(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_engine_kernel.o ssl_engine_kernel.lo: ssl_engine_kernel.c mod_ssl.h \
$(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
$(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
$(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_engine_log.o ssl_engine_log.lo: ssl_engine_log.c mod_ssl.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
$(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_engine_mutex.o ssl_engine_mutex.lo: ssl_engine_mutex.c mod_ssl.h \
$(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
$(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
$(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_engine_pphrase.o ssl_engine_pphrase.lo: ssl_engine_pphrase.c mod_ssl.h \
$(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
$(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
$(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_engine_rand.o ssl_engine_rand.lo: ssl_engine_rand.c mod_ssl.h \
$(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
$(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
$(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_engine_scache.o ssl_engine_scache.lo: ssl_engine_scache.c mod_ssl.h \
$(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
$(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
$(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_engine_vars.o ssl_engine_vars.lo: ssl_engine_vars.c mod_ssl.h \
$(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
$(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
$(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_expr.o ssl_expr.lo: ssl_expr.c mod_ssl.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
$(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_expr_eval.o ssl_expr_eval.lo: ssl_expr_eval.c mod_ssl.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
$(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_expr_parse.o ssl_expr_parse.lo: ssl_expr_parse.c mod_ssl.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
$(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_expr_scan.o ssl_expr_scan.lo: ssl_expr_scan.c mod_ssl.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
$(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_expr_parse.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h ssl_expr_parse.h
ssl_util.o ssl_util.lo: ssl_util.c mod_ssl.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
$(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_util_sdbm.o ssl_util_sdbm.lo: ssl_util_sdbm.c mod_ssl.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
$(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
ssl_util_ssl.o ssl_util_ssl.lo: ssl_util_ssl.c mod_ssl.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
$(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/httpd.h $(INCDIR)/alloc.h $(INCDIR)/ap_hook.h \
- $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h \
+ ssl_util_sdbm.h
+ssl_util_table.o ssl_util_table.lo: ssl_util_table.c ssl_util_table.h
diff --git a/usr.sbin/httpd/src/modules/ssl/Makefile.win32 b/usr.sbin/httpd/src/modules/ssl/Makefile.win32
index 3cf7677078d..0e7976f26a3 100644
--- a/usr.sbin/httpd/src/modules/ssl/Makefile.win32
+++ b/usr.sbin/httpd/src/modules/ssl/Makefile.win32
@@ -1,8 +1,8 @@
## _ _
-## _ __ ___ ___ __| | ___ ___| |
-## | '_ ` _ \ / _ \ / _` | / __/ __| |
-## | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-## |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+## _ __ ___ ___ __| | ___ ___| | mod_ssl
+## | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+## | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+## |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
## |_____|
## Makefile.win32
## Apache 1.3 Makefile for SSL module (Win32 environment)
@@ -28,7 +28,7 @@
## software must display the following acknowledgment:
## "This product includes software developed by
## Ralf S. Engelschall <rse@engelschall.com> for use in the
-## mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+## mod_ssl project (http://www.modssl.org/)."
##
## 4. The names "mod_ssl" must not be used to endorse or promote
## products derived from this software without prior written
@@ -43,7 +43,7 @@
## acknowledgment:
## "This product includes software developed by
## Ralf S. Engelschall <rse@engelschall.com> for use in the
-## mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+## mod_ssl project (http://www.modssl.org/)."
##
## THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
## EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -62,8 +62,8 @@
# the following variables are automatically
# adjusted by the configure.bat script.
-SSLEAY_INC = p:\ssl\work\win32\ssleay\include
-SSLEAY_LIB = p:\ssl\work\win32\ssleay\lib
+SSL_INC = p:\ssl\work\win32\openssl\include
+SSL_LIB = p:\ssl\work\win32\openssl\lib
MOD_SSL_VERS_NUM = 000000
MOD_SSL_VERS_STR = 0.0.0
@@ -71,7 +71,7 @@ MOD_SSL_VERS_STR = 0.0.0
CC = cl.exe
CFLAGS = /nologo /c /O2 /MD /W3 /GX /DNDEBUG /DWIN32 /D_WINDOWS /DSHARED_MODULE /DEAPI
CFLAGS = $(CFLAGS) /DMOD_SSL=$(MOD_SSL_VERS_NUM) /DMOD_SSL_VERSION=\"$(MOD_SSL_VERS_STR)\"
-CFLAGS = $(CFLAGS) /I..\..\include /I$(SSLEAY_INC)
+CFLAGS = $(CFLAGS) /I..\..\include /I$(SSL_INC)
LD = link.exe
LDFLAGS = /nologo
RM = del
@@ -87,6 +87,7 @@ OBJS=\
ssl_engine_config.obj\
ssl_engine_compat.obj\
ssl_engine_ds.obj\
+ ssl_engine_dh.obj\
ssl_engine_init.obj\
ssl_engine_kernel.obj\
ssl_engine_rand.obj\
@@ -103,7 +104,8 @@ OBJS=\
ssl_expr_eval.obj\
ssl_util.obj\
ssl_util_ssl.obj\
- ssl_util_sdbm.obj
+ ssl_util_sdbm.obj\
+ ssl_util_table.obj
.c.obj:
$(CC) $(CFLAGS) $<
@@ -118,8 +120,8 @@ $(LIBNAME).dll: $(OBJS)
$(LD) $(LDFLAGS) /dll /out:$@ \
$(OBJS) \
..\..\CoreR\ApacheCore.lib \
- $(SSLEAY_LIB)\ssleay32.lib \
- $(SSLEAY_LIB)\libeay32.lib \
+ $(SSL_LIB)\ssleay32.lib \
+ $(SSL_LIB)\libeay32.lib \
wsock32.lib
clean:
diff --git a/usr.sbin/httpd/src/modules/ssl/README b/usr.sbin/httpd/src/modules/ssl/README
index fc5269acd39..e363b8a3554 100644
--- a/usr.sbin/httpd/src/modules/ssl/README
+++ b/usr.sbin/httpd/src/modules/ssl/README
@@ -2,19 +2,24 @@
_ __ ___ ___ __| | ___ ___| |
| '_ ` _ \ / _ \ / _` | / __/ __| |
| | | | | | (_) | (_| | \__ \__ \ | ``mod_ssl combines the flexibility of
- |_| |_| |_|\___/ \__,_|___|___/___/_| Apache with the security of SSLeay.''
+ |_| |_| |_|\___/ \__,_|___|___/___/_| Apache with the security of OpenSSL.''
|_____|
- ``Ralf Engelschall has released an
- mod_ssl - Apache Interface to SSLeay excellent module that integrates
- http://www.engelschall.com/sw/mod_ssl/ Apache and SSLeay.''
- Version 2.1.0-1.3.3 Tim J. Hudson, SSLeay co-author
+ mod_ssl ``Ralf Engelschall has released an
+ Apache Interface to OpenSSL excellent module that integrates
+ http://www.modssl.org/ Apache and SSLeay.''
+ Version 2.3 -- Tim J. Hudson
+ SYNOPSIS
+
This Apache module provides strong cryptography for the Apache 1.3 webserver
via the Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS
- v1) protocols by the help of the SSL/TLS implementation library SSLeay from
- Eric A. Young and Tim J. Hudson. The mod_ssl package was created in April
- 1998 by Ralf S. Engelschall and was originally derived from software
- developed by Ben Laurie for use in the Apache-SSL HTTP server project.
+ v1) protocols by the help of the SSL/TLS implementation library OpenSSL which
+ is based on SSLeay from Eric A. Young and Tim J. Hudson. The mod_ssl package
+ was created in April 1998 by Ralf S. Engelschall and was originally derived
+ from software developed by Ben Laurie for use in the Apache-SSL HTTP server
+ project.
+
+ SOURCES
Here is a short overview of the source files:
@@ -53,18 +58,22 @@
-Wmissing-declarations -Wnested-externs -Winline'' compiler test without any
complains. When you make changes or additions make sure the source still
passes this compiler test.
+
+ FUNCTIONS
Inside the source code you will be confronted with the following types of
functions which can be identified by their prefixes:
ap_xxxx() ............... Apache API function
ssl_xxxx() .............. mod_ssl function
- SSL_xxxx() .............. SSLeay function (SSL library)
- SSLeay_xxxx() ........... SSLeay function (SSL library)
- X509_xxxx() ............. SSLeay function (Crypto library)
- PEM_xxxx() .............. SSLeay function (Crypto library)
- EVP_xxxx() .............. SSLeay function (Crypto library)
- RSA_xxxx() .............. SSLeay function (Crypto library)
+ SSL_xxxx() .............. OpenSSL function (SSL library)
+ OpenSSL_xxxx() .......... OpenSSL function (SSL library)
+ X509_xxxx() ............. OpenSSL function (Crypto library)
+ PEM_xxxx() .............. OpenSSL function (Crypto library)
+ EVP_xxxx() .............. OpenSSL function (Crypto library)
+ RSA_xxxx() .............. OpenSSL function (Crypto library)
+
+ DATA STRUCTURES
Inside the source code you will be confronted with the following
data structures:
@@ -77,12 +86,12 @@
SSLModConfig ............ mod_ssl (Global) Module Configuration
SSLSrvConfig ............ mod_ssl (Virtual) Server Configuration
SSLDirConfig ............ mod_ssl Directory Configuration
- SSL_CTX ................. SSLeay Context
- SSL_METHOD .............. SSLeay Protocol Method
- SSL_CIPHER .............. SSLeay Cipher
- SSL_SESSION ............. SSLeay Session
- SSL ..................... SSLeay Connection
- BIO ..................... SSLeay Connection Buffer
+ SSL_CTX ................. OpenSSL Context
+ SSL_METHOD .............. OpenSSL Protocol Method
+ SSL_CIPHER .............. OpenSSL Cipher
+ SSL_SESSION ............. OpenSSL Session
+ SSL ..................... OpenSSL Connection
+ BIO ..................... OpenSSL Connection Buffer
For an overview how these are related and chained together have a look at the
page in README.dsov.{fig,ps}. It contains overview diagrams for those data
@@ -90,3 +99,38 @@
a smaller version inside XFig by specifing a magnification on the Export
panel.
+ EXPERIMENTAL CODE
+
+ Experimental code is always encapsulated as
+
+ | #ifdef SSL_EXPERIMENTAL
+ | ...
+ | #endif
+
+ blocks and only compiled in when this define is enabled with the APACI
+ --enable-rule=SSL_EXPERIMENTAL option. Currently the following features are
+ experimental:
+
+ o The ability to use SSLCACertificateFile and SSLCACertificatePath
+ in a per-directory context (.htaccess). This is provided by some nasty
+ reconfiguration hacks until OpenSSL has better support for this. It
+ should work on non-multithreaded platforms (all but Win32).
+
+ VENDOR EXTENSIONS
+
+ Inside the mod_ssl sources you can enable various EAPI vendor hooks
+ (`ap::mod_ssl::vendor::xxxx') by using the APACI --enable-rule=SSL_VENDOR
+ option. These hooks can be used to change or extend mod_ssl by a vendor
+ without patching the source code. Grep for `ap::mod_ssl::vendor::'.
+ Additionally vendors can add their own source code to files named
+ ssl_vendor.c, ssl_vendor_XXX.c, etc. The libssl.module script automatically
+ picks these up under configuration time and mod_ssl under run-time calls the
+ functions `void ssl_vendor_register(void)' and `void
+ ssl_vendor_unregister(void)' inside these objects to bootstrap them.
+
+ An ssl_vendor.c should at least contain the following contents:
+
+ | #include "mod_ssl.h"
+ | void ssl_vendor_register(void) { return; }
+ | void ssl_vendor_unregister(void) { return; }
+
diff --git a/usr.sbin/httpd/src/modules/ssl/README.dsov.fig b/usr.sbin/httpd/src/modules/ssl/README.dsov.fig
index 9a76380718c..d8d03db247c 100644
--- a/usr.sbin/httpd/src/modules/ssl/README.dsov.fig
+++ b/usr.sbin/httpd/src/modules/ssl/README.dsov.fig
@@ -14,14 +14,14 @@ Single
0 36 #ffffff
6 6345 2835 7155 3150
6 6345 2970 7110 3150
-4 0 0 200 0 20 8 0.0000 4 120 750 6345 3105 "ssl_module")\001
+4 0 0 200 0 20 8 0.0000 4 120 585 6345 3105 "ssl_module")\001
-6
-4 0 0 200 0 20 8 0.0000 4 135 810 6345 2970 ap_ctx_get(...,\001
+4 0 0 200 0 20 8 0.0000 4 120 660 6345 2970 ap_ctx_get(...,\001
-6
6 10800 2610 12240 3060
-4 0 0 200 0 20 8 0.0000 4 120 1425 10800 2745 ap_get_module_config(...\001
-4 0 0 200 0 20 8 0.0000 4 135 1035 10800 2880 ->per_dir_config,\001
-4 0 0 200 0 20 8 0.0000 4 120 750 10800 3015 &ssl_module)\001
+4 0 0 200 0 20 8 0.0000 4 120 1170 10800 2745 ap_get_module_config(...\001
+4 0 0 200 0 20 8 0.0000 4 120 795 10800 2880 ->per_dir_config,\001
+4 0 0 200 0 20 8 0.0000 4 120 585 10800 3015 &ssl_module)\001
-6
6 7920 4770 9135 4995
2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
@@ -280,16 +280,16 @@ Single
1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000
1.000
4 0 0 100 0 0 12 0.0000 4 180 1440 10575 675 Ralf S. Engelschall\001
-4 0 0 100 0 18 20 0.0000 4 270 3600 4275 675 Apache+mod_ssl+SSLeay\001
+4 0 0 100 0 18 20 0.0000 4 270 3840 4275 675 Apache+mod_ssl+OpenSSL\001
4 0 0 100 0 0 10 0.0000 4 135 1320 10575 855 rse@engelschall.com\001
4 0 0 100 0 0 10 0.0000 4 135 1410 10575 1035 www.engelschall.com\001
4 0 0 100 0 0 12 0.0000 4 135 870 900 675 Version 1.3\001
-4 0 0 100 0 0 12 0.0000 4 135 1005 900 855 27-Jan-1998\001
-4 0 0 200 0 20 8 0.0000 4 75 510 6210 4680 ->server\001
-4 0 0 200 0 20 8 0.0000 4 135 1095 8280 6120 ap_ctx_get(...,"ssl")\001
-4 0 0 200 0 20 8 0.0000 4 120 1425 7740 2700 ap_get_module_config(...\001
-4 0 0 200 0 20 8 0.0000 4 135 1020 7740 2835 ->module_config,\001
-4 0 0 200 0 20 8 0.0000 4 120 750 7740 2970 &ssl_module)\001
+4 0 0 100 0 0 12 0.0000 4 180 1035 900 855 12-Apr-1999\001
+4 0 0 200 0 20 8 0.0000 4 60 390 6210 4680 ->server\001
+4 0 0 200 0 20 8 0.0000 4 120 855 8280 6120 ap_ctx_get(...,"ssl")\001
+4 0 0 200 0 20 8 0.0000 4 120 1170 7740 2700 ap_get_module_config(...\001
+4 0 0 200 0 20 8 0.0000 4 120 810 7740 2835 ->module_config,\001
+4 0 0 200 0 20 8 0.0000 4 120 585 7740 2970 &ssl_module)\001
4 0 0 100 0 18 20 0.0000 4 270 1200 9000 8100 Chaining\001
4 0 0 100 0 18 20 0.0000 4 210 1095 2745 8100 Lifetime\001
4 0 0 100 0 18 12 0.0000 4 180 1215 810 6255 ap_global_ctx\001
@@ -308,7 +308,7 @@ Single
4 0 0 200 0 0 8 0.0000 4 90 1050 2025 7110 Connection Duration\001
4 0 0 200 0 0 8 0.0000 4 120 885 2835 6885 Request Duration\001
4 0 0 200 0 18 20 0.0000 4 195 90 6345 6795 t\001
-4 0 0 200 0 20 8 0.0000 4 105 465 7110 5985 ->client\001
+4 0 0 200 0 20 8 0.0000 4 90 345 7110 5985 ->client\001
4 0 0 100 0 18 12 0.0000 4 180 1305 6795 2430 SSLModConfig\001
4 0 0 100 0 18 12 0.0000 4 180 1260 8865 2430 SSLSrvConfig\001
4 0 0 100 0 18 12 0.0000 4 180 1215 6345 3555 ap_global_ctx\001
@@ -320,27 +320,27 @@ Single
4 0 0 100 0 18 12 0.0000 4 180 1305 11025 5355 SSL_METHOD\001
4 0 0 100 0 18 12 0.0000 4 180 840 11475 4455 SSL_CTX\001
4 0 0 100 0 18 24 0.0000 4 285 4365 3915 1080 Data Structure Overview\001
-4 0 0 200 0 20 8 0.0000 4 105 795 7065 5085 ->connection\001
-4 0 0 200 0 20 8 0.0000 4 75 510 7065 4770 ->server\001
-4 0 0 200 0 20 8 0.0000 4 120 1200 8010 5445 SSL_get_app_data()\001
-4 0 0 200 0 20 8 0.0000 4 120 705 10530 4050 ->pSSLCtx\001
-4 0 0 200 0 20 8 0.0000 4 120 1515 7875 4275 SSL_CTX_get_app_data()\001
-4 0 0 200 0 20 8 0.0000 4 120 1485 10305 5535 SSL_get_current_cipher()\001
+4 0 0 200 0 20 8 0.0000 4 90 615 7065 5085 ->connection\001
+4 0 0 200 0 20 8 0.0000 4 60 390 7065 4770 ->server\001
+4 0 0 200 0 20 8 0.0000 4 120 960 8010 5445 SSL_get_app_data()\001
+4 0 0 200 0 20 8 0.0000 4 120 510 10530 4050 ->pSSLCtx\001
+4 0 0 200 0 20 8 0.0000 4 120 1215 7875 4275 SSL_CTX_get_app_data()\001
+4 0 0 200 0 20 8 0.0000 4 120 1155 10305 5535 SSL_get_current_cipher()\001
4 0 0 100 0 18 12 0.0000 4 180 1170 11025 5760 SSL_CIPHER\001
4 0 0 100 0 18 12 0.0000 4 180 1350 10980 6165 SSL_SESSION\001
-4 0 0 200 0 20 8 0.0000 4 120 1095 10440 5940 SSL_get_session()\001
+4 0 0 200 0 20 8 0.0000 4 120 840 10440 5940 SSL_get_session()\001
4 0 0 100 0 18 12 0.0000 4 180 1665 10575 7110 X509_STORE_CTX\001
4 0 0 100 0 18 12 0.0000 4 135 345 9720 7110 BIO\001
-4 0 0 200 0 20 8 0.0000 4 135 1080 9540 7335 SSL_get_{r,w}bio()\001
-4 0 0 100 0 18 12 0.0000 4 180 720 10935 7785 [Crypto]\001
-4 0 0 100 0 18 20 0.0000 4 270 1050 10935 7605 SSLeay\001
-4 0 0 100 0 18 20 0.0000 4 270 1050 11115 3645 SSLeay\001
-4 0 0 100 0 18 12 0.0000 4 180 495 11115 3825 [SSL]\001
+4 0 0 200 0 20 8 0.0000 4 120 840 9540 7335 SSL_get_{r,w}bio()\001
4 0 0 100 0 18 20 0.0000 4 270 1170 8730 3465 mod_ssl\001
4 0 0 100 0 18 20 0.0000 4 270 1050 8145 6750 Apache\001
-4 0 0 200 0 20 8 0.0000 4 120 1245 10125 4680 SSL_get_SSL_CTX()\001
-4 0 0 200 0 20 8 0.0000 4 120 1530 10350 5175 SSL_get_SSL_METHOD()\001
-4 0 0 200 0 20 8 0.0000 4 105 585 11745 4770 ->method\001
-4 0 0 200 0 20 8 0.0000 4 120 2070 9945 6480 X509_STORE_CTX_get_app_data()\001
-4 0 0 200 0 20 8 0.0000 4 120 1560 10980 6705 SSL_CTX_get_cert_store()\001
-4 0 0 200 0 20 8 0.0000 4 120 1275 8280 5130 SSL_get_app_data2()\001
+4 0 0 200 0 20 8 0.0000 4 120 945 10125 4680 SSL_get_SSL_CTX()\001
+4 0 0 200 0 20 8 0.0000 4 120 1170 10350 5175 SSL_get_SSL_METHOD()\001
+4 0 0 200 0 20 8 0.0000 4 90 465 11745 4770 ->method\001
+4 0 0 200 0 20 8 0.0000 4 120 1665 9945 6480 X509_STORE_CTX_get_app_data()\001
+4 0 0 200 0 20 8 0.0000 4 120 1215 10980 6705 SSL_CTX_get_cert_store()\001
+4 0 0 200 0 20 8 0.0000 4 120 1020 8280 5130 SSL_get_app_data2()\001
+4 0 0 100 0 18 20 0.0000 4 270 1290 10710 7605 OpenSSL\001
+4 0 0 100 0 18 12 0.0000 4 180 720 10710 7785 [Crypto]\001
+4 0 0 100 0 18 20 0.0000 4 270 1290 10935 3645 OpenSSL\001
+4 0 0 100 0 18 12 0.0000 4 180 495 10935 3825 [SSL]\001
diff --git a/usr.sbin/httpd/src/modules/ssl/README.dsov.ps b/usr.sbin/httpd/src/modules/ssl/README.dsov.ps
index 73ddf39aa2d..def19dbecfa 100644
--- a/usr.sbin/httpd/src/modules/ssl/README.dsov.ps
+++ b/usr.sbin/httpd/src/modules/ssl/README.dsov.ps
@@ -1,15 +1,15 @@
%!PS-Adobe-2.0
%%Title: README.dsov.ps
%%Creator: fig2dev Version 3.2 Patchlevel 1
-%%CreationDate: Thu Jan 28 11:08:27 1999
+%%CreationDate: Mon Apr 12 17:09:11 1999
%%For: rse@en1.engelschall.com (Ralf S. Engelschall)
%%Orientation: Landscape
-%%BoundingBox: 42 11 570 781
+%%BoundingBox: 59 37 553 755
%%Pages: 1
%%BeginSetup
%%IncludeFeature: *PageSize Letter
%%EndSetup
-%%Magnification: 1.0000
+%%Magnification: 0.9340
%%EndComments
/$F2psDict 200 dict def
$F2psDict begin
@@ -55,7 +55,7 @@ $F2psDict /mtrx matrix put
end
save
-30.0 -15.0 translate
+48.0 12.0 translate
90 rotate
1 -1 scale
@@ -137,7 +137,7 @@ newfontname newfont definefont pop end } def
$F2psBegin
10 setmiterlimit
n -1000 9572 m -1000 -1000 l 13622 -1000 l 13622 9572 l cp clip
- 0.06299 0.06299 sc
+ 0.05883 0.05883 sc
%%Page: 1 1
% Polyline
7.500 slw
@@ -866,9 +866,9 @@ n 9690 6930 m 9630 6930 9630 7095 60 arcto 4 {pop} repeat
10170 7155 10170 6990 60 arcto 4 {pop} repeat
10170 6930 9690 6930 60 arcto 4 {pop} repeat
cp gs col35 1.00 shd ef gr gs col35 s gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-8280 5130 m
-gs 1 -1 sc (SSL_get_app_data2\(\)) col0 sh gr
+/Times-Roman-iso ff 120.00 scf sf
+900 7560 m
+gs 1 -1 sc (Startup, Runtime, Shutdown) col0 sh gr
/Helvetica-Narrow-iso ff 120.00 scf sf
6345 2970 m
gs 1 -1 sc (ap_ctx_get\(...,) col0 sh gr
@@ -943,9 +943,9 @@ gs 1 -1 sc (->module_config,) col0 sh gr
/Helvetica-Narrow-iso ff 120.00 scf sf
7740 2970 m
gs 1 -1 sc (&ssl_module\)) col0 sh gr
-/Times-Roman-iso ff 120.00 scf sf
-900 7560 m
-gs 1 -1 sc (Startup, Runtime, Shutdown) col0 sh gr
+/Helvetica-Narrow-iso ff 120.00 scf sf
+6345 3105 m
+gs 1 -1 sc ("ssl_module"\)) col0 sh gr
/Times-Roman-iso ff 120.00 scf sf
1350 7335 m
gs 1 -1 sc (Configuration Time) col0 sh gr
@@ -1001,16 +1001,16 @@ gs 1 -1 sc (X509_STORE_CTX_get_app_data\(\)) col0 sh gr
10980 6705 m
gs 1 -1 sc (SSL_CTX_get_cert_store\(\)) col0 sh gr
/Helvetica-Narrow-iso ff 120.00 scf sf
-6345 3105 m
-gs 1 -1 sc ("ssl_module"\)) col0 sh gr
+8280 5130 m
+gs 1 -1 sc (SSL_get_app_data2\(\)) col0 sh gr
/Helvetica-Bold-iso ff 180.00 scf sf
3645 1620 m
gs 1 -1 sc (SSLDirConfig) col0 sh gr
/Helvetica-Bold-iso ff 300.00 scf sf
-11115 3645 m
-gs 1 -1 sc (SSLeay) col0 sh gr
+10935 3645 m
+gs 1 -1 sc (OpenSSL) col0 sh gr
/Helvetica-Bold-iso ff 180.00 scf sf
-11115 3825 m
+10935 3825 m
gs 1 -1 sc ([SSL]) col0 sh gr
/Helvetica-Bold-iso ff 180.00 scf sf
11025 5760 m
@@ -1019,8 +1019,8 @@ gs 1 -1 sc (SSL_CIPHER) col0 sh gr
10980 6165 m
gs 1 -1 sc (SSL_SESSION) col0 sh gr
/Helvetica-Bold-iso ff 300.00 scf sf
-8730 3465 m
-gs 1 -1 sc (mod_ssl) col0 sh gr
+10710 7605 m
+gs 1 -1 sc (OpenSSL) col0 sh gr
/Helvetica-Bold-iso ff 180.00 scf sf
10575 7110 m
gs 1 -1 sc (X509_STORE_CTX) col0 sh gr
@@ -1069,7 +1069,7 @@ gs 1 -1 sc (request_rec) col0 sh gr
gs 1 -1 sc (Ralf S. Engelschall) col0 sh gr
/Helvetica-Bold-iso ff 300.00 scf sf
4275 675 m
-gs 1 -1 sc (Apache+mod_ssl+SSLeay) col0 sh gr
+gs 1 -1 sc (Apache+mod_ssl+OpenSSL) col0 sh gr
/Times-Roman-iso ff 150.00 scf sf
10575 855 m
gs 1 -1 sc (rse@engelschall.com) col0 sh gr
@@ -1081,22 +1081,22 @@ gs 1 -1 sc (www.engelschall.com) col0 sh gr
gs 1 -1 sc (Version 1.3) col0 sh gr
/Times-Roman-iso ff 180.00 scf sf
900 855 m
-gs 1 -1 sc (27-Jan-1998) col0 sh gr
+gs 1 -1 sc (12-Apr-1999) col0 sh gr
/Helvetica-Bold-iso ff 360.00 scf sf
3915 1080 m
gs 1 -1 sc (Data Structure Overview) col0 sh gr
/Helvetica-Bold-iso ff 180.00 scf sf
9720 7110 m
gs 1 -1 sc (BIO) col0 sh gr
-/Helvetica-Bold-iso ff 300.00 scf sf
-8145 6750 m
-gs 1 -1 sc (Apache) col0 sh gr
/Helvetica-Bold-iso ff 180.00 scf sf
-10935 7785 m
+10710 7785 m
gs 1 -1 sc ([Crypto]) col0 sh gr
/Helvetica-Bold-iso ff 300.00 scf sf
-10935 7605 m
-gs 1 -1 sc (SSLeay) col0 sh gr
+8730 3465 m
+gs 1 -1 sc (mod_ssl) col0 sh gr
+/Helvetica-Bold-iso ff 300.00 scf sf
+8145 6750 m
+gs 1 -1 sc (Apache) col0 sh gr
/Helvetica-Bold-iso ff 300.00 scf sf
9000 8100 m
gs 1 -1 sc (Chaining) col0 sh gr
diff --git a/usr.sbin/httpd/src/modules/ssl/libssl.module b/usr.sbin/httpd/src/modules/ssl/libssl.module
index a9bb26c49a8..444a3818c5b 100644
--- a/usr.sbin/httpd/src/modules/ssl/libssl.module
+++ b/usr.sbin/httpd/src/modules/ssl/libssl.module
@@ -1,8 +1,8 @@
## _ _
-## _ __ ___ ___ __| | ___ ___| |
-## | '_ ` _ \ / _ \ / _` | / __/ __| |
-## | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-## |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+## _ __ ___ ___ __| | ___ ___| | mod_ssl
+## | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+## | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+## |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
## |_____|
## libssl.module
## Apache 1.3 Configuration mechanism module stub
@@ -28,7 +28,7 @@
## software must display the following acknowledgment:
## "This product includes software developed by
## Ralf S. Engelschall <rse@engelschall.com> for use in the
-## mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+## mod_ssl project (http://www.modssl.org/)."
##
## 4. The names "mod_ssl" must not be used to endorse or promote
## products derived from this software without prior written
@@ -43,7 +43,7 @@
## acknowledgment:
## "This product includes software developed by
## Ralf S. Engelschall <rse@engelschall.com> for use in the
-## mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+## mod_ssl project (http://www.modssl.org/)."
##
## THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
## EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -139,10 +139,12 @@ ConfigStart
my_rule_SSL_COMPAT=$SSL_COMPAT
my_rule_SSL_SDBM=$SSL_SDBM
my_rule_SSL_EXPERIMENTAL=$SSL_EXPERIMENTAL
+ my_rule_SSL_VENDOR=$SSL_VENDOR
else
my_rule_SSL_COMPAT=`./helpers/CutRule SSL_COMPAT $file`
my_rule_SSL_SDBM=`./helpers/CutRule SSL_SDBM $file`
my_rule_SSL_EXPERIMENTAL=`./helpers/CutRule SSL_EXPERIMENTAL $file`
+ my_rule_SSL_VENDOR=`./helpers/CutRule SSL_VENDOR $file`
fi
#
@@ -165,6 +167,25 @@ ConfigStart
echo "$my_prefix SSL interface experimental code: disabled"
fi
+ #
+ # determine vendor mode
+ #
+ SSL_VENDOR_OBJS=''
+ SSL_VENDOR_OBJS_PIC=''
+ if [ ".$my_rule_SSL_VENDOR" = .yes ]; then
+ echo "$my_prefix SSL interface vendor extensions: enabled"
+ SSL_CFLAGS="$SSL_CFLAGS -DSSL_VENDOR"
+ my_src="`cd $my_dir && echo ssl_vendor*.c`"
+ if [ ".$my_src" != . -a ".$my_src" != ".ssl_vendor*.c" ]; then
+ SSL_CFLAGS="$SSL_CFLAGS -DSSL_VENDOR_OBJS"
+ SSL_VENDOR_OBJS="`echo $my_src | sed -e 's;\.c;.o;g'`"
+ SSL_VENDOR_OBJS_PIC="`echo $my_src | sed -e 's;\.c;.lo;g'`"
+ echo "$my_prefix SSL interface vendor objects: $SSL_VENDOR_OBJS"
+ fi
+ else
+ echo "$my_prefix SSL interface vendor extensions: disabled"
+ fi
+
#
# determine DBM support library
# (src/Configure has DBM_LIB predefined for some platforms)
@@ -242,7 +263,7 @@ ConfigStart
else
if [ ! -d "$SSL_BASE" ]; then
echo "Error: Cannot find SSL installation in $SSL_BASE" 1>&2
- echo "Hint: Please provide us with the location of SSLeay" 1>&2
+ echo "Hint: Please provide us with the location of OpenSSL" 1>&2
echo " via the environment variable SSL_BASE." 1>&2
exit 1
fi
@@ -250,7 +271,9 @@ ConfigStart
fi
#
- # determine location of SSLeay binaries
+ # determine location of OpenSSL binaries
+ # (we still search also for `ssleay' to allow us to
+ # better complain about the actually installed version)
#
SSL_BINDIR=""
if [ ".$SSL_BASE" = .SYSTEM ]; then
@@ -267,8 +290,12 @@ ConfigStart
fi
done
if [ ".$SSL_BINDIR" = . ]; then
- echo "Error: Cannot find SSL binaries in $PATH" 1>&2
- exit 1
+# echo "Error: Cannot find SSL binaries in $PATH" 1>&2
+# exit 1
+# Kludge for OpenBSD - Make sure we work even if the stuff
+# isn't there yet.
+ SSL_BINDIR="/usr/sbin"
+ SSL_PROGRAM="/usr/sbin/openssl"
fi
else
for name in openssl ssleay; do
@@ -290,12 +317,28 @@ ConfigStart
fi
#
- # determine location of SSLeay headers
+ # SSL version
+ #
+# kludged for OpenBSD - Don't want this retarded shit breaking make build
+# when openssl isn't there yet.
+# SSL_VERSION_ID="`$SSL_PROGRAM version`"
+# echo "$my_prefix SSL library version: $SSL_VERSION_ID"
+# case $SSL_VERSION_ID in
+# *0.[5678].*|*0.9.[012]* )
+# echo "Error: OpenSSL VERSIONS BELOW 0.9.3 ARE NO LONGER SUPPORTED."
+# echo "Hint: Use OpenSSL version 0.9.3 or higher!"
+# exit 1
+# ;;
+# esac
+ SSL_VERSION_ID=0.9.4
+
+ #
+ # determine location of OpenSSL headers
#
if [ ".$SSL_BASE" = .SYSTEM ]; then
SSL_INCDIR=""
for p in . /usr/include /usr/include/ssl/ /usr/local/include /usr/local/include/ssl; do
- if [ -f "$p/ssl.h" ]; then
+ if [ -f "$p/openssl/ssl.h" ]; then
SSL_INCDIR="$p"
break
fi
@@ -306,21 +349,17 @@ ConfigStart
exit 1
fi
else
- if [ -f "$SSL_BASE/include/ssl.h" ]; then
+ if [ -f "$SSL_BASE/include/openssl/ssl.h" ]; then
SSL_INCDIR='$(SSL_BASE)/include'
else
- if [ -f "$SSL_BASE/ssl.h" ]; then
- SSL_INCDIR='$(SSL_BASE)'
- else
- echo "Error: Cannot find SSL header files under $SSL_BASE" 1>&2
- exit 1
- fi
+ echo "Error: Cannot find SSL header files under $SSL_BASE" 1>&2
+ exit 1
fi
fi
SSL_CFLAGS="$SSL_CFLAGS -I\$(SSL_INCDIR)"
#
- # determine location of SSLeay libraries
+ # determine location of OpenSSL libraries
#
if [ ".$SSL_BASE" = .SYSTEM ]; then
SSL_LIBDIR=""
@@ -337,17 +376,15 @@ ConfigStart
exit 1
fi
else
- if [ -f "$SSL_BASE/lib/libssl.a" ]; then
+ if [ -f "$SSL_BASE/libssl.a" ]; then
+ SSL_LIBDIR='$(SSL_BASE)'
+ my_real_ssl_libdir="$SSL_BASE"
+ elif [ -f "$SSL_BASE/lib/libssl.a" ]; then
SSL_LIBDIR='$(SSL_BASE)/lib'
my_real_ssl_libdir="$SSL_BASE/lib"
else
- if [ -f "$SSL_BASE/libssl.a" ]; then
- SSL_LIBDIR='$(SSL_BASE)'
- my_real_ssl_libdir="$SSL_BASE"
- else
- echo "Error: Cannot find SSL library files under $SSL_BASE" 1>&2
- exit 1
- fi
+ echo "Error: Cannot find SSL library files under $SSL_BASE" 1>&2
+ exit 1
fi
fi
SSL_LDFLAGS="$SSL_LDFLAGS -L\$(SSL_LIBDIR)"
@@ -367,19 +404,6 @@ ConfigStart
echo "$my_prefix SSL library type: $my_type $my_note"
#
- # SSL version
- #
- SSLEAY_VERSION="`$SSL_PROGRAM version`"
- echo "$my_prefix SSL library version: $SSLEAY_VERSION"
- case $SSLEAY_VERSION in
- *0.[5678].* )
- echo "$my_prefixe WARNING: THE SSLeay VERSIONS BELOW 0.9.0 ARE NO LONGER SUPPORTED."
- echo "$my_prefixe Hint: Use SSLeay version 0.9.0b or any OpenSSL version."
- exit 1
- ;;
- esac
-
- #
# support for RSAref library
#
if [ ".$RSA_BASE" = . ]; then
@@ -387,7 +411,7 @@ ConfigStart
fi
if [ ".$RSA_BASE" != . ]; then
if [ ! -f "$my_real_ssl_libdir/libRSAglue.a" ]; then
- echo "Error: Cannot find SSLeay's RSAglue library under $my_real_ssl_libdir" 1>&2
+ echo "Error: Cannot find OpenSSL's RSAglue library under $my_real_ssl_libdir" 1>&2
exit 1
else
SSL_LIBS="$SSL_LIBS -lRSAglue"
@@ -443,18 +467,16 @@ ConfigStart
SSL_LIBS="$SSL_LIBS -lrsaref"
echo "$my_prefix SSL library plugin path: $RSA_BASE/librsaref.a"
my_found=yes
+ elif [ -f "$RSA_BASE/rsaref.a" ]; then
+ SSL_LIBS="$SSL_LIBS $RSA_BASE/rsaref.a"
+ echo "$my_prefix SSL library plugin path: $RSA_BASE/rsaref.a"
+ my_found=yes
else
- if [ -f "$RSA_BASE/rsaref.a" ]; then
- SSL_LIBS="$SSL_LIBS $RSA_BASE/rsaref.a"
- echo "$my_prefix SSL library plugin path: $RSA_BASE/rsaref.a"
+ wild="`echo $RSA_BASE/*/rsaref.a`"
+ if [ -f "$wild" ]; then
+ SSL_LIBS="$SSL_LIBS $wild"
+ echo "$my_prefix SSL library plugin path: $wild"
my_found=yes
- else
- wild="`echo $RSA_BASE/*/rsaref.a`"
- if [ -f "$wild" ]; then
- SSL_LIBS="$SSL_LIBS $wild"
- echo "$my_prefix SSL library plugin path: $wild"
- my_found=yes
- fi
fi
fi
if [ .$my_found = .no ]; then
@@ -494,6 +516,8 @@ ConfigStart
echo "SSL_PROGRAM=$SSL_PROGRAM" >>$my_outfile
echo "SSL_VERSION=$SSL_VERSION" >>$my_outfile
echo "SSL_CFLAGS=$SSL_CFLAGS" >>$my_outfile
+ echo "SSL_VENDOR_OBJS=$SSL_VENDOR_OBJS" >>$my_outfile
+ echo "SSL_VENDOR_OBJS_PIC=$SSL_VENDOR_OBJS_PIC" >>$my_outfile
if [ ".$my_buildtype" = .DSO ]; then
# under DSO we link ourself
echo "SSL_LIBS=$SSL_LIBS" >>$my_outfile
diff --git a/usr.sbin/httpd/src/modules/ssl/libssl.version b/usr.sbin/httpd/src/modules/ssl/libssl.version
index 851544d6678..d6396570caf 100644
--- a/usr.sbin/httpd/src/modules/ssl/libssl.version
+++ b/usr.sbin/httpd/src/modules/ssl/libssl.version
@@ -1 +1 @@
-mod_ssl/2.2.3-1.3.4
+mod_ssl/2.4.2-1.3.9
diff --git a/usr.sbin/httpd/src/modules/ssl/mod_ssl.c b/usr.sbin/httpd/src/modules/ssl/mod_ssl.c
index d0c0ae10d3b..d473c1237bd 100644
--- a/usr.sbin/httpd/src/modules/ssl/mod_ssl.c
+++ b/usr.sbin/httpd/src/modules/ssl/mod_ssl.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** mod_ssl.c
** Apache API interface structures
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -74,7 +74,7 @@
* identify the module to SCCS `what' and RCS `ident' commands
*/
static char const sccsid[] = "@(#) mod_ssl/" MOD_SSL_VERSION " >";
-static char const rcsid[] = "$Id: mod_ssl.c,v 1.1 1999/03/01 04:28:50 beck Exp $";
+static char const rcsid[] = "$Id: mod_ssl.c,v 1.2 1999/09/29 06:29:45 beck Exp $";
/*
* the table of configuration directives we provide
@@ -107,9 +107,12 @@ static command_rec ssl_config_cmds[] = {
"(`XXX:...:XXX' - see manual)")
AP_SRV_CMD(CertificateFile, TAKE1,
"SSL Server Certificate file "
- "(`/path/to/file' - PEM encoded)")
+ "(`/path/to/file' - PEM or DER encoded)")
AP_SRV_CMD(CertificateKeyFile, TAKE1,
"SSL Server Private Key file "
+ "(`/path/to/file' - PEM or DER encoded)")
+ AP_SRV_CMD(CertificateChainFile, TAKE1,
+ "SSL Server CA Certificate Chain file "
"(`/path/to/file' - PEM encoded)")
#ifdef SSL_EXPERIMENTAL
AP_ALL_CMD(CACertificatePath, TAKE1,
@@ -126,12 +129,18 @@ static command_rec ssl_config_cmds[] = {
"SSL CA Certificate file "
"(`/path/to/file' - PEM encoded)")
#endif
+ AP_SRV_CMD(CARevocationPath, TAKE1,
+ "SSL CA Certificate Revocation List (CRL) path "
+ "(`/path/to/dir' - contains PEM encoded files)")
+ AP_SRV_CMD(CARevocationFile, TAKE1,
+ "SSL CA Certificate Revocation List (CRL) file "
+ "(`/path/to/file' - PEM encoded)")
AP_ALL_CMD(VerifyClient, TAKE1,
"SSL Client verify type "
"(`none', `optional', `require', `optional_no_ca')")
AP_ALL_CMD(VerifyDepth, TAKE1,
"SSL Client verify depth "
- "(`N' - number of intermediate certifcates)")
+ "(`N' - number of intermediate certificates)")
AP_SRV_CMD(SessionCacheTimeout, TAKE1,
"SSL Session Cache object lifetime "
"(`N' - number of seconds)")
@@ -181,9 +190,9 @@ module MODULE_VAR_EXPORT ssl_module = {
ssl_config_server_merge, /* merge per-server config structures */
ssl_config_cmds, /* table of config file commands */
ssl_config_handler, /* [#8] MIME-typed-dispatched handlers */
- NULL, /* [#1] URI to filename translation */
+ ssl_hook_Translate, /* [#1] URI to filename translation */
ssl_hook_Auth, /* [#4] validate user id from request */
- NULL, /* [#5] check if the user is ok _here_ */
+ ssl_hook_UserCheck, /* [#5] check if the user is ok _here_ */
ssl_hook_Access, /* [#3] check access by host address */
NULL, /* [#6] determine MIME type */
ssl_hook_Fixup, /* [#7] pre-run fixups */
@@ -198,7 +207,7 @@ module MODULE_VAR_EXPORT ssl_module = {
ssl_hook_AddModule, /* after modules was added to core */
ssl_hook_RemoveModule, /* before module is removed from core */
ssl_hook_RewriteCommand, /* configuration command rewriting */
- ssl_hook_NewConnection /* configuration command rewriting */
+ ssl_hook_NewConnection, /* socket connection open */
+ ssl_hook_CloseConnection /* socket connection close */
};
-
diff --git a/usr.sbin/httpd/src/modules/ssl/mod_ssl.h b/usr.sbin/httpd/src/modules/ssl/mod_ssl.h
index d1481b83de1..812bf6f3c46 100644
--- a/usr.sbin/httpd/src/modules/ssl/mod_ssl.h
+++ b/usr.sbin/httpd/src/modules/ssl/mod_ssl.h
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** mod_ssl.h
** Global header
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -75,16 +75,21 @@
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
+#include <time.h>
+#ifndef WIN32
+#include <sys/time.h>
+#endif
#include <sys/stat.h>
-/* SSLeay headers */
-#include <ssl.h>
-#include <err.h>
-#include <x509.h>
-#include <pem.h>
-#include <crypto.h>
-#include <evp.h>
-#include <rand.h>
+/* OpenSSL headers */
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
/* Apache headers */
#define CORE_PRIVATE
@@ -93,6 +98,7 @@
#include "http_config.h"
#include "http_conf_globals.h"
#include "http_protocol.h"
+#include "http_request.h"
#include "http_main.h"
#include "http_core.h"
#include "http_log.h"
@@ -103,21 +109,32 @@
/* mod_ssl headers */
#include "ssl_expr.h"
#include "ssl_util_ssl.h"
+#include "ssl_util_table.h"
/*
* Provide reasonable default for some defines
*/
#ifndef FALSE
-#define FALSE 0
+#define FALSE (0)
#endif
#ifndef TRUE
-#define TRUE !FALSE
+#define TRUE (!FALSE)
+#endif
+#ifndef PFALSE
+#define PFALSE ((void *)FALSE)
+#endif
+#ifndef PTRUE
+#define PTRUE ((void *)TRUE)
#endif
#ifndef UNSET
-#define UNSET -1
+#define UNSET (-1)
#endif
#ifndef NUL
-#define NUL '\0'
+#define NUL '\0'
+#endif
+#ifndef RAND_MAX
+#include <limits.h>
+#define RAND_MAX INT_MAX
#endif
/*
@@ -148,6 +165,7 @@
#define cfgMerge(el,unset) new->el = add->el == unset ? base->el : add->el
#define cfgMergeArray(el) new->el = ap_append_arrays(p, add->el, base->el)
#define cfgMergeTable(el) new->el = ap_overlay_tables(p, add->el, base->el)
+#define cfgMergeCtx(el) new->el = ap_ctx_overlay(p, add->el, base->el)
#define cfgMergeString(el) cfgMerge(el, NULL)
#define cfgMergeBool(el) cfgMerge(el, UNSET)
#define cfgMergeInt(el) cfgMerge(el, UNSET)
@@ -189,7 +207,6 @@
/*
* Defaults for the configuration
*/
-
#ifndef SSL_SESSION_CACHE_TIMEOUT
#define SSL_SESSION_CACHE_TIMEOUT 300
#endif
@@ -246,6 +263,15 @@
#endif
/*
+ * Support for MM library
+ */
+#ifndef WIN32
+#define SSL_MM_FILE_MODE ( S_IRUSR|S_IWUSR )
+#else
+#define SSL_MM_FILE_MODE ( _S_IREAD|_S_IWRITE )
+#endif
+
+/*
* Support for DBM library
*/
#ifndef WIN32
@@ -266,8 +292,13 @@
#define ssl_dbm_nextkey sdbm_nextkey
#define SSL_DBM_FILE_SUFFIX_DIR ".dir"
#define SSL_DBM_FILE_SUFFIX_PAG ".pag"
+#else /* !SSL_USE_SDBM */
+#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) \
+ && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
+#include <db1/ndbm.h>
#else
#include <ndbm.h>
+#endif
#define ssl_dbm_open dbm_open
#define ssl_dbm_close dbm_close
#define ssl_dbm_store dbm_store
@@ -275,7 +306,11 @@
#define ssl_dbm_delete dbm_delete
#define ssl_dbm_firstkey dbm_firstkey
#define ssl_dbm_nextkey dbm_nextkey
-#if defined(__FreeBSD__) || (defined(DB_LOCK) && defined(DB_SHMEM))
+#if !defined(SSL_DBM_FILE_SUFFIX_DIR) && !defined(SSL_DBM_FILE_SUFFIX_PAG)
+#if defined(DBM_SUFFIX)
+#define SSL_DBM_FILE_SUFFIX_DIR DBM_SUFFIX
+#define SSL_DBM_FILE_SUFFIX_PAG DBM_SUFFIX
+#elif defined(__FreeBSD__) || (defined(DB_LOCK) && defined(DB_SHMEM))
#define SSL_DBM_FILE_SUFFIX_DIR ".db"
#define SSL_DBM_FILE_SUFFIX_PAG ".db"
#else
@@ -283,13 +318,14 @@
#define SSL_DBM_FILE_SUFFIX_PAG ".pag"
#endif
#endif
+#endif /* !SSL_USE_SDBM */
/*
- * Check for SSLeay 0.9.0 and below
- * and enabled Extended API (EAPI)
+ * Check for OpenSSL version and whether
+ * Extended API (EAPI) is enabled
*/
-#if SSL_LIBRARY_VERSION < 0x0900
-#error "SSLeay versions below 0.9.0 are no longer supported"
+#if SSL_LIBRARY_VERSION < 0x00903100
+#error "mod_ssl requires OpenSSL 0.9.3 or higher"
#endif
#ifndef EAPI
#error "mod_ssl requires Extended API (EAPI)"
@@ -312,6 +348,21 @@ typedef struct {
} ssl_ds_table;
/*
+ * Define the certificate algorithm types
+ */
+
+typedef int ssl_algo_t;
+
+#define SSL_ALGO_UNKNOWN (0)
+#define SSL_ALGO_RSA (1<<0)
+#define SSL_ALGO_DSA (1<<1)
+#define SSL_ALGO_ALL (SSL_ALGO_RSA|SSL_ALGO_DSA)
+
+#define SSL_AIDX_RSA (0)
+#define SSL_AIDX_DSA (1)
+#define SSL_AIDX_MAX (2)
+
+/*
* Define the SSL options
*/
#define SSL_OPT_NONE (0)
@@ -319,13 +370,14 @@ typedef struct {
#define SSL_OPT_COMPATENVVARS (1<<1)
#define SSL_OPT_EXPORTCERTDATA (1<<2)
#define SSL_OPT_FAKEBASICAUTH (1<<3)
-#define SSL_OPT_ALL (SSL_OPT_COMPATENVVAR|SSL_OPT_EXPORTCERTDATA|SSL_OPT_FAKEBASICAUTH)
+#define SSL_OPT_STRICTREQUIRE (1<<4)
+#define SSL_OPT_OPTRENEGOTIATE (1<<5)
+#define SSL_OPT_ALL (SSL_OPT_COMPATENVVAR|SSL_OPT_EXPORTCERTDATA|SSL_OPT_FAKEBASICAUTH|SSL_OPT_STRICTREQUIRE|SSL_OPT_OPTRENEGOTIATE)
typedef int ssl_opt_t;
/*
* Define the SSL Protocol options
*/
-
#define SSL_PROTOCOL_NONE (0)
#define SSL_PROTOCOL_SSLV2 (1<<0)
#define SSL_PROTOCOL_SSLV3 (1<<1)
@@ -433,30 +485,29 @@ typedef struct {
typedef struct {
pool *pPool;
BOOL bFixed;
-
- /*
- * global config data
- */
int nInitCount;
-
- RSA *pRSATmpKey;
+ RSA *pRSATmpKey512;
+ RSA *pRSATmpKey1024;
+ DH *pDHTmpParam512;
+ DH *pDHTmpParam1024;
int nSessionCacheMode;
char *szSessionCacheDataFile;
+ int nSessionCacheDataSize;
+ AP_MM *pSessionCacheDataMM;
+ table_t *tSessionCacheDataTable;
ssl_mutexmode_t nMutexMode;
char *szMutexFile;
int nMutexFD;
int nMutexSEMID;
array_header *aRandSeed;
-
ssl_ds_table *tPublicCert;
ssl_ds_table *tPrivateKey;
-
- /*
- * arbitrary global context data
- */
struct {
void *pV1, *pV2, *pV3, *pV4, *pV5, *pV6, *pV7, *pV8, *pV9;
} rCtx;
+#ifdef SSL_VENDOR
+ ap_ctx *ctx;
+#endif
} SSLModConfigRec;
/*
@@ -466,8 +517,9 @@ typedef struct {
*/
typedef struct {
BOOL bEnabled;
- char *szCertificateFile;
- char *szKeyFile;
+ char *szPublicCertFile[SSL_AIDX_MAX];
+ char *szPrivateKeyFile[SSL_AIDX_MAX];
+ char *szCertificateChain;
char *szCACertificatePath;
char *szCACertificateFile;
char *szLogFile;
@@ -476,13 +528,19 @@ typedef struct {
int nLogLevel;
int nVerifyDepth;
ssl_verify_t nVerifyClient;
- X509 *px509Certificate;
- RSA *prsaKey;
+ X509 *pPublicCert[SSL_AIDX_MAX];
+ EVP_PKEY *pPrivateKey[SSL_AIDX_MAX];
SSL_CTX *pSSLCtx;
int nSessionCacheTimeout;
int nPassPhraseDialogType;
char *szPassPhraseDialogPath;
ssl_proto_t nProtocol;
+ char *szCARevocationPath;
+ char *szCARevocationFile;
+ X509_STORE *pRevocationStore;
+#ifdef SSL_VENDOR
+ ap_ctx *ctx;
+#endif
} SSLSrvConfigRec;
/*
@@ -503,6 +561,9 @@ typedef struct {
char *szCACertificatePath;
char *szCACertificateFile;
#endif
+#ifdef SSL_VENDOR
+ ap_ctx *ctx;
+#endif
} SSLDirConfigRec;
/*
@@ -523,13 +584,16 @@ void *ssl_config_perdir_merge(pool *, void *, void *);
const char *ssl_cmd_SSLMutex(cmd_parms *, char *, char *);
const char *ssl_cmd_SSLPassPhraseDialog(cmd_parms *, char *, char *);
const char *ssl_cmd_SSLRandomSeed(cmd_parms *, char *, char *, char *, char *);
-const char *ssl_cmd_SSLEngine(cmd_parms *, char *, int flag);
+const char *ssl_cmd_SSLEngine(cmd_parms *, char *, int);
const char *ssl_cmd_SSLCipherSuite(cmd_parms *, SSLDirConfigRec *, char *);
const char *ssl_cmd_SSLCertificateFile(cmd_parms *, char *, char *);
const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, char *, char *);
+const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *, char *, char *);
const char *ssl_cmd_SSLCACertificatePath(cmd_parms *, SSLDirConfigRec *, char *);
const char *ssl_cmd_SSLCACertificateFile(cmd_parms *, SSLDirConfigRec *, char *);
-const char *ssl_cmd_SSLVerifyClient(cmd_parms *, SSLDirConfigRec *, char *level);
+const char *ssl_cmd_SSLCARevocationPath(cmd_parms *, SSLDirConfigRec *, char *);
+const char *ssl_cmd_SSLCARevocationFile(cmd_parms *, SSLDirConfigRec *, char *);
+const char *ssl_cmd_SSLVerifyClient(cmd_parms *, SSLDirConfigRec *, char *);
const char *ssl_cmd_SSLVerifyDepth(cmd_parms *, SSLDirConfigRec *, char *);
const char *ssl_cmd_SSLSessionCache(cmd_parms *, char *, char *);
const char *ssl_cmd_SSLSessionCacheTimeout(cmd_parms *, char *, char *);
@@ -542,27 +606,35 @@ const char *ssl_cmd_SSLRequire(cmd_parms *, SSLDirConfigRec *, char *);
/* module initialization */
void ssl_init_Module(server_rec *, pool *);
-void ssl_init_SSLLibrary(server_rec *);
-void ssl_init_GetCertAndKey(server_rec *, pool *, SSLSrvConfigRec *);
-STACK *ssl_init_FindCAList(server_rec *, pool *, char *, char *);
+void ssl_init_SSLLibrary(void);
+void ssl_init_ConfigureServer(server_rec *, pool *, SSLSrvConfigRec *);
+void ssl_init_CheckServers(server_rec *, pool *);
+STACK_OF(X509_NAME)
+ *ssl_init_FindCAList(server_rec *, pool *, char *, char *);
void ssl_init_Child(server_rec *, pool *);
+void ssl_init_ChildKill(void *);
+void ssl_init_ModuleKill(void *);
/* Apache API hooks */
void ssl_hook_AddModule(module *);
void ssl_hook_RemoveModule(module *);
-char *ssl_hook_RewriteCommand(cmd_parms *, void *config, const char *);
+char *ssl_hook_RewriteCommand(cmd_parms *, void *, const char *);
void ssl_hook_NewConnection(conn_rec *);
void ssl_hook_TimeoutConnection(int);
-void ssl_hook_CloseConnection(void *);
+void ssl_hook_CloseConnection(conn_rec *);
+int ssl_hook_Translate(request_rec *);
int ssl_hook_Auth(request_rec *);
+int ssl_hook_UserCheck(request_rec *);
int ssl_hook_Access(request_rec *);
int ssl_hook_Fixup(request_rec *);
int ssl_hook_ReadReq(request_rec *);
int ssl_hook_Handler(request_rec *);
-/* SSLeay callbacks */
-RSA *ssl_callback_TmpRSA(SSL *, int);
+/* OpenSSL callbacks */
+RSA *ssl_callback_TmpRSA(SSL *, int, int);
+DH *ssl_callback_TmpDH(SSL *, int, int);
int ssl_callback_SSLVerify(int, X509_STORE_CTX *);
+int ssl_callback_SSLVerify_CRL(int, X509_STORE_CTX *, server_rec *);
int ssl_callback_NewSessionCacheEntry(SSL *, SSL_SESSION *);
SSL_SESSION *ssl_callback_GetSessionCacheEntry(SSL *, unsigned char *, int, int *);
void ssl_callback_DelSessionCacheEntry(SSL_CTX *, SSL_SESSION *);
@@ -570,21 +642,36 @@ void ssl_callback_LogTracingState(SSL *, int, int);
/* Session Cache Support */
void ssl_scache_init(server_rec *, pool *);
-void ssl_scache_store(server_rec *, SSL_SESSION *, int);
+void ssl_scache_kill(server_rec *);
+BOOL ssl_scache_store(server_rec *, SSL_SESSION *, int);
SSL_SESSION *ssl_scache_retrieve(server_rec *, UCHAR *, int);
void ssl_scache_remove(server_rec *, SSL_SESSION *);
-void ssl_scache_expire(server_rec *);
+void ssl_scache_expire(server_rec *, time_t);
+void ssl_scache_status(server_rec *, pool *, void (*)(char *, void *), void *);
char *ssl_scache_id2sz(UCHAR *, int);
void ssl_scache_dbm_init(server_rec *, pool *);
-void ssl_scache_dbm_store(server_rec *, ssl_scinfo_t *);
+void ssl_scache_dbm_kill(server_rec *);
+BOOL ssl_scache_dbm_store(server_rec *, ssl_scinfo_t *);
void ssl_scache_dbm_retrieve(server_rec *, ssl_scinfo_t *);
void ssl_scache_dbm_remove(server_rec *, ssl_scinfo_t *);
-void ssl_scache_dbm_expire(server_rec *);
+void ssl_scache_dbm_expire(server_rec *, time_t);
+void ssl_scache_dbm_status(server_rec *, pool *, void (*)(char *, void *), void *);
+void ssl_scache_shm_init(server_rec *, pool *);
+void ssl_scache_shm_kill(server_rec *);
+BOOL ssl_scache_shm_store(server_rec *, ssl_scinfo_t *);
+void ssl_scache_shm_retrieve(server_rec *, ssl_scinfo_t *);
+void ssl_scache_shm_remove(server_rec *, ssl_scinfo_t *);
+void ssl_scache_shm_expire(server_rec *, time_t);
+void ssl_scache_shm_status(server_rec *, pool *, void (*)(char *, void *), void *);
/* Pass Phrase Support */
void ssl_pphrase_Handle(server_rec *, pool *);
int ssl_pphrase_Handle_CB(char *, int, int);
+/* Diffie-Hellman Parameter Support */
+DH *ssl_dh_GetTmpParam(int);
+DH *ssl_dh_GetParamFromFile(char *);
+
/* Data Structures */
ssl_ds_array *ssl_ds_array_make(pool *, int);
BOOL ssl_ds_array_isempty(ssl_ds_array *);
@@ -601,9 +688,10 @@ void ssl_ds_table_kill(ssl_ds_table *);
/* Mutex Support */
void ssl_mutex_init(server_rec *, pool *);
-void ssl_mutex_open(server_rec *, pool *);
-void ssl_mutex_on(void);
-void ssl_mutex_off(void);
+void ssl_mutex_reinit(server_rec *, pool *);
+void ssl_mutex_on(server_rec *);
+void ssl_mutex_off(server_rec *);
+void ssl_mutex_kill(server_rec *s);
void ssl_mutex_file_create(server_rec *, pool *);
void ssl_mutex_file_open(server_rec *, pool *);
void ssl_mutex_file_remove(void *);
@@ -616,7 +704,8 @@ BOOL ssl_mutex_sem_acquire(void);
BOOL ssl_mutex_sem_release(void);
/* Logfile Support */
-void ssl_log_open(server_rec *, pool *);
+void ssl_log_open(server_rec *, server_rec *, pool *);
+BOOL ssl_log_applies(server_rec *, int);
void ssl_log(server_rec *, int, const char *, ...);
void ssl_die(void);
@@ -628,7 +717,10 @@ char *ssl_var_lookup(pool *, server_rec *, conn_rec *, request_rec *, cha
/* I/O */
void ssl_io_register(void);
void ssl_io_unregister(void);
-long ssl_io_data_cb(BIO *, int, char *, int, long, long);
+long ssl_io_data_cb(BIO *, int, const char *, int, long, long);
+#ifdef SSL_EXPERIMENTAL
+void ssl_io_suck(request_rec *, SSL *);
+#endif
/* PRNG */
int ssl_rand_seed(server_rec *, pool *, ssl_rsctx_t);
@@ -653,7 +745,15 @@ int ssl_util_ppopen_child(void *, child_info *);
void ssl_util_ppclose(server_rec *, pool *, FILE *);
char *ssl_util_readfilter(server_rec *, pool *, char *);
BOOL ssl_util_path_check(ssl_pathcheck_t, char *);
+ssl_algo_t ssl_util_algotypeof(X509 *, EVP_PKEY *);
+char *ssl_util_algotypestr(ssl_algo_t);
char *ssl_util_ptxtsub(pool *, const char *, const char *, char *);
void ssl_util_thread_setup(void);
+/* Vendor extension support */
+#if defined(SSL_VENDOR) && defined(SSL_VENDOR_OBJS)
+void ssl_vendor_register(void);
+void ssl_vendor_unregister(void);
+#endif
+
#endif /* MOD_SSL_H */
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_compat.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_compat.c
index 967fb206bad..2690de05af2 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_compat.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_compat.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_engine_compat.c
** Backward Compatibility
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -78,9 +78,11 @@
* The mapping of obsolete directives to official ones...
*/
-static char *ssl_compat_SSLRequireCipher(pool *p, const char *, const char *, const char *);
-static char *ssl_compat_SSLBanCipher(pool *p, const char *, const char *, const char *);
-static char *ssl_compat_words2list(pool *p, const char *);
+static char *ssl_compat_SSLSessionLockFile(pool *, const char *, const char *, const char *);
+static char *ssl_compat_SSLCacheDisable(pool *, const char *, const char *, const char *);
+static char *ssl_compat_SSLRequireCipher(pool *, const char *, const char *, const char *);
+static char *ssl_compat_SSLBanCipher(pool *, const char *, const char *, const char *);
+static char *ssl_compat_words2list(pool *, const char *);
#define CRM_BEGIN /* nop */
#define CRM_ENTRY(what,action) { what, action },
@@ -143,8 +145,13 @@ static struct {
/*
* Stronghold 2.x backward compatibility
*/
+ CRM_ENTRY( CRM_CMD("StrongholdAccelerator"), CRM_LOG("Not supported by mod_ssl") )
+ CRM_ENTRY( CRM_CMD("StrongholdKey"), CRM_LOG("Not supported by mod_ssl") )
+ CRM_ENTRY( CRM_CMD("StrongholdLicenseFile"), CRM_LOG("Not supported by mod_ssl") )
CRM_ENTRY( CRM_CMD("SSLFlag"), CRM_SUB("SSLEngine") )
- CRM_ENTRY( CRM_CMD("SSLSessionLockFile"), CRM_SUB("SSLMutex") )
+ CRM_ENTRY( CRM_CMD("SSLClientCAfile"), CRM_SUB("SSLCACertificateFile") )
+ CRM_ENTRY( CRM_CMD("SSLSessionLockFile"), CRM_CAL(ssl_compat_SSLSessionLockFile) )
+ CRM_ENTRY( CRM_CMD("SSLCacheDisable"), CRM_CAL(ssl_compat_SSLCacheDisable) )
CRM_ENTRY( CRM_CMD("RequireSSL"), CRM_SUB("SSLRequireSSL") )
CRM_ENTRY( CRM_CMD("SSLCipherList"), CRM_SUB("SSLCipherSuite") )
CRM_ENTRY( CRM_CMD("SSLErrorFile"), CRM_LOG("Not needed for mod_ssl") )
@@ -162,6 +169,28 @@ static struct {
CRM_END
};
+static char *ssl_compat_SSLSessionLockFile(
+ pool *p, const char *oline, const char *cmd, const char *args)
+{
+ char *cp;
+
+ for (cp = (char *)args; ap_isspace(*cp); cp++)
+ ;
+ return ap_pstrcat(p, "SSLMutex file:", cp, NULL);
+}
+
+static char *ssl_compat_SSLCacheDisable(
+ pool *p, const char *oline, const char *cmd, const char *args)
+{
+ char *cp;
+
+ for (cp = (char *)args; ap_isspace(*cp); cp++)
+ ;
+ if (strcEQ(cp, "on"))
+ return "SSLSessionCache none";
+ return "";
+}
+
static char *ssl_compat_SSLRequireCipher(pool *p, const char *oline, const char *cmd, const char *args)
{
return ap_pstrcat(p, "SSLRequire %{SSL_CIPHER} in {",
@@ -347,6 +376,8 @@ static struct {
VRM_ENTRY( VRM_VAR("SSL_SERVER_CERTIFICATE"), VRM_SUB("SSL_SERVER_CERT") )
VRM_ENTRY( VRM_VAR("SSL_SERVER_CERT_START"), VRM_SUB("SSL_SERVER_V_START") )
VRM_ENTRY( VRM_VAR("SSL_SERVER_CERT_END"), VRM_SUB("SSL_SERVER_V_END") )
+ VRM_ENTRY( VRM_VAR("SSL_SERVER_CERT_SERIAL"), VRM_SUB("SSL_SERVER_M_SERIAL") )
+ VRM_ENTRY( VRM_VAR("SSL_SERVER_SIGNATURE_ALGORITHM"),VRM_SUB("SSL_SERVER_A_SIG") )
VRM_ENTRY( VRM_VAR("SSL_SERVER_DN"), VRM_SUB("SSL_SERVER_S_DN") )
VRM_ENTRY( VRM_VAR("SSL_SERVER_CN"), VRM_SUB("SSL_SERVER_S_DN_CN") )
VRM_ENTRY( VRM_VAR("SSL_SERVER_EMAIL"), VRM_SUB("SSL_SERVER_S_DN_Email") )
@@ -366,6 +397,8 @@ static struct {
VRM_ENTRY( VRM_VAR("SSL_CLIENT_CERTIFICATE"), VRM_SUB("SSL_CLIENT_CERT") )
VRM_ENTRY( VRM_VAR("SSL_CLIENT_CERT_START"), VRM_SUB("SSL_CLIENT_V_START") )
VRM_ENTRY( VRM_VAR("SSL_CLIENT_CERT_END"), VRM_SUB("SSL_CLIENT_V_END") )
+ VRM_ENTRY( VRM_VAR("SSL_CLIENT_CERT_SERIAL"), VRM_SUB("SSL_CLIENT_M_SERIAL") )
+ VRM_ENTRY( VRM_VAR("SSL_CLIENT_SIGNATURE_ALGORITHM"),VRM_SUB("SSL_CLIENT_A_SIG") )
VRM_ENTRY( VRM_VAR("SSL_CLIENT_DN"), VRM_SUB("SSL_CLIENT_S_DN") )
VRM_ENTRY( VRM_VAR("SSL_CLIENT_CN"), VRM_SUB("SSL_CLIENT_S_DN_CN") )
VRM_ENTRY( VRM_VAR("SSL_CLIENT_EMAIL"), VRM_SUB("SSL_CLIENT_S_DN_Email") )
@@ -382,10 +415,15 @@ static struct {
VRM_ENTRY( VRM_VAR("SSL_CLIENT_IC"), VRM_SUB("SSL_CLIENT_I_DN_C") )
VRM_ENTRY( VRM_VAR("SSL_CLIENT_ISP"), VRM_SUB("SSL_CLIENT_I_DN_SP") )
VRM_ENTRY( VRM_VAR("SSL_CLIENT_IL"), VRM_SUB("SSL_CLIENT_I_DN_L") )
+ VRM_ENTRY( VRM_VAR("SSL_EXPORT"), VRM_SUB("SSL_CIPHER_EXPORT") )
+ VRM_ENTRY( VRM_VAR("SSL_KEYSIZE"), VRM_SUB("SSL_CIPHER_ALGKEYSIZE") )
+ VRM_ENTRY( VRM_VAR("SSL_SECRETKEYSIZE"), VRM_SUB("SSL_CIPHER_USEKEYSIZE") )
+ VRM_ENTRY( VRM_VAR("SSL_SSLEAY_VERSION"), VRM_SUB("SSL_VERSION_LIBRARY") )
+ VRM_ENTRY( VRM_VAR("SSL_STRONG_CRYPTO"), VRM_LOG("Not supported by mod_ssl") )
VRM_ENTRY( VRM_VAR("SSL_SERVER_KEY_EXP"), VRM_LOG("Not supported by mod_ssl") )
+ VRM_ENTRY( VRM_VAR("SSL_SERVER_KEY_SIZE"), VRM_LOG("Not supported by mod_ssl") )
VRM_ENTRY( VRM_VAR("SSL_SERVER_KEY_ALGORITHM"), VRM_LOG("Not supported by mod_ssl") )
- VRM_ENTRY( VRM_VAR("SSL_SERVER_SIGNATURE_ALGORITHM"),VRM_LOG("Not supported by mod_ssl") )
VRM_ENTRY( VRM_VAR("SSL_SERVER_SESSIONDIR"), VRM_LOG("Not supported by mod_ssl") )
VRM_ENTRY( VRM_VAR("SSL_SERVER_CERTIFICATELOGDIR"), VRM_LOG("Not supported by mod_ssl") )
VRM_ENTRY( VRM_VAR("SSL_SERVER_CERTFILE"), VRM_LOG("Not supported by mod_ssl") )
@@ -394,7 +432,6 @@ static struct {
VRM_ENTRY( VRM_VAR("SSL_CLIENT_KEY_EXP"), VRM_LOG("Not supported by mod_ssl") )
VRM_ENTRY( VRM_VAR("SSL_CLIENT_KEY_ALGORITHM"), VRM_LOG("Not supported by mod_ssl") )
VRM_ENTRY( VRM_VAR("SSL_CLIENT_KEY_SIZE"), VRM_LOG("Not supported by mod_ssl") )
- VRM_ENTRY( VRM_VAR("SSL_CLIENT_SIGNATURE_ALGORITHM"),VRM_LOG("Not supported by mod_ssl") )
VRM_END
};
@@ -417,9 +454,25 @@ void ssl_compat_variables(request_rec *r)
ap_table_set(r->subprocess_env, cpOld, cpVal);
}
else if (cpMsg != NULL) {
+#ifdef SSL_VENDOR
+ /*
+ * something that isn't provided by mod_ssl, so at least
+ * let vendor extensions provide a reasonable value first.
+ */
+ cpVal = NULL;
+ ap_hook_use("ap::mod_ssl::vendor::compat_variables_lookup",
+ AP_HOOK_SIG3(ptr,ptr,ptr),
+ AP_HOOK_DECLINE(NULL),
+ &cpVal, r, cpOld);
+ if (cpVal != NULL) {
+ ap_table_set(r->subprocess_env, cpOld, cpVal);
+ continue;
+ }
+#endif
+
/*
- * we cannot print a message, so we at least the
- * variables contents to the message
+ * we cannot print a message, so we set at least
+ * the variables content to the compat message
*/
ap_table_set(r->subprocess_env, cpOld, cpMsg);
}
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_config.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_config.c
index 3adf553c20d..68b9c313fc5 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_config.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_config.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_engine_config.c
** Apache Configuration Directives
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -85,6 +85,9 @@ void ssl_hook_AddModule(module *m)
ssl_var_register();
ssl_ext_register();
ssl_io_register();
+#if defined(SSL_VENDOR) && defined(SSL_VENDOR_OBJS)
+ ssl_vendor_register();
+#endif
}
return;
}
@@ -98,6 +101,9 @@ void ssl_hook_RemoveModule(module *m)
ssl_var_unregister();
ssl_ext_unregister();
ssl_io_unregister();
+#if defined(SSL_VENDOR) && defined(SSL_VENDOR_OBJS)
+ ssl_vendor_unregister();
+#endif
}
return;
}
@@ -121,18 +127,29 @@ void ssl_config_global_create(void)
* initialize per-module configuration
*/
mc->nInitCount = 0;
- mc->pRSATmpKey = NULL;
+ mc->pRSATmpKey512 = NULL;
+ mc->pRSATmpKey1024 = NULL;
+ mc->pDHTmpParam512 = NULL;
+ mc->pDHTmpParam1024 = NULL;
mc->nSessionCacheMode = SSL_SCMODE_UNSET;
mc->szSessionCacheDataFile = NULL;
+ mc->nSessionCacheDataSize = 0;
+ mc->pSessionCacheDataMM = NULL;
+ mc->tSessionCacheDataTable = NULL;
mc->nMutexMode = SSL_MUTEXMODE_UNSET;
mc->szMutexFile = NULL;
mc->nMutexFD = -1;
mc->nMutexSEMID = -1;
mc->aRandSeed = ap_make_array(pPool, 4, sizeof(ssl_randseed_t));
-
mc->tPrivateKey = ssl_ds_table_make(pPool, sizeof(ssl_asn1_t));
mc->tPublicCert = ssl_ds_table_make(pPool, sizeof(ssl_asn1_t));
+#ifdef SSL_VENDOR
+ mc->ctx = ap_ctx_new(pPool);
+ ap_hook_use("ap::mod_ssl::vendor::config_global_create",
+ AP_HOOK_SIG2(void,ptr), AP_HOOK_MODE_ALL, mc);
+#endif
+
/*
* And push it into Apache's global context
*/
@@ -172,10 +189,9 @@ void *ssl_config_server_create(pool *p, server_rec *s)
sc = ap_palloc(p, sizeof(SSLSrvConfigRec));
sc->bEnabled = UNSET;
- sc->szCertificateFile = NULL;
- sc->szKeyFile = NULL;
sc->szCACertificatePath = NULL;
sc->szCACertificateFile = NULL;
+ sc->szCertificateChain = NULL;
sc->szLogFile = NULL;
sc->szCipherSuite = NULL;
sc->nLogLevel = SSL_LOG_NONE;
@@ -186,9 +202,22 @@ void *ssl_config_server_create(pool *p, server_rec *s)
sc->szPassPhraseDialogPath = NULL;
sc->nProtocol = SSL_PROTOCOL_ALL;
sc->fileLogFile = NULL;
- sc->px509Certificate = NULL;
- sc->prsaKey = NULL;
sc->pSSLCtx = NULL;
+ sc->szCARevocationPath = NULL;
+ sc->szCARevocationFile = NULL;
+ sc->pRevocationStore = NULL;
+
+ (void)memset(sc->szPublicCertFile, 0, SSL_AIDX_MAX*sizeof(char *));
+ (void)memset(sc->szPrivateKeyFile, 0, SSL_AIDX_MAX*sizeof(char *));
+ (void)memset(sc->pPublicCert, 0, SSL_AIDX_MAX*sizeof(X509 *));
+ (void)memset(sc->pPrivateKey, 0, SSL_AIDX_MAX*sizeof(EVP_PKEY *));
+
+#ifdef SSL_VENDOR
+ sc->ctx = ap_ctx_new(p);
+ ap_hook_use("ap::mod_ssl::vendor::config_server_create",
+ AP_HOOK_SIG4(void,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
+ p, s, sc);
+#endif
return sc;
}
@@ -201,12 +230,12 @@ void *ssl_config_server_merge(pool *p, void *basev, void *addv)
SSLSrvConfigRec *base = (SSLSrvConfigRec *)basev;
SSLSrvConfigRec *add = (SSLSrvConfigRec *)addv;
SSLSrvConfigRec *new = (SSLSrvConfigRec *)ap_palloc(p, sizeof(SSLSrvConfigRec));
+ int i;
cfgMergeBool(bEnabled);
- cfgMergeString(szCertificateFile);
- cfgMergeString(szKeyFile);
cfgMergeString(szCACertificatePath);
cfgMergeString(szCACertificateFile);
+ cfgMergeString(szCertificateChain);
cfgMergeString(szLogFile);
cfgMergeString(szCipherSuite);
cfgMerge(nLogLevel, SSL_LOG_NONE);
@@ -217,9 +246,24 @@ void *ssl_config_server_merge(pool *p, void *basev, void *addv)
cfgMergeString(szPassPhraseDialogPath);
cfgMerge(nProtocol, SSL_PROTOCOL_ALL);
cfgMerge(fileLogFile, NULL);
- cfgMerge(px509Certificate, NULL);
- cfgMerge(prsaKey, NULL);
cfgMerge(pSSLCtx, NULL);
+ cfgMerge(szCARevocationPath, NULL);
+ cfgMerge(szCARevocationFile, NULL);
+ cfgMerge(pRevocationStore, NULL);
+
+ for (i = 0; i < SSL_AIDX_MAX; i++) {
+ cfgMergeString(szPublicCertFile[i]);
+ cfgMergeString(szPrivateKeyFile[i]);
+ cfgMerge(pPublicCert[i], NULL);
+ cfgMerge(pPrivateKey[i], NULL);
+ }
+
+#ifdef SSL_VENDOR
+ cfgMergeCtx(ctx);
+ ap_hook_use("ap::mod_ssl::vendor::config_server_merge",
+ AP_HOOK_SIG5(void,ptr,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
+ p, base, add, new);
+#endif
return new;
}
@@ -245,6 +289,13 @@ void *ssl_config_perdir_create(pool *p, char *dir)
dc->szCACertificateFile = NULL;
#endif
+#ifdef SSL_VENDOR
+ dc->ctx = ap_ctx_new(p);
+ ap_hook_use("ap::mod_ssl::vendor::config_perdir_create",
+ AP_HOOK_SIG4(void,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
+ p, dir, dc);
+#endif
+
return dc;
}
@@ -280,6 +331,13 @@ void *ssl_config_perdir_merge(pool *p, void *basev, void *addv)
cfgMergeString(szCACertificateFile);
#endif
+#ifdef SSL_VENDOR
+ cfgMergeCtx(ctx);
+ ap_hook_use("ap::mod_ssl::vendor::config_perdir_merge",
+ AP_HOOK_SIG5(void,ptr,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
+ p, base, add, new);
+#endif
+
return new;
}
@@ -314,10 +372,14 @@ const char *ssl_cmd_SSLMutex(
mc->nMutexMode = SSL_MUTEXMODE_NONE;
}
else if (strlen(arg) > 5 && strcEQn(arg, "file:", 5)) {
+#ifndef WIN32
mc->nMutexMode = SSL_MUTEXMODE_FILE;
mc->szMutexFile = ap_psprintf(mc->pPool, "%s.%lu",
- ap_server_root_relative(cmd->pool, arg+5),
+ ap_server_root_relative(cmd->pool, arg+5),
(unsigned long)getpid());
+#else
+ return "SSLMutex: Lockfiles not available on this platform";
+#endif
}
else if (strcEQ(arg, "sem")) {
#ifdef SSL_CAN_USE_SEM
@@ -394,12 +456,12 @@ const char *ssl_cmd_SSLRandomSeed(
if (!ssl_util_path_check(SSL_PCM_EXISTS, pRS->cpPath))
return ap_pstrcat(cmd->pool, "SSLRandomSeed: source path '",
pRS->cpPath, "' not exists", NULL);
- if (arg3 == NULL)
+ if (arg3 == NULL)
pRS->nBytes = 0; /* read whole file */
else {
if (pRS->nSrc == SSL_RSSRC_BUILTIN)
return "SSLRandomSeed: byte specification not "
- "allowd for builtin seed source";
+ "allowed for builtin seed source";
pRS->nBytes = atoi(arg3);
if (pRS->nBytes < 0)
return "SSLRandomSeed: invalid number of bytes specified";
@@ -433,12 +495,19 @@ const char *ssl_cmd_SSLCertificateFile(
{
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
char *cpPath;
+ int i;
cpPath = ap_server_root_relative(cmd->pool, arg);
if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
return ap_pstrcat(cmd->pool, "SSLCertificateFile: file '",
cpPath, "' not exists or empty", NULL);
- sc->szCertificateFile = cpPath;
+ for (i = 0; i < SSL_AIDX_MAX && sc->szPublicCertFile[i] != NULL; i++)
+ ;
+ if (i == SSL_AIDX_MAX)
+ return ap_psprintf(cmd->pool, "SSLCertificateFile: only up to %d "
+ "different certificates per virtual host allowed",
+ SSL_AIDX_MAX);
+ sc->szPublicCertFile[i] = cpPath;
return NULL;
}
@@ -447,12 +516,33 @@ const char *ssl_cmd_SSLCertificateKeyFile(
{
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
char *cpPath;
+ int i;
cpPath = ap_server_root_relative(cmd->pool, arg);
if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
return ap_pstrcat(cmd->pool, "SSLCertificateKeyFile: file '",
cpPath, "' not exists or empty", NULL);
- sc->szKeyFile = cpPath;
+ for (i = 0; i < SSL_AIDX_MAX && sc->szPrivateKeyFile[i] != NULL; i++)
+ ;
+ if (i == SSL_AIDX_MAX)
+ return ap_psprintf(cmd->pool, "SSLCertificateKeyFile: only up to %d "
+ "different private keys per virtual host allowed",
+ SSL_AIDX_MAX);
+ sc->szPrivateKeyFile[i] = cpPath;
+ return NULL;
+}
+
+const char *ssl_cmd_SSLCertificateChainFile(
+ cmd_parms *cmd, char *struct_ptr, char *arg)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ char *cpPath;
+
+ cpPath = ap_server_root_relative(cmd->pool, arg);
+ if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
+ return ap_pstrcat(cmd->pool, "SSLCertificateChainFile: file '",
+ cpPath, "' not exists or empty", NULL);
+ sc->szCertificateChain = cpPath;
return NULL;
}
@@ -485,7 +575,7 @@ const char *ssl_cmd_SSLCACertificateFile(
cpPath = ap_server_root_relative(cmd->pool, arg);
if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
- return ap_pstrcat(cmd->pool, "SSLCACertificateKeyFile: file '",
+ return ap_pstrcat(cmd->pool, "SSLCACertificateFile: file '",
cpPath, "' not exists or empty", NULL);
#ifdef SSL_EXPERIMENTAL
if (cmd->path == NULL || dc == NULL)
@@ -498,6 +588,34 @@ const char *ssl_cmd_SSLCACertificateFile(
return NULL;
}
+const char *ssl_cmd_SSLCARevocationPath(
+ cmd_parms *cmd, SSLDirConfigRec *dc, char *arg)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ char *cpPath;
+
+ cpPath = ap_server_root_relative(cmd->pool, arg);
+ if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISDIR, cpPath))
+ return ap_pstrcat(cmd->pool, "SSLCARecocationPath: directory '",
+ cpPath, "' not exists", NULL);
+ sc->szCARevocationPath = cpPath;
+ return NULL;
+}
+
+const char *ssl_cmd_SSLCARevocationFile(
+ cmd_parms *cmd, SSLDirConfigRec *dc, char *arg)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ char *cpPath;
+
+ cpPath = ap_server_root_relative(cmd->pool, arg);
+ if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
+ return ap_pstrcat(cmd->pool, "SSLCARevocationFile: file '",
+ cpPath, "' not exists or empty", NULL);
+ sc->szCARevocationFile = cpPath;
+ return NULL;
+}
+
const char *ssl_cmd_SSLVerifyClient(
cmd_parms *cmd, SSLDirConfigRec *dc, char *level)
{
@@ -542,6 +660,8 @@ const char *ssl_cmd_SSLSessionCache(
{
const char *err;
SSLModConfigRec *mc = myModConfig();
+ char *cp, *cp2;
+ int maxsize;
if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
return err;
@@ -556,7 +676,34 @@ const char *ssl_cmd_SSLSessionCache(
mc->szSessionCacheDataFile = ap_pstrdup(mc->pPool,
ap_server_root_relative(cmd->pool, arg+4));
}
- else
+ else if (strlen(arg) > 4 && strcEQn(arg, "shm:", 4)) {
+ if (!ap_mm_useable())
+ return "SSLSessionCache: shared memory cache not useable on this platform";
+ mc->nSessionCacheMode = SSL_SCMODE_SHM;
+ mc->szSessionCacheDataFile = ap_pstrdup(mc->pPool,
+ ap_server_root_relative(cmd->pool, arg+4));
+ mc->tSessionCacheDataTable = NULL;
+ mc->nSessionCacheDataSize = 1024*512; /* 512KB */
+ if ((cp = strchr(mc->szSessionCacheDataFile, '(')) != NULL) {
+ *cp++ = NUL;
+ if ((cp2 = strchr(cp, ')')) == NULL)
+ return "SSLSessionCache: Invalid argument: no closing parenthesis";
+ *cp2 = NUL;
+ mc->nSessionCacheDataSize = atoi(cp);
+ if (mc->nSessionCacheDataSize <= 8192)
+ return "SSLSessionCache: Invalid argument: size has to be >= 8192 bytes";
+ maxsize = ap_mm_core_maxsegsize();
+ if (mc->nSessionCacheDataSize >= maxsize)
+ return ap_psprintf(cmd->pool, "SSLSessionCache: Invalid argument: "
+ "size has to be < %d bytes on this platform", maxsize);
+ }
+ }
+ else
+#ifdef SSL_VENDOR
+ if (!ap_hook_use("ap::mod_ssl::vendor::cmd_sslsessioncache",
+ AP_HOOK_SIG4(void,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
+ cmd, arg, mc))
+#endif
return "SSLSessionCache: Invalid argument";
return NULL;
}
@@ -638,6 +785,10 @@ const char *ssl_cmd_SSLOptions(
opt = SSL_OPT_EXPORTCERTDATA;
else if (strcEQ(w, "FakeBasicAuth"))
opt = SSL_OPT_FAKEBASICAUTH;
+ else if (strcEQ(w, "StrictRequire"))
+ opt = SSL_OPT_STRICTREQUIRE;
+ else if (strcEQ(w, "OptRenegotiate"))
+ opt = SSL_OPT_OPTRENEGOTIATE;
else
return ap_pstrcat(cmd->pool, "SSLOptions: Illegal option '", w, "'", NULL);
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_dh.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_dh.c
new file mode 100644
index 00000000000..dba9040b49a
--- /dev/null
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_dh.c
@@ -0,0 +1,255 @@
+#if 0
+=pod
+#endif
+/* _ _
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
+** |_____|
+** ssl_engine_dh.c
+** Diffie-Hellman Built-in Temporary Parameters
+*/
+
+/* ====================================================================
+ * Copyright (c) 1998-1999 Ralf S. Engelschall. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by
+ * Ralf S. Engelschall <rse@engelschall.com> for use in the
+ * mod_ssl project (http://www.modssl.org/)."
+ *
+ * 4. The names "mod_ssl" must not be used to endorse or promote
+ * products derived from this software without prior written
+ * permission. For written permission, please contact
+ * rse@engelschall.com.
+ *
+ * 5. Products derived from this software may not be called "mod_ssl"
+ * nor may "mod_ssl" appear in their names without prior
+ * written permission of Ralf S. Engelschall.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by
+ * Ralf S. Engelschall <rse@engelschall.com> for use in the
+ * mod_ssl project (http://www.modssl.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
+ * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include "mod_ssl.h"
+
+/* ----BEGIN GENERATED SECTION-------- */
+
+/*
+** Diffie-Hellman-Parameters: (512 bit)
+** prime:
+** 00:d4:bc:d5:24:06:f6:9b:35:99:4b:88:de:5d:b8:
+** 96:82:c8:15:7f:62:d8:f3:36:33:ee:57:72:f1:1f:
+** 05:ab:22:d6:b5:14:5b:9f:24:1e:5a:cc:31:ff:09:
+** 0a:4b:c7:11:48:97:6f:76:79:50:94:e7:1e:79:03:
+** 52:9f:5a:82:4b
+** generator: 2 (0x2)
+** Diffie-Hellman-Parameters: (1024 bit)
+** prime:
+** 00:e6:96:9d:3d:49:5b:e3:2c:7c:f1:80:c3:bd:d4:
+** 79:8e:91:b7:81:82:51:bb:05:5e:2a:20:64:90:4a:
+** 79:a7:70:fa:15:a2:59:cb:d5:23:a6:a6:ef:09:c4:
+** 30:48:d5:a2:2f:97:1f:3c:20:12:9b:48:00:0e:6e:
+** dd:06:1c:bc:05:3e:37:1d:79:4e:53:27:df:61:1e:
+** bb:be:1b:ac:9b:5c:60:44:cf:02:3d:76:e0:5e:ea:
+** 9b:ad:99:1b:13:a6:3c:97:4e:9e:f1:83:9e:b5:db:
+** 12:51:36:f7:26:2e:56:a8:87:15:38:df:d8:23:c6:
+** 50:50:85:e2:1f:0d:d5:c8:6b
+** generator: 2 (0x2)
+*/
+
+static unsigned char dh512_p[] =
+{
+ 0xD4, 0xBC, 0xD5, 0x24, 0x06, 0xF6, 0x9B, 0x35, 0x99, 0x4B, 0x88, 0xDE,
+ 0x5D, 0xB8, 0x96, 0x82, 0xC8, 0x15, 0x7F, 0x62, 0xD8, 0xF3, 0x36, 0x33,
+ 0xEE, 0x57, 0x72, 0xF1, 0x1F, 0x05, 0xAB, 0x22, 0xD6, 0xB5, 0x14, 0x5B,
+ 0x9F, 0x24, 0x1E, 0x5A, 0xCC, 0x31, 0xFF, 0x09, 0x0A, 0x4B, 0xC7, 0x11,
+ 0x48, 0x97, 0x6F, 0x76, 0x79, 0x50, 0x94, 0xE7, 0x1E, 0x79, 0x03, 0x52,
+ 0x9F, 0x5A, 0x82, 0x4B,
+};
+static unsigned char dh512_g[] =
+{
+ 0x02,
+};
+
+static DH *get_dh512()
+{
+ DH *dh;
+
+ if ((dh = DH_new()) == NULL)
+ return (NULL);
+ dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL);
+ dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL);
+ if ((dh->p == NULL) || (dh->g == NULL))
+ return (NULL);
+ return (dh);
+}
+static unsigned char dh1024_p[] =
+{
+ 0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3,
+ 0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E,
+ 0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59,
+ 0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2,
+ 0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD,
+ 0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF,
+ 0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02,
+ 0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C,
+ 0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7,
+ 0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50,
+ 0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B,
+};
+static unsigned char dh1024_g[] =
+{
+ 0x02,
+};
+
+static DH *get_dh1024()
+{
+ DH *dh;
+
+ if ((dh = DH_new()) == NULL)
+ return (NULL);
+ dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
+ dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
+ if ((dh->p == NULL) || (dh->g == NULL))
+ return (NULL);
+ return (dh);
+}
+/* ----END GENERATED SECTION---------- */
+
+DH *ssl_dh_GetTmpParam(int nKeyLen)
+{
+ DH *dh;
+
+ if (nKeyLen == 512)
+ dh = get_dh512();
+ else if (nKeyLen == 1024)
+ dh = get_dh1024();
+ else
+ dh = get_dh1024();
+ return dh;
+}
+
+DH *ssl_dh_GetParamFromFile(char *file)
+{
+ DH *dh = NULL;
+ BIO *bio;
+
+ if ((bio = BIO_new_file(file, "r")) == NULL)
+ return NULL;
+#if SSL_LIBRARY_VERSION < 0x00904000
+ dh = PEM_read_bio_DHparams(bio, NULL, NULL);
+#else
+ dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
+#endif
+ BIO_free(bio);
+ return (dh);
+}
+
+/*
+=cut
+##
+## Embedded Perl script for generating the temporary DH parameters
+##
+
+require 5.003;
+use strict;
+
+# configuration
+my $file = $0;
+my $begin = '----BEGIN GENERATED SECTION--------';
+my $end = '----END GENERATED SECTION----------';
+
+# read ourself and keep a backup
+open(FP, "<$file") || die;
+my $source = '';
+$source .= $_ while (<FP>);
+close(FP);
+open(FP, ">$file.bak") || die;
+print FP $source;
+close(FP);
+
+# generate the DH parameters
+print "1. Generate 512 and 1024 bit Diffie-Hellman parameters (p, g)\n";
+my $rand = '';
+foreach $file (qw(/var/log/messages /var/adm/messages
+ /kernel /vmunix /vmlinuz /etc/hosts /etc/resolv.conf)) {
+ if (-f $file) {
+ $rand = $file if ($rand eq '');
+ $rand .= ":$file" if ($rand ne '');
+ }
+}
+$rand = "-rand $rand" if ($rand ne '');
+system("openssl gendh $rand -out dh512.pem 512");
+system("openssl gendh $rand -out dh1024.pem 1024");
+
+# generate DH param info
+my $dhinfo = '';
+open(FP, "openssl dh -noout -text -in dh512.pem |") || die;
+$dhinfo .= $_ while (<FP>);
+close(FP);
+open(FP, "openssl dh -noout -text -in dh1024.pem |") || die;
+$dhinfo .= $_ while (<FP>);
+close(FP);
+$dhinfo =~ s|^|** |mg;
+$dhinfo = "\n\/\*\n$dhinfo\*\/\n\n";
+
+# generate C source from DH params
+my $dhsource = '';
+open(FP, "openssl dh -noout -C -in dh512.pem | indent | expand -8 |") || die;
+$dhsource .= $_ while (<FP>);
+close(FP);
+open(FP, "openssl dh -noout -C -in dh1024.pem | indent | expand -8 |") || die;
+$dhsource .= $_ while (<FP>);
+close(FP);
+$dhsource =~ s|(DH\s+\*get_dh)|static $1|sg;
+
+# generate output
+my $o = $dhinfo . $dhsource;
+
+# insert the generated code at the target location
+$source =~ s|(\/\* $begin.+?\n).*\n(.*?\/\* $end)|$1$o$2|s;
+
+# and update the source on disk
+print "Updating file `$file'\n";
+open(FP, ">$file") || die;
+print FP $source;
+close(FP);
+
+# cleanup
+unlink("dh512.pem");
+unlink("dh1024.pem");
+
+=pod
+*/
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_ds.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_ds.c
index 04d8c0bd38c..b83b5b93052 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_ds.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_ds.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_engine_ds.c
** Additional Data Structures
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_ext.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_ext.c
index dab6fd269f6..14e1efd9089 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_ext.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_ext.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_engine_ext.c
** Extensions to other Apache parts
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -76,12 +76,15 @@ static void ssl_ext_mr_register(void);
static void ssl_ext_mr_unregister(void);
static void ssl_ext_mp_register(void);
static void ssl_ext_mp_unregister(void);
+static void ssl_ext_ms_register(void);
+static void ssl_ext_ms_unregister(void);
void ssl_ext_register(void)
{
ssl_ext_mlc_register();
ssl_ext_mr_register();
ssl_ext_mp_register();
+ ssl_ext_ms_register();
return;
}
@@ -90,6 +93,7 @@ void ssl_ext_unregister(void)
ssl_ext_mlc_unregister();
ssl_ext_mr_unregister();
ssl_ext_mp_unregister();
+ ssl_ext_ms_unregister();
return;
}
@@ -119,7 +123,7 @@ static void ssl_ext_mlc_unregister(void)
{
ap_hook_unregister("ap::mod_log_config::log_c",
ssl_ext_mlc_log_c);
- ap_hook_unregister("ap::mod_log_config::log_x",
+ ap_hook_unregister("ap::mod_log_config::log_x",
ssl_ext_mlc_log_x);
return;
}
@@ -135,17 +139,17 @@ static char *ssl_ext_mlc_log_c(request_rec *r, char *a)
if (ap_ctx_get(r->connection->client->ctx, "ssl") == NULL)
return NULL;
result = NULL;
- if (strcmp(a, "version") == 0)
+ if (strEQ(a, "version"))
result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_PROTOCOL");
- else if (strcmp(a, "cipher") == 0)
+ else if (strEQ(a, "cipher"))
result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER");
- else if (strcmp(a, "subjectdn") == 0 || strcmp(a, "clientcert") == 0)
+ else if (strEQ(a, "subjectdn") || strEQ(a, "clientcert"))
result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CLIENT_S_DN");
- else if (strcmp(a, "issuerdn") == 0 || strcmp(a, "cacert") == 0)
+ else if (strEQ(a, "issuerdn") || strEQ(a, "cacert"))
result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CLIENT_I_DN");
- else if (strcmp(a, "errcode") == 0)
+ else if (strEQ(a, "errcode"))
result = "-";
- else if (strcmp(a, "errstr") == 0)
+ else if (strEQ(a, "errstr"))
result = ap_ctx_get(r->connection->client->ctx, "ssl::verify::error");
if (result != NULL && result[0] == NUL)
result = NULL;
@@ -188,7 +192,7 @@ static void ssl_ext_mr_register(void)
static void ssl_ext_mr_unregister(void)
{
- ap_hook_unregister("ap::mod_rewrite::lookup_variable",
+ ap_hook_unregister("ap::mod_rewrite::lookup_variable",
ssl_ext_mr_lookup_variable);
return;
}
@@ -251,7 +255,7 @@ static int ssl_ext_mp_canon(request_rec *r, char *url)
{
int rc;
- if (strncasecmp(url, "https:", 6) == 0) {
+ if (strcEQn(url, "https:", 6)) {
rc = OK;
ap_hook_call("ap::mod_proxy::http::canon",
&rc, r, url+6, "https", DEFAULT_HTTPS_PORT);
@@ -265,18 +269,21 @@ static int ssl_ext_mp_handler(
{
int rc;
- if (strcasecmp(protocol, "https") == 0) {
- ap_ctx_set(r->ctx, "ssl_enabled", (void *)1);
+ if (strcEQ(protocol, "https")) {
+ ap_ctx_set(r->ctx, "ssl::proxy::enabled", PTRUE);
ap_hook_call("ap::mod_proxy::http::handler",
&rc, r, cr, url, proxyhost, proxyport);
return rc;
}
+ else {
+ ap_ctx_set(r->ctx, "ssl::proxy::enabled", PFALSE);
+ }
return DECLINED;
}
static int ssl_ext_mp_set_destport(request_rec *r)
{
- if (ap_ctx_get(r->ctx, "ssl_enabled") == (void *)1)
+ if (ap_ctx_get(r->ctx, "ssl::proxy::enabled") == PTRUE)
return DEFAULT_HTTPS_PORT;
else
return DEFAULT_HTTP_PORT;
@@ -288,18 +295,30 @@ static char *ssl_ext_mp_new_connection(request_rec *r, BUFF *fb)
SSL *ssl;
char *errmsg;
int rc;
+ char *cpVHostID;
- if (ap_ctx_get(r->ctx, "ssl_enabled") != (void *)1)
+ if (ap_ctx_get(r->ctx, "ssl::proxy::enabled") == PFALSE)
return NULL;
+ cpVHostID = ssl_util_vhostid(r->pool, r->server);
/*
* Create a SSL context and handle
*/
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
- ssl = SSL_new(ssl_ctx);
+ if ((ssl = SSL_new(ssl_ctx)) == NULL) {
+ errmsg = ap_pstrcat(r->pool, "SSL new failed (%s): ", cpVHostID,
+ ERR_reason_error_string(ERR_get_error()), NULL);
+ ap_ctx_set(fb->ctx, "ssl", NULL);
+ return errmsg;
+ }
SSL_clear(ssl);
+ SSL_set_session_id_context(ssl, (unsigned char *)cpVHostID, strlen(cpVHostID));
SSL_set_fd(ssl, fb->fd);
ap_ctx_set(fb->ctx, "ssl", ssl);
+
+ /*
+ * Give us a chance to gracefully close the connection
+ */
ap_register_cleanup(r->pool, (void *)fb,
ssl_ext_mp_close_connection, ssl_ext_mp_close_connection);
@@ -307,9 +326,10 @@ static char *ssl_ext_mp_new_connection(request_rec *r, BUFF *fb)
* Establish the SSL connection
*/
if ((rc = SSL_connect(ssl)) <= 0) {
- errmsg = ap_pstrcat(r->pool, "SSL connect failed: ",
+ errmsg = ap_pstrcat(r->pool, "SSL connect failed (%s): ", cpVHostID,
ERR_reason_error_string(ERR_get_error()), NULL);
SSL_free(ssl);
+ ap_ctx_set(fb->ctx, "ssl", NULL);
return errmsg;
}
@@ -324,7 +344,7 @@ static void ssl_ext_mp_close_connection(void *_fb)
ssl = ap_ctx_get(fb->ctx, "ssl");
if (ssl != NULL) {
SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
- while (!SSL_shutdown(ssl));
+ SSL_smart_shutdown(ssl);
SSL_free(ssl);
ap_ctx_set(fb->ctx, "ssl", NULL);
}
@@ -334,7 +354,7 @@ static void ssl_ext_mp_close_connection(void *_fb)
static int ssl_ext_mp_write_host_header(
request_rec *r, BUFF *fb, char *host, int port, char *portstr)
{
- if (ap_ctx_get(r->ctx, "ssl_enabled") != (void *)1)
+ if (ap_ctx_get(r->ctx, "ssl::proxy::enabled") == PFALSE)
return DECLINED;
if (portstr != NULL && port != DEFAULT_HTTPS_PORT) {
@@ -344,3 +364,50 @@ static int ssl_ext_mp_write_host_header(
return DECLINED;
}
+
+/* _________________________________________________________________
+**
+** SSL Extension to mod_status
+** _________________________________________________________________
+*/
+
+static void ssl_ext_ms_display(request_rec *, int, int);
+
+static void ssl_ext_ms_register(void)
+{
+ ap_hook_register("ap::mod_status::display", ssl_ext_ms_display, AP_HOOK_NOCTX);
+ return;
+}
+
+static void ssl_ext_ms_unregister(void)
+{
+ ap_hook_unregister("ap::mod_status::display", ssl_ext_ms_display);
+ return;
+}
+
+static void ssl_ext_ms_display_cb(char *str, void *_r)
+{
+ request_rec *r = (request_rec *)_r;
+ if (str != NULL)
+ ap_rputs(str, r);
+ return;
+}
+
+static void ssl_ext_ms_display(request_rec *r, int no_table_report, int short_report)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(r->server);
+
+ if (sc == NULL)
+ return;
+ ap_rputs("<hr>\n", r);
+ ap_rputs("<table cellspacing=0 cellpadding=0>\n", r);
+ ap_rputs("<tr><td bgcolor=\"#000000\">\n", r);
+ ap_rputs("<b><font color=\"#ffffff\" face=\"Arial,Helvetica\">SSL/TLS Session Cache Status:</font></b>\r", r);
+ ap_rputs("</td></tr>\n", r);
+ ap_rputs("<tr><td bgcolor=\"#ffffff\">\n", r);
+ ssl_scache_status(r->server, r->pool, ssl_ext_ms_display_cb, r);
+ ap_rputs("</td></tr>\n", r);
+ ap_rputs("</table>\n", r);
+ return;
+}
+
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_init.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_init.c
index 1cb917793de..37c0e9ea33b 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_init.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_init.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_engine_init.c
** Initialization of Servers
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -128,6 +128,11 @@ void ssl_init_Module(server_rec *s, pool *p)
mc->nInitCount++;
/*
+ * Let us cleanup on restarts and exists
+ */
+ ap_register_cleanup(p, s, ssl_init_ModuleKill, ssl_init_ChildKill);
+
+ /*
* Any init round fixes the global config
*/
ssl_config_global_create(); /* just to avoid problems */
@@ -153,9 +158,21 @@ void ssl_init_Module(server_rec *s, pool *p)
sc->nPassPhraseDialogType = SSL_PPTYPE_BUILTIN;
/* Open the dedicated SSL logfile */
- ssl_log_open(s2, p);
+ ssl_log_open(s, s2, p);
}
+ /*
+ * Identification
+ */
+ if (mc->nInitCount == 1)
+ ssl_log(s, SSL_LOG_INFO, "Server: %s, Interface: %s, Library: %s",
+ SERVER_BASEVERSION,
+ ssl_var_lookup(p, NULL, NULL, NULL, "SSL_VERSION_INTERFACE"),
+ ssl_var_lookup(p, NULL, NULL, NULL, "SSL_VERSION_LIBRARY"));
+
+ /*
+ * Initialization round information
+ */
if (mc->nInitCount == 1)
ssl_log(s, SSL_LOG_INFO, "Init: 1st startup round (still not detached)");
else if (mc->nInitCount == 2)
@@ -164,6 +181,11 @@ void ssl_init_Module(server_rec *s, pool *p)
ssl_log(s, SSL_LOG_INFO, "Init: %d%s restart round (already detached)",
mc->nInitCount-2, (mc->nInitCount-2) == 1 ? "st" : "nd");
+#ifdef SSL_VENDOR
+ ap_hook_use("ap::mod_ssl::vendor::init_module",
+ AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, s, p);
+#endif
+
/*
* The initialization phase inside the Apache API is totally bogus.
* We actually have three non-trivial problems:
@@ -200,10 +222,15 @@ void ssl_init_Module(server_rec *s, pool *p)
*/
#ifdef SHARED_MODULE
- ssl_init_SSLLibrary(s);
+ ssl_log(s, SSL_LOG_INFO, "Init: %snitializing %s library",
+ mc->nInitCount == 1 ? "I" : "Rei", SSL_LIBRARY_NAME);
+ ssl_init_SSLLibrary();
#else
- if (mc->nInitCount <= 2)
- ssl_init_SSLLibrary(s);
+ if (mc->nInitCount <= 2) {
+ ssl_log(s, SSL_LOG_INFO, "Init: %snitializing %s library",
+ mc->nInitCount == 1 ? "I" : "Rei", SSL_LIBRARY_NAME);
+ ssl_init_SSLLibrary();
+ }
#endif
if (mc->nInitCount == 1) {
ssl_pphrase_Handle(s, p);
@@ -235,23 +262,49 @@ void ssl_init_Module(server_rec *s, pool *p)
ssl_log(s, SSL_LOG_INFO, "Init: Seeding PRNG with %d bytes of entropy", n);
/*
- * pre-generate the temporary RSA key
+ * pre-generate the temporary RSA keys
*/
- if (mc->pRSATmpKey == NULL) {
- ssl_log(s, SSL_LOG_INFO, "Init: Generating temporary (512 bit) RSA private key");
- mc->pRSATmpKey = RSA_generate_key(512, RSA_F4, NULL, NULL);
- if (mc->pRSATmpKey == NULL) {
+ if (mc->pRSATmpKey512 == NULL) {
+ ssl_log(s, SSL_LOG_INFO, "Init: Generating temporary RSA private keys (512/1024 bits)");
+ mc->pRSATmpKey512 = RSA_generate_key(512, RSA_F4, NULL, NULL);
+ if (mc->pRSATmpKey512 == NULL) {
#ifdef __OpenBSD__
- ssl_log(s, SSL_LOG_ERROR, "Init: Failed to generate temporary (512 bit) RSA private key (SSL won't work without an RSA capable shared library)");
- ssl_log(s, SSL_LOG_ERROR, "Init: pkg_add ftp://ftp.openbsd.org/pub/OpenBSD/<version>/packages/<arch>/libssl-1.1.tgz if you are able to use RSA");
- /* harmless in http only case. We'll get a fatal error below
- * if this didn't work and we try to init https servers
- */
- return;
+ ssl_log(s, SSL_LOG_ERROR, "Init: Failed to generate temporary (512 b
+it) RSA private key (SSL won't work without an RSA capable shared library)");
+ ssl_log(s, SSL_LOG_ERROR, "Init: pkg_add ftp://ftp.openbsd.org/pub/O
+penBSD/<version>/packages/<arch>/libssl-2.1.tgz if you are able to use RSA");
+ /* harmless in http only case. We'll get a fatal error below
+ * if this didn't work and we try to init https servers
+ */
+ return;
#else
- ssl_log(s, SSL_LOG_ERROR, "Init: Failed to generate temporary (512 bit) RSA private key");
+ ssl_log(s, SSL_LOG_ERROR, "Init: Failed to generate temporary (512 b
+it) RSA private key");
ssl_die();
#endif
+
+ }
+ mc->pRSATmpKey1024 = RSA_generate_key(1024, RSA_F4, NULL, NULL);
+ if (mc->pRSATmpKey1024 == NULL) {
+ ssl_log(s, SSL_LOG_ERROR, "Init: Failed to generate temporary 1024 bit RSA private key");
+ ssl_die();
+ }
+ }
+
+ /*
+ * pre-configure the temporary DH parameters
+ */
+ if (mc->pDHTmpParam512 == NULL) {
+ ssl_log(s, SSL_LOG_INFO, "Init: Configuring temporary DH parameters (512/1024 bits)");
+ mc->pDHTmpParam512 = ssl_dh_GetTmpParam(512);
+ if (mc->pDHTmpParam512 == NULL) {
+ ssl_log(s, SSL_LOG_ERROR, "Init: Failed to configure temporary 512 bit DH parameters");
+ ssl_die();
+ }
+ mc->pDHTmpParam1024 = ssl_dh_GetTmpParam(1024);
+ if (mc->pDHTmpParam1024 == NULL) {
+ ssl_log(s, SSL_LOG_ERROR, "Init: Failed to configure temporary 1024 bit DH parameters");
+ ssl_die();
}
}
@@ -259,40 +312,31 @@ void ssl_init_Module(server_rec *s, pool *p)
* initialize servers
*/
ssl_log(s, SSL_LOG_INFO, "Init: Initializing (virtual) servers for SSL");
- for (; s != NULL; s = s->next) {
- sc = mySrvConfig(s);
-
- /*
- * Give out warnings when HTTPS is configured for
- * the HTTP port or vice versa
- */
- if (sc->bEnabled && s->port == DEFAULT_HTTP_PORT)
- ssl_log(s, SSL_LOG_WARN,
- "Init: You configured HTTPS(%d) on the standard HTTP(%d) port!",
- DEFAULT_HTTPS_PORT, DEFAULT_HTTP_PORT);
- if (!sc->bEnabled && s->port == DEFAULT_HTTPS_PORT)
- ssl_log(s, SSL_LOG_WARN,
- "Init: You configured HTTP(%d) on the standard HTTPS(%d) port!",
- DEFAULT_HTTP_PORT, DEFAULT_HTTPS_PORT);
-
- /*
+ for (s2 = s; s2 != NULL; s2 = s2->next) {
+ sc = mySrvConfig(s2);
+ /*
* Either now skip this server when SSL is disabled for
* it or give out some information about what we're
* configuring.
*/
if (!sc->bEnabled)
continue;
- ssl_log(s, SSL_LOG_INFO,
+ ssl_log(s2, SSL_LOG_INFO,
"Init: Configuring server %s for SSL protocol",
- ssl_util_vhostid(p, s));
+ ssl_util_vhostid(p, s2));
/*
* Read the server certificate and key
*/
- ssl_init_GetCertAndKey(s, p, sc);
+ ssl_init_ConfigureServer(s2, p, sc);
}
/*
+ * Configuration consistency checks
+ */
+ ssl_init_CheckServers(s, p);
+
+ /*
* Announce mod_ssl and SSL library in HTTP Server field
* as ``mod_ssl/X.X.X OpenSSL/X.X.X''
*/
@@ -307,30 +351,36 @@ void ssl_init_Module(server_rec *s, pool *p)
/*
* Initialize SSL library (also already needed for the pass phrase dialog)
*/
-void ssl_init_SSLLibrary(server_rec *s)
+void ssl_init_SSLLibrary(void)
{
- ssl_log(s, SSL_LOG_INFO, "Init: Initializing %s library", SSL_LIBRARY_NAME);
#ifdef WIN32
CRYPTO_malloc_init();
#endif
SSL_load_error_strings();
- SSLeay_add_ssl_algorithms();
+ SSL_library_init();
ssl_util_thread_setup();
+ X509V3_add_standard_extensions();
return;
}
/*
- * Read the SSL Server Certificate and Key
+ * Configure a particular server
*/
-void ssl_init_GetCertAndKey(server_rec *s, pool *p, SSLSrvConfigRec *sc)
+void ssl_init_ConfigureServer(server_rec *s, pool *p, SSLSrvConfigRec *sc)
{
SSLModConfigRec *mc = myModConfig();
int nVerify;
char *cpVHostID;
+ EVP_PKEY *pKey;
SSL_CTX *ctx;
- STACK *skCAList;
+ STACK_OF(X509_NAME) *skCAList;
ssl_asn1_t *asn1;
+ unsigned char *ucp;
char *cp;
+ BOOL ok;
+ BOOL bSkipFirst;
+ int isca, pathlen;
+ int i, n;
/*
* Create the server host:port string because we need it a lot
@@ -341,7 +391,7 @@ void ssl_init_GetCertAndKey(server_rec *s, pool *p, SSLSrvConfigRec *sc)
* Now check for important parameters and the
* possibility that the user forgot to set them.
*/
- if (sc->szCertificateFile == NULL) {
+ if (sc->szPublicCertFile[0] == NULL) {
ssl_log(s, SSL_LOG_ERROR,
"Init: (%s) No SSL Certificate set [hint: SSLCertificateFile]",
cpVHostID);
@@ -351,7 +401,8 @@ void ssl_init_GetCertAndKey(server_rec *s, pool *p, SSLSrvConfigRec *sc)
/*
* Check for problematic re-initializations
*/
- if (sc->px509Certificate) {
+ if (sc->pPublicCert[SSL_AIDX_RSA] != NULL ||
+ sc->pPublicCert[SSL_AIDX_DSA] != NULL ) {
ssl_log(s, SSL_LOG_ERROR,
"Init: (%s) Illegal attempt to re-initialise SSL for server "
"(theoretically shouldn't happen!)", cpVHostID);
@@ -367,26 +418,36 @@ void ssl_init_GetCertAndKey(server_rec *s, pool *p, SSLSrvConfigRec *sc)
cpVHostID);
ssl_die();
}
- cp = ap_pstrcat(p, (sc->nProtocol & SSL_PROTOCOL_SSLV2 ? "SSLv2, " : ""),
- (sc->nProtocol & SSL_PROTOCOL_SSLV3 ? "SSLv3, " : ""),
+ cp = ap_pstrcat(p, (sc->nProtocol & SSL_PROTOCOL_SSLV2 ? "SSLv2, " : ""),
+ (sc->nProtocol & SSL_PROTOCOL_SSLV3 ? "SSLv3, " : ""),
(sc->nProtocol & SSL_PROTOCOL_TLSV1 ? "TLSv1, " : ""), NULL);
cp[strlen(cp)-2] = NUL;
- ssl_log(s, SSL_LOG_TRACE,
+ ssl_log(s, SSL_LOG_TRACE,
"Init: (%s) Creating new SSL context (protocols: %s)", cpVHostID, cp);
if (sc->nProtocol == SSL_PROTOCOL_SSLV2)
- ctx = SSL_CTX_new(SSLv2_server_method()); /* only SSLv2 is left */
+ ctx = SSL_CTX_new(SSLv2_server_method()); /* only SSLv2 is left */
else
ctx = SSL_CTX_new(SSLv23_server_method()); /* be more flexible */
+ SSL_CTX_set_options(ctx, SSL_OP_ALL);
if (!(sc->nProtocol & SSL_PROTOCOL_SSLV2))
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
if (!(sc->nProtocol & SSL_PROTOCOL_SSLV3))
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
- if (!(sc->nProtocol & SSL_PROTOCOL_TLSV1))
+ if (!(sc->nProtocol & SSL_PROTOCOL_TLSV1))
SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);
SSL_CTX_set_app_data(ctx, s);
sc->pSSLCtx = ctx;
/*
+ * Configure additional context ingredients
+ */
+ SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
+ if (mc->nSessionCacheMode == SSL_SCMODE_UNSET)
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
+ else
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
+
+ /*
* Configure callbacks for SSL context
*/
nVerify = SSL_VERIFY_NONE;
@@ -400,15 +461,17 @@ void ssl_init_GetCertAndKey(server_rec *s, pool *p, SSLSrvConfigRec *sc)
SSL_CTX_sess_set_get_cb(ctx, ssl_callback_GetSessionCacheEntry);
SSL_CTX_sess_set_remove_cb(ctx, ssl_callback_DelSessionCacheEntry);
SSL_CTX_set_tmp_rsa_callback(ctx, ssl_callback_TmpRSA);
+ SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH);
SSL_CTX_set_info_callback(ctx, ssl_callback_LogTracingState);
/*
* Configure SSL Cipher Suite
*/
- ssl_log(s, SSL_LOG_TRACE,
- "Init: (%s) Configuring permitted SSL ciphers", cpVHostID);
if (sc->szCipherSuite != NULL) {
- if (!SSL_CTX_set_cipher_list(sc->pSSLCtx, sc->szCipherSuite)) {
+ ssl_log(s, SSL_LOG_TRACE,
+ "Init: (%s) Configuring permitted SSL ciphers [%s]",
+ cpVHostID, sc->szCipherSuite);
+ if (!SSL_CTX_set_cipher_list(ctx, sc->szCipherSuite)) {
ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
"Init: (%s) Unable to configure permitted SSL ciphers",
cpVHostID);
@@ -422,8 +485,8 @@ void ssl_init_GetCertAndKey(server_rec *s, pool *p, SSLSrvConfigRec *sc)
if (sc->szCACertificateFile != NULL || sc->szCACertificatePath != NULL) {
ssl_log(s, SSL_LOG_TRACE,
"Init: (%s) Configuring client authentication", cpVHostID);
- if (!SSL_CTX_load_verify_locations(sc->pSSLCtx,
- sc->szCACertificateFile,
+ if (!SSL_CTX_load_verify_locations(ctx,
+ sc->szCACertificateFile,
sc->szCACertificatePath)) {
ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
"Init: (%s) Unable to configure verify locations "
@@ -441,41 +504,258 @@ void ssl_init_GetCertAndKey(server_rec *s, pool *p, SSLSrvConfigRec *sc)
}
/*
+ * Configure Certificate Revocation List (CRL) Details
+ */
+ if (sc->szCARevocationFile != NULL || sc->szCARevocationPath != NULL) {
+ ssl_log(s, SSL_LOG_TRACE,
+ "Init: (%s) Configuring certificate revocation facility", cpVHostID);
+ if ((sc->pRevocationStore =
+ SSL_X509_STORE_create(sc->szCARevocationFile,
+ sc->szCARevocationPath)) == NULL) {
+ ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
+ "Init: (%s) Unable to configure X.509 CRL storage "
+ "for certificate revocation", cpVHostID);
+ ssl_die();
+ }
+ }
+
+ /*
* Give a warning when no CAs were configured but client authentication
* should take place. This cannot work.
*/
if (sc->nVerifyClient == SSL_CVERIFY_REQUIRE) {
- skCAList = SSL_CTX_get_client_CA_list(sc->pSSLCtx);
- if (sk_num(skCAList) == 0)
- ssl_log(s, SSL_LOG_WARN,
+ skCAList = SSL_CTX_get_client_CA_list(ctx);
+ if (sk_X509_NAME_num(skCAList) == 0)
+ ssl_log(s, SSL_LOG_WARN,
"Init: Ops, you want to request client authentication, "
"but no CAs are known for verification!? "
"[Hint: SSLCACertificate*]");
}
/*
- * Configure server certificate
+ * Configure server certificate(s)
*/
- ssl_log(s, SSL_LOG_TRACE,
- "Init: (%s) Configuring server certificate", cpVHostID);
- if ((asn1 = (ssl_asn1_t *)ssl_ds_table_get(mc->tPublicCert, cpVHostID)) == NULL) {
+ ok = FALSE;
+ cp = ap_psprintf(p, "%s:RSA", cpVHostID);
+ if ((asn1 = (ssl_asn1_t *)ssl_ds_table_get(mc->tPublicCert, cp)) != NULL) {
+ ssl_log(s, SSL_LOG_TRACE,
+ "Init: (%s) Configuring RSA server certificate", cpVHostID);
+ ucp = asn1->cpData;
+ sc->pPublicCert[SSL_AIDX_RSA] = d2i_X509(NULL, &ucp, asn1->nData);
+ if (SSL_CTX_use_certificate(ctx, sc->pPublicCert[SSL_AIDX_RSA]) <= 0) {
+ ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
+ "Init: (%s) Unable to configure RSA server certificate",
+ cpVHostID);
+ ssl_die();
+ }
+ ok = TRUE;
+ }
+ cp = ap_psprintf(p, "%s:DSA", cpVHostID);
+ if ((asn1 = (ssl_asn1_t *)ssl_ds_table_get(mc->tPublicCert, cp)) != NULL) {
+ ssl_log(s, SSL_LOG_TRACE,
+ "Init: (%s) Configuring DSA server certificate", cpVHostID);
+ ucp = asn1->cpData;
+ sc->pPublicCert[SSL_AIDX_DSA] = d2i_X509(NULL, &ucp, asn1->nData);
+ if (SSL_CTX_use_certificate(ctx, sc->pPublicCert[SSL_AIDX_DSA]) <= 0) {
+ ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
+ "Init: (%s) Unable to configure DSA server certificate",
+ cpVHostID);
+ ssl_die();
+ }
+ ok = TRUE;
+ }
+ if (!ok) {
ssl_log(s, SSL_LOG_ERROR,
- "Init: (%s) Ops, can't find server certificate?!", cpVHostID);
+ "Init: (%s) Ops, no RSA or DSA server certificate found?!", cpVHostID);
+ ssl_log(s, SSL_LOG_ERROR,
+ "Init: (%s) You have to perform a *full* server restart when you added or removed a certificate and/or key file", cpVHostID);
ssl_die();
}
- sc->px509Certificate = d2i_X509(NULL, &(asn1->cpData), asn1->nData);
/*
- * Configure server private key
+ * Some information about the certificate(s)
*/
- ssl_log(s, SSL_LOG_TRACE,
- "Init: (%s) Configuring server private key", cpVHostID);
- if ((asn1 = (ssl_asn1_t *)ssl_ds_table_get(mc->tPrivateKey, cpVHostID)) == NULL) {
+ for (i = 0; i < SSL_AIDX_MAX; i++) {
+ if (sc->pPublicCert[i] != NULL) {
+ if (SSL_X509_isSGC(sc->pPublicCert[i])) {
+ ssl_log(s, SSL_LOG_INFO,
+ "Init: (%s) %s server certificate enables "
+ "Server Gated Cryptography (SGC)",
+ cpVHostID, (i == SSL_AIDX_RSA ? "RSA" : "DSA"));
+ }
+ if (SSL_X509_getBC(sc->pPublicCert[i], &isca, &pathlen)) {
+ if (isca)
+ ssl_log(s, SSL_LOG_WARN,
+ "Init: (%s) %s server certificate is a CA certificate "
+ "(BasicConstraints: CA == TRUE !?)",
+ cpVHostID, (i == SSL_AIDX_RSA ? "RSA" : "DSA"));
+ if (pathlen > 0)
+ ssl_log(s, SSL_LOG_WARN,
+ "Init: (%s) %s server certificate is not a leaf certificate "
+ "(BasicConstraints: pathlen == %d > 0 !?)",
+ cpVHostID, (i == SSL_AIDX_RSA ? "RSA" : "DSA"), pathlen);
+ }
+ if (SSL_X509_getCN(p, sc->pPublicCert[i], &cp)) {
+ if (strNE(s->server_hostname, cp)) {
+ ssl_log(s, SSL_LOG_WARN,
+ "Init: (%s) %s server certificate CommonName (CN) `%s' "
+ "does NOT match server name!?", cpVHostID,
+ (i == SSL_AIDX_RSA ? "RSA" : "DSA"), cp);
+ }
+ }
+ }
+ }
+
+ /*
+ * Configure server private key(s)
+ */
+ ok = FALSE;
+ cp = ap_psprintf(p, "%s:RSA", cpVHostID);
+ if ((asn1 = (ssl_asn1_t *)ssl_ds_table_get(mc->tPrivateKey, cp)) != NULL) {
+ ssl_log(s, SSL_LOG_TRACE,
+ "Init: (%s) Configuring RSA server private key", cpVHostID);
+ ucp = asn1->cpData;
+ sc->pPrivateKey[SSL_AIDX_RSA] =
+ d2i_PrivateKey(EVP_PKEY_RSA, NULL, &ucp, asn1->nData);
+ if (SSL_CTX_use_PrivateKey(ctx, sc->pPrivateKey[SSL_AIDX_RSA]) <= 0) {
+ ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
+ "Init: (%s) Unable to configure server RSA private key",
+ cpVHostID);
+ ssl_die();
+ }
+ ok = TRUE;
+ }
+ cp = ap_psprintf(p, "%s:DSA", cpVHostID);
+ if ((asn1 = (ssl_asn1_t *)ssl_ds_table_get(mc->tPrivateKey, cp)) != NULL) {
+ ssl_log(s, SSL_LOG_TRACE,
+ "Init: (%s) Configuring DSA server private key", cpVHostID);
+ ucp = asn1->cpData;
+ sc->pPrivateKey[SSL_AIDX_DSA] =
+ d2i_PrivateKey(EVP_PKEY_DSA, NULL, &ucp, asn1->nData);
+ if (SSL_CTX_use_PrivateKey(ctx, sc->pPrivateKey[SSL_AIDX_DSA]) <= 0) {
+ ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
+ "Init: (%s) Unable to configure server DSA private key",
+ cpVHostID);
+ ssl_die();
+ }
+ ok = TRUE;
+ }
+ if (!ok) {
ssl_log(s, SSL_LOG_ERROR,
- "Init: (%s) Ops, can't find server private key?!", cpVHostID);
+ "Init: (%s) Ops, no RSA or DSA server private key found?!", cpVHostID);
ssl_die();
}
- sc->prsaKey = d2i_RSAPrivateKey(NULL, &(asn1->cpData), asn1->nData);
+
+ /*
+ * Optionally copy DSA parameters for certificate from private key
+ * (see http://www.psy.uq.edu.au/~ftp/Crypto/ssleay/TODO.html)
+ */
+ if ( sc->pPublicCert[SSL_AIDX_DSA] != NULL
+ && sc->pPrivateKey[SSL_AIDX_DSA] != NULL) {
+ pKey = X509_get_pubkey(sc->pPublicCert[SSL_AIDX_DSA]);
+ if ( pKey != NULL
+ && EVP_PKEY_type(pKey->type) == EVP_PKEY_DSA
+ && EVP_PKEY_missing_parameters(pKey))
+ EVP_PKEY_copy_parameters(pKey, sc->pPrivateKey[SSL_AIDX_DSA]);
+ }
+
+ /*
+ * Optionally configure extra server certificate chain certificates.
+ * This is usually done by OpenSSL automatically when one of the
+ * server cert issuers are found under SSLCACertificatePath or in
+ * SSLCACertificateFile. But because these are intended for client
+ * authentication it can conflict. For instance when you use a
+ * Global ID server certificate you've to send out the intermediate
+ * CA certificate, too. When you would just configure this with
+ * SSLCACertificateFile and also use client authentication mod_ssl
+ * would accept all clients also issued by this CA. Obviously this
+ * isn't what we want in this situation. So this feature here exists
+ * to allow one to explicity configure CA certificates which are
+ * used only for the server certificate chain.
+ */
+ if (sc->szCertificateChain != NULL) {
+ bSkipFirst = FALSE;
+ for (i = 0; i < SSL_AIDX_MAX && sc->szPublicCertFile[i] != NULL; i++) {
+ if (strEQ(sc->szPublicCertFile[i], sc->szCertificateChain)) {
+ bSkipFirst = TRUE;
+ break;
+ }
+ }
+ if ((n = SSL_CTX_use_certificate_chain(ctx, sc->szCertificateChain,
+ bSkipFirst, NULL)) < 0) {
+ ssl_log(s, SSL_LOG_ERROR,
+ "Init: (%s) Failed to configure CA certificate chain!", cpVHostID);
+ ssl_die();
+ }
+ ssl_log(s, SSL_LOG_TRACE, "Init: (%s) Configuring "
+ "server certificate chain (%d CA certificate%s)", cpVHostID,
+ n, n == 1 ? "" : "s");
+ }
+
+ return;
+}
+
+void ssl_init_CheckServers(server_rec *sm, pool *p)
+{
+ server_rec *s;
+ server_rec **ps;
+ SSLSrvConfigRec *sc;
+ ssl_ds_table *t;
+ pool *sp;
+ char *key;
+ BOOL bConflict;
+
+ /*
+ * Give out warnings when a server has HTTPS configured
+ * for the HTTP port or vice versa
+ */
+ for (s = sm; s != NULL; s = s->next) {
+ sc = mySrvConfig(s);
+ if (sc->bEnabled && s->port == DEFAULT_HTTP_PORT)
+ ssl_log(sm, SSL_LOG_WARN,
+ "Init: (%s) You configured HTTPS(%d) on the standard HTTP(%d) port!",
+ ssl_util_vhostid(p, s), DEFAULT_HTTPS_PORT, DEFAULT_HTTP_PORT);
+ if (!sc->bEnabled && s->port == DEFAULT_HTTPS_PORT)
+ ssl_log(sm, SSL_LOG_WARN,
+ "Init: (%s) You configured HTTP(%d) on the standard HTTPS(%d) port!",
+ ssl_util_vhostid(p, s), DEFAULT_HTTP_PORT, DEFAULT_HTTPS_PORT);
+ }
+
+ /*
+ * Give out warnings when more than one SSL-aware virtual server uses the
+ * same IP:port. This doesn't work because mod_ssl then will always use
+ * just the certificate/keys of one virtual host (which one cannot be said
+ * easily - but that doesn't matter here).
+ */
+ sp = ap_make_sub_pool(p);
+ t = ssl_ds_table_make(sp, sizeof(server_rec *));
+ bConflict = FALSE;
+ for (s = sm; s != NULL; s = s->next) {
+ sc = mySrvConfig(s);
+ if (!sc->bEnabled)
+ continue;
+ key = ap_psprintf(sp, "%pA:%u", &s->addrs->host_addr, s->addrs->host_port);
+ ps = ssl_ds_table_get(t, key);
+ if (ps != NULL) {
+ ssl_log(sm, SSL_LOG_WARN,
+ "Init: SSL server IP/port conflict: %s (%s:%d) vs. %s (%s:%d)",
+ ssl_util_vhostid(p, s),
+ (s->defn_name != NULL ? s->defn_name : "unknown"),
+ s->defn_line_number,
+ ssl_util_vhostid(p, *ps),
+ ((*ps)->defn_name != NULL ? (*ps)->defn_name : "unknown"),
+ (*ps)->defn_line_number);
+ bConflict = TRUE;
+ continue;
+ }
+ ps = ssl_ds_table_push(t, key);
+ *ps = s;
+ }
+ ssl_ds_table_kill(t);
+ ap_destroy_pool(sp);
+ if (bConflict)
+ ssl_log(sm, SSL_LOG_WARN,
+ "Init: You cannot use name-based virtual hosts in conjunction with SSL!!");
return;
}
@@ -485,10 +765,10 @@ static int ssl_init_FindCAList_X509NameCmp(X509_NAME **a, X509_NAME **b)
return(X509_NAME_cmp(*a, *b));
}
-STACK *ssl_init_FindCAList(server_rec *s, pool *pp, char *cpCAfile, char *cpCApath)
+STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s, pool *pp, char *cpCAfile, char *cpCApath)
{
- STACK *skCAList;
- STACK *sk;
+ STACK_OF(X509_NAME) *skCAList;
+ STACK_OF(X509_NAME) *sk;
DIR *dir;
struct DIR_TYPE *direntry;
char *cp;
@@ -506,19 +786,19 @@ STACK *ssl_init_FindCAList(server_rec *s, pool *pp, char *cpCAfile, char *cpCApa
* Start with a empty stack/list where new
* entries get added in sorted order.
*/
- skCAList = sk_new(ssl_init_FindCAList_X509NameCmp);
+ skCAList = sk_X509_NAME_new(ssl_init_FindCAList_X509NameCmp);
/*
* Process CA certificate bundle file
*/
if (cpCAfile != NULL) {
sk = SSL_load_client_CA_file(cpCAfile);
- for(n = 0; sk != NULL && n < sk_num(sk); n++) {
+ for(n = 0; sk != NULL && n < sk_X509_NAME_num(sk); n++) {
ssl_log(s, SSL_LOG_TRACE,
"CA certificate: %s",
- X509_NAME_oneline((X509_NAME *)sk_value(sk, n), NULL, 0));
- if (sk_find(skCAList, sk_value(sk, n)) < 0)
- sk_push(skCAList, sk_value(sk, n));
+ X509_NAME_oneline(sk_X509_NAME_value(sk, n), NULL, 0));
+ if (sk_X509_NAME_find(skCAList, sk_X509_NAME_value(sk, n)) < 0)
+ sk_X509_NAME_push(skCAList, sk_X509_NAME_value(sk, n));
}
}
@@ -530,12 +810,12 @@ STACK *ssl_init_FindCAList(server_rec *s, pool *pp, char *cpCAfile, char *cpCApa
while ((direntry = readdir(dir)) != NULL) {
cp = ap_pstrcat(p, cpCApath, "/", direntry->d_name, NULL);
sk = SSL_load_client_CA_file(cp);
- for(n = 0; sk != NULL && n < sk_num(sk); n++) {
+ for(n = 0; sk != NULL && n < sk_X509_NAME_num(sk); n++) {
ssl_log(s, SSL_LOG_TRACE,
"CA certificate: %s",
- X509_NAME_oneline((X509_NAME *)sk_value(sk, n), NULL, 0));
- if (sk_find(skCAList, sk_value(sk, n)) < 0)
- sk_push(skCAList, sk_value(sk, n));
+ X509_NAME_oneline(sk_X509_NAME_value(sk, n), NULL, 0));
+ if (sk_X509_NAME_find(skCAList, sk_X509_NAME_value(sk, n)) < 0)
+ sk_X509_NAME_push(skCAList, sk_X509_NAME_value(sk, n));
}
}
ap_pclosedir(p, dir);
@@ -544,7 +824,7 @@ STACK *ssl_init_FindCAList(server_rec *s, pool *pp, char *cpCAfile, char *cpCApa
/*
* Cleanup
*/
- sk_set_cmp_func(skCAList, NULL);
+ sk_X509_NAME_set_cmp_func(skCAList, NULL);
ap_destroy_pool(p);
return skCAList;
@@ -553,7 +833,54 @@ STACK *ssl_init_FindCAList(server_rec *s, pool *pp, char *cpCAfile, char *cpCApa
void ssl_init_Child(server_rec *s, pool *p)
{
/* open the mutex lockfile */
- ssl_mutex_open(s, p);
+ ssl_mutex_reinit(s, p);
return;
}
+void ssl_init_ChildKill(void *data)
+{
+ /* currently nothing to do */
+ return;
+}
+
+void ssl_init_ModuleKill(void *data)
+{
+ SSLSrvConfigRec *sc;
+ server_rec *s = (server_rec *)data;
+
+ /*
+ * Drop the session cache and mutex
+ */
+ ssl_scache_kill(s);
+ ssl_mutex_kill(s);
+
+ /*
+ * Free the non-pool allocated structures
+ * in the per-server configurations
+ */
+ for (; s != NULL; s = s->next) {
+ sc = mySrvConfig(s);
+ if (sc->pPublicCert[SSL_AIDX_RSA] != NULL) {
+ X509_free(sc->pPublicCert[SSL_AIDX_RSA]);
+ sc->pPublicCert[SSL_AIDX_RSA] = NULL;
+ }
+ if (sc->pPublicCert[SSL_AIDX_DSA] != NULL) {
+ X509_free(sc->pPublicCert[SSL_AIDX_DSA]);
+ sc->pPublicCert[SSL_AIDX_DSA] = NULL;
+ }
+ if (sc->pPrivateKey[SSL_AIDX_RSA] != NULL) {
+ EVP_PKEY_free(sc->pPrivateKey[SSL_AIDX_RSA]);
+ sc->pPrivateKey[SSL_AIDX_RSA] = NULL;
+ }
+ if (sc->pPrivateKey[SSL_AIDX_DSA] != NULL) {
+ EVP_PKEY_free(sc->pPrivateKey[SSL_AIDX_DSA]);
+ sc->pPrivateKey[SSL_AIDX_DSA] = NULL;
+ }
+ if (sc->pSSLCtx != NULL) {
+ SSL_CTX_free(sc->pSSLCtx);
+ sc->pSSLCtx = NULL;
+ }
+ }
+ return;
+}
+
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_io.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_io.c
index 851c937ab21..e6da098f11f 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_io.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_io.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_engine_io.c
** I/O Functions
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -64,6 +64,216 @@
-- Unknown */
#include "mod_ssl.h"
+/* _________________________________________________________________
+**
+** I/O Request Body Sucking and Re-Injection
+** _________________________________________________________________
+*/
+
+#ifdef SSL_EXPERIMENTAL
+
+/*
+ * Background:
+ *
+ * 1. When the client sends a HTTP/HTTPS request, Apache's core code
+ * reads only the request line ("METHOD /path HTTP/x.y") and the
+ * attached MIME headers ("Foo: bar") up to the terminating line ("CR
+ * LF"). An attached request body (for instance the data of a POST
+ * method) is _NOT_ read. Instead it is read by mod_cgi's content
+ * handler and directly passed to the CGI script.
+ *
+ * 2. mod_ssl supports per-directory re-configuration of SSL parameters.
+ * This is implemented by performing an SSL renegotiation of the
+ * re-configured parameters after the request is read, but before the
+ * response is sent. In more detail: the renegotiation happens after the
+ * request line and MIME headers were read, but _before_ the attached
+ * request body is read. The reason simply is that in the HTTP protocol
+ * usually there is no acknowledgment step between the headers and the
+ * body (there is the 100-continue feature and the chunking facility
+ * only), so Apache has no API hook for this step.
+ *
+ * 3. the problem now occurs when the client sends a POST request for
+ * URL /foo via HTTPS the server and the server has SSL parameters
+ * re-configured on a per-URL basis for /foo. Then mod_ssl has to
+ * perform an SSL renegotiation after the request was read and before
+ * the response is sent. But the problem is the pending POST body data
+ * in the receive buffer of SSL (which Apache still has not read - it's
+ * pending until mod_cgi sucks it in). When mod_ssl now tries to perform
+ * the renegotiation the pending data leads to an I/O error.
+ *
+ * Solution Idea:
+ *
+ * There are only two solutions: Either to simply state that POST
+ * requests to URLs with SSL re-configurations are not allowed, or to
+ * renegotiate really after the _complete_ request (i.e. including
+ * the POST body) was read. Obviously the latter would be preferred,
+ * but it cannot be done easily inside Apache, because as already
+ * mentioned, there is no API step between the body reading and the body
+ * processing. And even when we mod_ssl would hook directly into the
+ * loop of mod_cgi, we wouldn't solve the problem for other handlers, of
+ * course. So the only general solution is to suck in the pending data
+ * of the request body from the OpenSSL BIO into the Apache BUFF. Then
+ * the renegotiation can be done and after this step Apache can proceed
+ * processing the request as before.
+ *
+ * Solution Implementation:
+ *
+ * We cannot simply suck in the data via an SSL_read-based loop because of
+ * HTTP chunking. Instead we _have_ to use the Apache API for this step which
+ * is aware of HTTP chunking. So the trick is to suck in the pending request
+ * data via the Apache API (which uses Apache's BUFF code and in the
+ * background mod_ssl's I/O glue code) and re-inject it later into the Apache
+ * BUFF code again. This way the data flows twice through the Apache BUFF, of
+ * course. But this way the solution doesn't depend on any Apache specifics
+ * and is fully transparent to Apache modules.
+ */
+
+struct ssl_io_suck_st {
+ BOOL active;
+ char *bufptr;
+ int buflen;
+ char *pendptr;
+ int pendlen;
+};
+
+/* prepare request_rec structure for input sucking */
+static void ssl_io_suck_start(request_rec *r)
+{
+ struct ssl_io_suck_st *ss;
+
+ ss = ap_ctx_get(r->ctx, "ssl::io::suck");
+ if (ss == NULL) {
+ ss = ap_palloc(r->pool, sizeof(struct ssl_io_suck_st));
+ ap_ctx_set(r->ctx, "ssl::io::suck", ss);
+ ss->buflen = 8192;
+ ss->bufptr = ap_palloc(r->pool, ss->buflen);
+ }
+ ss->pendptr = ss->bufptr;
+ ss->pendlen = 0;
+ ss->active = FALSE;
+ return;
+}
+
+/* record a sucked input chunk */
+static void ssl_io_suck_record(request_rec *r, char *buf, int len)
+{
+ struct ssl_io_suck_st *ss;
+
+ if ((ss = ap_ctx_get(r->ctx, "ssl::io::suck")) == NULL)
+ return;
+ if (((ss->bufptr+ss->buflen)-(ss->pendptr+ss->pendlen)) < len) {
+ /* "expand" buffer */
+ int newlen;
+ char *newptr;
+ if (ss->buflen < len)
+ newlen = ss->buflen * 2;
+ else
+ newlen = ss->buflen + len;
+ newptr = ap_palloc(r->pool, newlen);
+ memcpy(newptr, ss->bufptr, ss->buflen);
+ ss->bufptr = newptr;
+ ss->buflen = newlen;
+ }
+ memcpy(ss->pendptr+ss->pendlen, buf, len);
+ ss->pendlen += len;
+ return;
+}
+
+/* finish request_rec after input sucking */
+static void ssl_io_suck_end(request_rec *r)
+{
+ struct ssl_io_suck_st *ss;
+
+ if ((ss = ap_ctx_get(r->ctx, "ssl::io::suck")) == NULL)
+ return;
+ ss->active = TRUE;
+ r->read_body = REQUEST_NO_BODY;
+ r->read_length = 0;
+ r->read_chunked = 0;
+ r->remaining = 0;
+ ap_bsetflag(r->connection->client, B_CHUNK, 0);
+ return;
+}
+
+void ssl_io_suck(request_rec *r, SSL *ssl)
+{
+ int rc;
+ int len;
+ char *buf;
+ int buflen;
+ char c;
+ int sucked;
+
+ if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) == OK) {
+ if (ap_should_client_block(r)) {
+
+ /* read client request block through Apache API */
+ buflen = HUGE_STRING_LEN;
+ buf = ap_palloc(r->pool, buflen);
+ ap_hard_timeout("SSL I/O request body pre-sucking", r);
+ sucked = 0;
+ ssl_io_suck_start(r);
+ while ((len = ap_get_client_block(r, buf, buflen)) > 0) {
+ ssl_io_suck_record(r, buf, len);
+ sucked += len;
+ }
+ ssl_io_suck_end(r);
+ ap_kill_timeout(r);
+
+ /* suck trailing data (usually CR LF) which
+ is still in the Apache BUFF layer */
+ while (ap_bpeekc(r->connection->client) != EOF) {
+ c = ap_bgetc(r->connection->client);
+ ssl_io_suck_record(r, &c, 1);
+ sucked++;
+ }
+
+ ssl_log(r->server, SSL_LOG_TRACE,
+ "I/O: sucked %d bytes of input data from SSL/TLS I/O layer "
+ "for delayed injection into Apache I/O layer", sucked);
+ }
+ }
+ return;
+}
+
+/* the SSL_read replacement routine which known about the suck buffer */
+static int ssl_io_suck_read(SSL *ssl, char *buf, int len)
+{
+ ap_ctx *actx;
+ struct ssl_io_suck_st *ss;
+ request_rec *r = NULL;
+ int rv;
+
+ actx = (ap_ctx *)SSL_get_app_data2(ssl);
+ if (actx != NULL)
+ r = (request_rec *)ap_ctx_get(actx, "ssl::request_rec");
+
+ rv = -1;
+ if (r != NULL) {
+ ss = ap_ctx_get(r->ctx, "ssl::io::suck");
+ if (ss != NULL) {
+ if (ss->active && ss->pendlen > 0) {
+ /* ok, there is pre-sucked data */
+ len = (ss->pendlen > len ? len : ss->pendlen);
+ memcpy(buf, ss->pendptr, len);
+ ss->pendptr += len;
+ ss->pendlen -= len;
+ ssl_log(r->server, SSL_LOG_TRACE,
+ "I/O: injecting %d bytes of pre-sucked data "
+ "into Apache I/O layer", len);
+ rv = len;
+ }
+ }
+ }
+ if (rv == -1)
+ rv = SSL_read(ssl, buf, len);
+ return rv;
+}
+
+/* override SSL_read in the following code... */
+#define SSL_read ssl_io_suck_read
+
+#endif /* SSL_EXPERIMENTAL */
/* _________________________________________________________________
**
@@ -94,9 +304,9 @@ void ssl_io_register(void)
ap_hook_register("ap::buff::writev", ssl_io_hook_writev, AP_HOOK_NOCTX);
#endif
#ifdef WIN32
- ap_hook_register("ap::buff::recvwithtimeout",
+ ap_hook_register("ap::buff::recvwithtimeout",
ssl_io_hook_recvwithtimeout, AP_HOOK_NOCTX);
- ap_hook_register("ap::buff::sendwithtimeout",
+ ap_hook_register("ap::buff::sendwithtimeout",
ssl_io_hook_sendwithtimeout, AP_HOOK_NOCTX);
#endif
return;
@@ -125,9 +335,9 @@ static int ssl_io_hook_read(BUFF *fb, char *buf, int len)
if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
rc = SSL_read(ssl, buf, len);
/*
- * Simulate an EINTR in case SSLeay wants to read more.
+ * Simulate an EINTR in case OpenSSL wants to read more.
* (This is usually the case when the client forces an SSL
- * renegotation which is handled implicitly by SSLeay.)
+ * renegotation which is handled implicitly by OpenSSL.)
*/
if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ)
errno = EINTR;
@@ -159,7 +369,7 @@ static int ssl_io_hook_write(BUFF *fb, char *buf, int len)
if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
rc = SSL_write(ssl, buf, len);
/*
- * Simulate an EINTR in case SSLeay wants to write more.
+ * Simulate an EINTR in case OpenSSL wants to write more.
*/
if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE)
errno = EINTR;
@@ -195,7 +405,7 @@ static int ssl_io_hook_writev(BUFF *fb, const struct iovec *iov, int iovcnt)
if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
rc = SSL_writev(ssl, iov, iovcnt);
/*
- * Simulate an EINTR in case SSLeay wants to write more.
+ * Simulate an EINTR in case OpenSSL wants to write more.
*/
if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE)
errno = EINTR;
@@ -257,7 +467,7 @@ static int ssl_io_hook_sendwithtimeout(BUFF *fb, const char *buf, int len)
/* _________________________________________________________________
**
-** Special Functions for SSLeay
+** Special Functions for OpenSSL
** _________________________________________________________________
*/
@@ -372,8 +582,8 @@ static int SSL_recvwithtimeout(BUFF *fb, char *buf, int len)
#endif /*WIN32*/
/*
- * There is no SSL_writev() provided by SSLeay. The reason is mainly because
- * SSLeay has to fragment the data itself again for the SSL record layer, so a
+ * There is no SSL_writev() provided by OpenSSL. The reason is mainly because
+ * OpenSSL has to fragment the data itself again for the SSL record layer, so a
* writev() like interface makes not much sense. What we do is to emulate it
* to at least being able to use the write() like interface. But keep in mind
* that the network I/O performance is not write() like, of course.
@@ -405,7 +615,7 @@ static int SSL_writev(SSL *ssl, const struct iovec *iov, int iovcnt)
#define DUMP_WIDTH 16
-static void ssl_io_data_dump(server_rec *srvr, char *s, long len)
+static void ssl_io_data_dump(server_rec *srvr, const char *s, long len)
{
char buf[256];
char tmp[64];
@@ -453,34 +663,39 @@ static void ssl_io_data_dump(server_rec *srvr, char *s, long len)
return;
}
-long ssl_io_data_cb(BIO *bio, int cmd, char *argp, int argi, long argl, long len)
+long ssl_io_data_cb(BIO *bio, int cmd, const char *argp, int argi, long argl, long rc)
{
SSL *ssl;
conn_rec *c;
server_rec *s;
if ((ssl = (SSL *)BIO_get_callback_arg(bio)) == NULL)
- return len;
+ return rc;
if ((c = (conn_rec *)SSL_get_app_data(ssl)) == NULL)
- return len;
+ return rc;
s = c->server;
- if (len >= 0) {
- ssl_log(s, SSL_LOG_DEBUG,
- "%s: %s %ld/%d bytes %s BIO#%08X [mem: %08lX] %s",
- SSL_LIBRARY_NAME, (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),
- len, argi, (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "to" : "from"),
- bio, argp, (argp != NULL ? "(BIO dump follows)" : "(Ops, no memory buffer?)"));
- if (argp != NULL)
- ssl_io_data_dump(s, argp, len);
- }
- else {
- ssl_log(s, SSL_LOG_DEBUG,
- "%s: I/O error, %d bytes expected to %s on BIO#%08X [mem: %08lX]",
- SSL_LIBRARY_NAME, argi,
- (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),
- bio, argp);
+ if ( cmd == (BIO_CB_WRITE|BIO_CB_RETURN)
+ || cmd == (BIO_CB_READ |BIO_CB_RETURN) ) {
+ if (rc >= 0) {
+ ssl_log(s, SSL_LOG_DEBUG,
+ "%s: %s %ld/%d bytes %s BIO#%08X [mem: %08lX] %s",
+ SSL_LIBRARY_NAME,
+ (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),
+ rc, argi, (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "to" : "from"),
+ bio, argp,
+ (argp != NULL ? "(BIO dump follows)" : "(Ops, no memory buffer?)"));
+ if (argp != NULL)
+ ssl_io_data_dump(s, argp, rc);
+ }
+ else {
+ ssl_log(s, SSL_LOG_DEBUG,
+ "%s: I/O error, %d bytes expected to %s on BIO#%08X [mem: %08lX]",
+ SSL_LIBRARY_NAME, argi,
+ (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),
+ bio, argp);
+ }
}
- return len;
+ return rc;
}
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_kernel.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_kernel.c
index 99b19843c07..3addfce1275 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_kernel.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_kernel.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_engine_kernel.c
** The SSL engine kernel
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -130,8 +130,11 @@ void ssl_hook_NewConnection(conn_rec *conn)
server_rec *srvr;
BUFF *fb;
SSLSrvConfigRec *sc;
+ ap_ctx *apctx;
SSL *ssl;
char *cp;
+ char *cpVHostID;
+ X509 *xs;
int rc;
int n;
@@ -158,8 +161,9 @@ void ssl_hook_NewConnection(conn_rec *conn)
* Remember the connection information for
* later access inside callback functions
*/
+ cpVHostID = ssl_util_vhostid(conn->pool, srvr);
ssl_log(srvr, SSL_LOG_INFO, "Connection to child %d established (server %s)",
- conn->child_num, ssl_util_vhostid(conn->pool, srvr));
+ conn->child_num, cpVHostID);
/*
* Seed the Pseudo Random Number Generator (PRNG)
@@ -172,54 +176,41 @@ void ssl_hook_NewConnection(conn_rec *conn)
* attach this to the socket. Additionally we register this attachment
* so we can detach later.
*/
- ssl = SSL_new(sc->pSSLCtx);
- SSL_set_app_data(ssl, conn); /* conn_rec (available now) */
- SSL_set_app_data2(ssl, NULL); /* request_rec (available later) */
+ if ((ssl = SSL_new(sc->pSSLCtx)) == NULL) {
+ ssl_log(conn->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
+ "Unable to create a new SSL connection from the SSL context");
+ ap_ctx_set(fb->ctx, "ssl", NULL);
+ ap_bsetflag(fb, B_EOF|B_EOUT, 1);
+ conn->aborted = 1;
+ return;
+ }
+ SSL_clear(ssl);
+ SSL_set_session_id_context(ssl, (unsigned char *)cpVHostID, strlen(cpVHostID));
+ SSL_set_app_data(ssl, conn);
+ apctx = ap_ctx_new(conn->pool);
+ ap_ctx_set(apctx, "ssl::request_rec", NULL);
+ ap_ctx_set(apctx, "ssl::verify::depth", AP_CTX_NUM2PTR(0));
+ SSL_set_app_data2(ssl, apctx);
SSL_set_fd(ssl, fb->fd);
ap_ctx_set(fb->ctx, "ssl", ssl);
- ap_register_cleanup(conn->pool, (void *)conn,
- ssl_hook_CloseConnection, ssl_hook_CloseConnection);
/*
- * Configure SSLeay BIO Data Logging
+ * Configure callbacks for SSL connection
*/
+ SSL_set_tmp_rsa_callback(ssl, ssl_callback_TmpRSA);
+ SSL_set_tmp_dh_callback(ssl, ssl_callback_TmpDH);
if (sc->nLogLevel >= SSL_LOG_DEBUG) {
BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb);
BIO_set_callback_arg(SSL_get_rbio(ssl), ssl);
}
/*
- * Configure the server certificate and private key
- * which should be used for this connection.
- */
- if (sc->szCertificateFile != NULL) {
- if (SSL_use_certificate(ssl, sc->px509Certificate) <= 0) {
- ssl_log(conn->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Unable to configure server certificate for connection");
- SSL_free(ssl);
- ap_ctx_set(fb->ctx, "ssl", NULL);
- ap_bsetflag(fb, B_EOF|B_EOUT, 1);
- conn->aborted = 1;
- return;
- }
- if (SSL_use_RSAPrivateKey(ssl, sc->prsaKey) <= 0) {
- ssl_log(conn->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Unable to configure server private key for connection");
- SSL_free(ssl);
- ap_ctx_set(fb->ctx, "ssl", NULL);
- ap_bsetflag(fb, B_EOF|B_EOUT, 1);
- conn->aborted = 1;
- return;
- }
- }
-
- /*
* Predefine some client verification results
*/
ap_ctx_set(fb->ctx, "ssl::client::dn", NULL);
ap_ctx_set(fb->ctx, "ssl::verify::error", NULL);
- /*
+ /*
* We have to manage a I/O timeout ourself, because Apache
* does it the first time when reading the request, but we're
* working some time before this happens.
@@ -243,7 +234,7 @@ void ssl_hook_NewConnection(conn_rec *conn)
ssl_log(srvr, SSL_LOG_INFO,
"SSL handshake stopped: connection was closed");
SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
- while (!SSL_shutdown(ssl));
+ SSL_smart_shutdown(ssl);
SSL_free(ssl);
ap_ctx_set(fb->ctx, "ssl", NULL);
ap_bsetflag(fb, B_EOF|B_EOUT, 1);
@@ -252,16 +243,15 @@ void ssl_hook_NewConnection(conn_rec *conn)
}
else if (ERR_GET_REASON(ERR_peek_error()) == SSL_R_HTTP_REQUEST) {
/*
- * The case where SSLeay has recognized a HTTP request:
+ * The case where OpenSSL has recognized a HTTP request:
* This means the client speaks plain HTTP on our HTTPS
* port. Hmmmm... At least for this error we can be more friendly
* and try to provide him with a HTML error page. We have only one
- * problem: SSLeay has already read some bytes from the HTTP
+ * problem: OpenSSL has already read some bytes from the HTTP
* request. So we have to skip the request line manually and
* instead provide a faked one in order to continue the internal
* Apache processing.
*
- * (This feature is only available for SSLeay 0.9.0 and higher)
*/
char ca[2];
int rv;
@@ -287,7 +277,7 @@ void ssl_hook_NewConnection(conn_rec *conn)
/* third: kick away the SSL stuff */
SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
- while (!SSL_shutdown(ssl));
+ SSL_smart_shutdown(ssl);
SSL_free(ssl);
ap_ctx_set(fb->ctx, "ssl", NULL);
@@ -295,11 +285,11 @@ void ssl_hook_NewConnection(conn_rec *conn)
return;
}
else if (ap_ctx_get(ap_global_ctx, "ssl::handshake::timeout") == (void *)TRUE) {
- ssl_log(srvr, SSL_LOG_ERROR,
+ ssl_log(srvr, SSL_LOG_ERROR,
"SSL handshake timed out (client %s, server %s)",
- conn->remote_ip, ssl_util_vhostid(conn->pool, srvr));
+ conn->remote_ip, cpVHostID);
SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
- while (!SSL_shutdown(ssl));
+ SSL_smart_shutdown(ssl);
SSL_free(ssl);
ap_ctx_set(fb->ctx, "ssl", NULL);
ap_bsetflag(fb, B_EOF|B_EOUT, 1);
@@ -309,10 +299,16 @@ void ssl_hook_NewConnection(conn_rec *conn)
else if (SSL_get_error(ssl, rc) == SSL_ERROR_SYSCALL) {
if (errno == EINTR)
continue;
- ssl_log(srvr, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "SSL handshake interrupted by system");
+ if (errno > 0)
+ ssl_log(srvr, SSL_LOG_ERROR|SSL_ADD_SSLERR|SSL_ADD_ERRNO,
+ "SSL handshake interrupted by system "
+ "[Hint: Stop button pressed in browser?!]");
+ else
+ ssl_log(srvr, SSL_LOG_INFO|SSL_ADD_SSLERR|SSL_ADD_ERRNO,
+ "Spurious SSL handshake interrupt"
+ "[Hint: Usually just one of those OpenSSL confusions!?]");
SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
- while (!SSL_shutdown(ssl));
+ SSL_smart_shutdown(ssl);
SSL_free(ssl);
ap_ctx_set(fb->ctx, "ssl", NULL);
ap_bsetflag(fb, B_EOF|B_EOUT, 1);
@@ -325,7 +321,7 @@ void ssl_hook_NewConnection(conn_rec *conn)
*/
ssl_log(srvr, SSL_LOG_ERROR|SSL_ADD_SSLERR|SSL_ADD_ERRNO,
"SSL handshake failed (client %s, server %s)",
- conn->remote_ip, ssl_util_vhostid(conn->pool, srvr));
+ conn->remote_ip, cpVHostID);
/*
* try to gracefully shutdown the connection:
@@ -335,7 +331,7 @@ void ssl_hook_NewConnection(conn_rec *conn)
* - block the socket, so Apache cannot operate any more
*/
SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
- while (!SSL_shutdown(ssl));
+ SSL_smart_shutdown(ssl);
SSL_free(ssl);
ap_ctx_set(fb->ctx, "ssl", NULL);
ap_bsetflag(fb, B_EOF|B_EOUT, 1);
@@ -351,7 +347,7 @@ void ssl_hook_NewConnection(conn_rec *conn)
ssl_log(srvr, SSL_LOG_ERROR|SSL_ADD_SSLERR,
"SSL client authentication failed: %s", cp);
SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
- while (!SSL_shutdown(ssl));
+ SSL_smart_shutdown(ssl);
SSL_free(ssl);
ap_ctx_set(fb->ctx, "ssl", NULL);
ap_bsetflag(fb, B_EOF|B_EOUT, 1);
@@ -360,17 +356,12 @@ void ssl_hook_NewConnection(conn_rec *conn)
}
/*
- * Remember the peer certificate when
- * client authentication was done
+ * Remember the peer certificate's DN
*/
- if (sc->nVerifyClient != SSL_CVERIFY_NONE) {
- char *s;
- X509 *xs;
- if ((xs = SSL_get_peer_certificate(ssl)) != NULL) {
- s = X509_NAME_oneline(X509_get_subject_name(xs), NULL, 0);
- ap_ctx_set(fb->ctx, "ssl::client::dn", ap_pstrdup(conn->pool, s));
- free(s);
- }
+ if ((xs = SSL_get_peer_certificate(ssl)) != NULL) {
+ cp = X509_NAME_oneline(X509_get_subject_name(xs), NULL, 0);
+ ap_ctx_set(fb->ctx, "ssl::client::dn", ap_pstrdup(conn->pool, cp));
+ free(cp);
}
/*
@@ -382,7 +373,7 @@ void ssl_hook_NewConnection(conn_rec *conn)
ssl_log(srvr, SSL_LOG_ERROR,
"No acceptable peer certificate available");
SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
- while (!SSL_shutdown(ssl));
+ SSL_smart_shutdown(ssl);
SSL_free(ssl);
ap_ctx_set(fb->ctx, "ssl", NULL);
ap_bsetflag(fb, B_EOF|B_EOUT, 1);
@@ -399,7 +390,7 @@ void ssl_hook_NewConnection(conn_rec *conn)
/*
* Improve I/O throughput by using
- * SSLeay's read-ahead functionality
+ * OpenSSL's read-ahead functionality
* (don't used under Win32, because
* there we use select())
*/
@@ -407,6 +398,12 @@ void ssl_hook_NewConnection(conn_rec *conn)
SSL_set_read_ahead(ssl, TRUE);
#endif
+#ifdef SSL_VENDOR
+ /* Allow vendors to do more things on connection time... */
+ ap_hook_use("ap::mod_ssl::vendor::new_connection",
+ AP_HOOK_SIG2(void,ptr), AP_HOOK_ALL, conn);
+#endif
+
return;
}
@@ -422,29 +419,89 @@ void ssl_hook_TimeoutConnection(int sig)
/*
* Close the SSL part of the socket connection
+ * (called immediately _before_ the socket is closed)
*/
-void ssl_hook_CloseConnection(void *_conn)
+void ssl_hook_CloseConnection(conn_rec *conn)
{
- conn_rec *conn = _conn;
SSL *ssl;
+ char *cpType;
+
+ ssl = ap_ctx_get(conn->client->ctx, "ssl");
+ if (ssl == NULL)
+ return;
/*
- * Optionally shutdown the SSL session
+ * First make sure that no more data is pending in Apache's BUFF,
+ * because when it's (implicitly) flushed later by the ap_bclose()
+ * calls of Apache it would lead to an I/O error in the browser due
+ * to the fact that the SSL layer was already removed by us.
+ */
+ ap_bflush(conn->client);
+
+ /*
+ * Now close the SSL layer of the connection. We've to take
+ * the TLSv1 standard into account here:
+ *
+ * | 7.2.1. Closure alerts
+ * |
+ * | The client and the server must share knowledge that the connection is
+ * | ending in order to avoid a truncation attack. Either party may
+ * | initiate the exchange of closing messages.
+ * |
+ * | close_notify
+ * | This message notifies the recipient that the sender will not send
+ * | any more messages on this connection. The session becomes
+ * | unresumable if any connection is terminated without proper
+ * | close_notify messages with level equal to warning.
+ * |
+ * | Either party may initiate a close by sending a close_notify alert.
+ * | Any data received after a closure alert is ignored.
+ * |
+ * | Each party is required to send a close_notify alert before closing
+ * | the write side of the connection. It is required that the other party
+ * | respond with a close_notify alert of its own and close down the
+ * | connection immediately, discarding any pending writes. It is not
+ * | required for the initiator of the close to wait for the responding
+ * | close_notify alert before closing the read side of the connection.
+ *
+ * This means we've to send a close notify message, but haven't to wait
+ * for the close notify of the client. Actually we cannot wait for the
+ * close notify of the client because some clients (including Netscape
+ * 4.x) don't send one, so we would hang.
*/
- ssl = ap_ctx_get(conn->client->ctx, "ssl");
- if (ssl != NULL) {
- SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
- while (!SSL_shutdown(ssl));
- SSL_free(ssl);
- ap_ctx_set(conn->client->ctx, "ssl", NULL);
- }
/*
- * And finally log the connection close
+ * exchange close notify messages, but allow the user
+ * to force the type of handshake via SetEnvIf directive
*/
- ssl_log(conn->server, SSL_LOG_INFO, "Connection to child %d closed (server %s)",
- conn->child_num, ssl_util_vhostid(conn->pool, conn->server));
+ if (ap_ctx_get(conn->client->ctx, "ssl::flag::unclean-shutdown") == PTRUE) {
+ /* perform no close notify handshake at all
+ (violates the SSL/TLS standard!) */
+ SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
+ cpType = "unclean";
+ }
+ else if (ap_ctx_get(conn->client->ctx, "ssl::flag::accurate-shutdown") == PTRUE) {
+ /* send close notify and wait for clients close notify
+ (standard compliant, but usually causes connection hangs) */
+ SSL_set_shutdown(ssl, 0);
+ cpType = "accurate";
+ }
+ else {
+ /* send close notify, but don't wait for clients close notify
+ (standard compliant and safe, so it's the DEFAULT!) */
+ SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
+ cpType = "standard";
+ }
+ SSL_smart_shutdown(ssl);
+
+ /* deallocate the SSL connection */
+ SSL_free(ssl);
+ ap_ctx_set(conn->client->ctx, "ssl", NULL);
+ /* and finally log the fact that we've closed the connection */
+ ssl_log(conn->server, SSL_LOG_INFO,
+ "Connection to child %d closed with %s shutdown (server %s)",
+ conn->child_num, cpType, ssl_util_vhostid(conn->pool, conn->server));
return;
}
@@ -454,14 +511,17 @@ void ssl_hook_CloseConnection(void *_conn)
int ssl_hook_ReadReq(request_rec *r)
{
SSL *ssl;
+ ap_ctx *apctx;
/*
- * Get the SSL connection structure and perform the
+ * Get the SSL connection structure and perform the
* delayed interlinking from SSL back to request_rec
*/
ssl = ap_ctx_get(r->connection->client->ctx, "ssl");
- if (ssl != NULL)
- SSL_set_app_data2(ssl, r);
+ if (ssl != NULL) {
+ apctx = SSL_get_app_data2(ssl);
+ ap_ctx_set(apctx, "ssl::request_rec", r);
+ }
/*
* Force the mod_ssl content handler when URL indicates this
@@ -480,6 +540,43 @@ int ssl_hook_ReadReq(request_rec *r)
}
/*
+ * URL Translation Handler
+ */
+int ssl_hook_Translate(request_rec *r)
+{
+ if (ap_ctx_get(r->connection->client->ctx, "ssl") == NULL)
+ return DECLINED;
+
+ /*
+ * Log information about incoming HTTPS requests
+ */
+ if (ap_is_initial_req(r))
+ ssl_log(r->server, SSL_LOG_INFO,
+ "%s HTTPS request received for child %d (server %s)",
+ r->connection->keepalives <= 0 ?
+ "Initial (No.1)" :
+ ap_psprintf(r->pool, "Subsequent (No.%d)",
+ r->connection->keepalives+1),
+ r->connection->child_num,
+ ssl_util_vhostid(r->pool, r->server));
+
+ /*
+ * Move SetEnvIf information from request_rec to conn_rec/BUFF
+ * to allow the close connection handler to use them.
+ */
+ if (ap_table_get(r->subprocess_env, "ssl-unclean-shutdown") != NULL)
+ ap_ctx_set(r->connection->client->ctx, "ssl::flag::unclean-shutdown", PTRUE);
+ else
+ ap_ctx_set(r->connection->client->ctx, "ssl::flag::unclean-shutdown", PFALSE);
+ if (ap_table_get(r->subprocess_env, "ssl-accurate-shutdown") != NULL)
+ ap_ctx_set(r->connection->client->ctx, "ssl::flag::accurate-shutdown", PTRUE);
+ else
+ ap_ctx_set(r->connection->client->ctx, "ssl::flag::accurate-shutdown", PFALSE);
+
+ return DECLINED;
+}
+
+/*
* Content Handler
*/
int ssl_hook_Handler(request_rec *r)
@@ -510,55 +607,6 @@ int ssl_hook_Handler(request_rec *r)
}
/*
- * Auth Handler:
- * Fake a Basic authentication from the X509 client certificate.
- *
- * This must be run fairly early on to prevent a real authentication from
- * occuring, in particular it must be run before anything else that
- * authenticates a user. This means that the Module statement for this
- * module should be LAST in the Configuration file.
- */
-int ssl_hook_Auth(request_rec *r)
-{
- SSLSrvConfigRec *sc = mySrvConfig(r->server);
- SSLDirConfigRec *dc = myDirConfig(r);
- char b1[MAX_STRING_LEN], b2[MAX_STRING_LEN];
- char *clientdn;
-
- /*
- * We decline operation in various situations..
- */
- if (!sc->bEnabled)
- return DECLINED;
- if (ap_ctx_get(r->connection->client->ctx, "ssl") == NULL)
- return DECLINED;
- if (!(dc->nOptions & SSL_OPT_FAKEBASICAUTH))
- return DECLINED;
- if (r->connection->user)
- return DECLINED;
- if ((clientdn = (char *)ap_ctx_get(r->connection->client->ctx, "ssl::client::dn")) == NULL)
- return DECLINED;
-
- /*
- * Fake a password - which one would be immaterial, as, it seems, an empty
- * password in the users file would match ALL incoming passwords, if only
- * we were using the standard crypt library routine. Unfortunately, SSLeay
- * "fixes" a "bug" in crypt and thus prevents blank passwords from
- * working. (IMHO what they really fix is a bug in the users of the code
- * - failing to program correctly for shadow passwords). We need,
- * therefore, to provide a password. This password can be matched by
- * adding the string "xxj31ZMTZzkVA" as the password in the user file.
- * This is just the crypted variant of the word "password" ;-)
- */
- ap_snprintf(b1, sizeof(b1), "%s:password", clientdn);
- ssl_util_uuencode(b2, b1, FALSE);
- ap_snprintf(b1, sizeof(b1), "Basic %s", b2);
- ap_table_set(r->headers_in, "Authorization", b1);
-
- return DECLINED;
-}
-
-/*
* Access Handler
*/
int ssl_hook_Access(request_rec *r)
@@ -566,25 +614,35 @@ int ssl_hook_Access(request_rec *r)
SSLDirConfigRec *dc;
SSLSrvConfigRec *sc;
SSL *ssl;
- SSL_CTX *ctx;
+ SSL_CTX *ctx = NULL;
array_header *apRequirement;
ssl_require_t *pRequirements;
ssl_require_t *pRequirement;
char *cp;
int ok;
int i;
- BOOL renegotiate;
+ BOOL renegotiate;
+ BOOL renegotiate_quick;
#ifdef SSL_EXPERIMENTAL
BOOL reconfigured_locations;
- STACK *skCAList;
+ STACK_OF(X509_NAME) *skCAList;
char *cpCAPath;
char *cpCAFile;
#endif
- STACK *skCipherOld;
- STACK *skCipher;
+ X509 *cert;
+ STACK_OF(X509) *certstack;
+ X509_STORE *certstore;
+ X509_STORE_CTX certstorectx;
+ int depth;
+ STACK_OF(SSL_CIPHER) *skCipherOld;
+ STACK_OF(SSL_CIPHER) *skCipher;
+ SSL_CIPHER *pCipher;
+ ap_ctx *apctx;
int nVerifyOld;
int nVerify;
int n;
+ void *vp;
+ int rc;
dc = myDirConfig(r);
sc = mySrvConfig(r->server);
@@ -597,6 +655,8 @@ int ssl_hook_Access(request_rec *r)
*/
if (dc->bSSLRequired && ssl == NULL) {
ap_log_reason("SSL connection required", r->filename, r);
+ /* remember forbidden access for strict require option */
+ ap_table_setn(r->notes, "ssl-access-forbidden", (void *)1);
return FORBIDDEN;
}
@@ -609,83 +669,154 @@ int ssl_hook_Access(request_rec *r)
return DECLINED;
/*
- * Support for per-directory SSL connection parameters.
- *
+ * Support for per-directory reconfigured SSL connection parameters.
+ *
* This is implemented by forcing an SSL renegotiation with the
* reconfigured parameter suite. But Apache's internal API processing
- * makes our life very hard, because when internal sub-requests occur we
- * nevertheless should avoid multiple unnecessary SSL handshakes (they
- * need network I/O and time to perform). But the optimization for
- * filtering out the unnecessary handshakes isn't such obvious.
- * Especially because while Apache is in its sub-request processing the
- * client could force additional handshakes, too. And these take place
- * perhaps without our notice. So the only possibility is to ask
- * SSLeay/OpenSSL whether the renegotiation has to be performed or not. It
- * has to performed when some parameters which were previously known (by
- * us) are not those we've now reconfigured (as known by SSLeay/OpenSSL).
- */
- renegotiate = FALSE;
+ * makes our life very hard here, because when internal sub-requests occur
+ * we nevertheless should avoid multiple unnecessary SSL handshakes (they
+ * require extra network I/O and especially time to perform).
+ *
+ * But the optimization for filtering out the unnecessary handshakes isn't
+ * obvious and trivial. Especially because while Apache is in its
+ * sub-request processing the client could force additional handshakes,
+ * too. And these take place perhaps without our notice. So the only
+ * possibility is to explicitly _ask_ OpenSSL whether the renegotiation
+ * has to be performed or not. It has to performed when some parameters
+ * which were previously known (by us) are not those we've now
+ * reconfigured (as known by OpenSSL) or (in optimized way) at least when
+ * the reconfigured parameter suite is stronger (more restrictions) than
+ * the currently active one.
+ */
+ renegotiate = FALSE;
+ renegotiate_quick = FALSE;
#ifdef SSL_EXPERIMENTAL
reconfigured_locations = FALSE;
#endif
- /*
- * override of SSLCipherSuite
+ /*
+ * Override of SSLCipherSuite
+ *
+ * We provide two options here:
+ *
+ * o The paranoid and default approach where we force a renegotiation when
+ * the cipher suite changed in _any_ way (which is straight-forward but
+ * often forces renegotiations too often and is perhaps not what the
+ * user actually wanted).
+ *
+ * o The optimized and still secure way where we force a renegotiation
+ * only if the currently active cipher is no longer contained in the
+ * reconfigured/new cipher suite. Any other changes are not important
+ * because it's the servers choice to select a cipher from the ones the
+ * client supports. So as long as the current cipher is still in the new
+ * cipher suite we're happy. Because we can assume we would have
+ * selected it again even when other (better) ciphers exists now in the
+ * new cipher suite. This approach is fine because the user explicitly
+ * has to enable this via ``SSLOptions +OptRenegotiate''. So we do no
+ * implicit optimizations.
*/
if (dc->szCipherSuite != NULL) {
- /* remember old cipher suite for comparison */
- if ((skCipherOld = SSL_get_ciphers(ssl)) != NULL)
- skCipherOld = sk_dup(skCipherOld);
- /* configure new cipher suite */
+ /* remember old state */
+ pCipher = NULL;
+ skCipherOld = NULL;
+ if (dc->nOptions & SSL_OPT_OPTRENEGOTIATE)
+ pCipher = SSL_get_current_cipher(ssl);
+ else {
+ skCipherOld = SSL_get_ciphers(ssl);
+ if (skCipherOld != NULL)
+ skCipherOld = sk_SSL_CIPHER_dup(skCipherOld);
+ }
+ /* configure new state */
if (!SSL_set_cipher_list(ssl, dc->szCipherSuite)) {
ssl_log(r->server, SSL_LOG_WARN|SSL_ADD_SSLERR,
"Unable to reconfigure (per-directory) permitted SSL ciphers");
+ if (skCipherOld != NULL)
+ sk_SSL_CIPHER_free(skCipherOld);
return FORBIDDEN;
}
- /* determine whether the cipher suite was actually changed */
+ /* determine whether a renegotiation has to be forced */
skCipher = SSL_get_ciphers(ssl);
- if ((skCipherOld == NULL && skCipher != NULL) ||
- (skCipherOld != NULL && skCipher == NULL) )
- renegotiate = TRUE;
- else if (skCipherOld != NULL && skCipher != NULL) {
- for (n = 0; n < sk_num(skCipher); n++) {
- if (sk_find(skCipherOld, sk_value(skCipher, n)) < 0) {
- renegotiate = TRUE;
- break;
- }
+ if (dc->nOptions & SSL_OPT_OPTRENEGOTIATE) {
+ /* optimized way */
+ if ((pCipher == NULL && skCipher != NULL) ||
+ (pCipher != NULL && skCipher == NULL) )
+ renegotiate = TRUE;
+ else if (pCipher != NULL && skCipher != NULL
+ && sk_SSL_CIPHER_find(skCipher, pCipher) < 0) {
+ renegotiate = TRUE;
}
- for (n = 0; n < sk_num(skCipherOld); n++) {
- if (sk_find(skCipher, sk_value(skCipherOld, n)) < 0) {
- renegotiate = TRUE;
- break;
+ }
+ else {
+ /* paranoid way */
+ if ((skCipherOld == NULL && skCipher != NULL) ||
+ (skCipherOld != NULL && skCipher == NULL) )
+ renegotiate = TRUE;
+ else if (skCipherOld != NULL && skCipher != NULL) {
+ for (n = 0; !renegotiate && n < sk_SSL_CIPHER_num(skCipher); n++) {
+ if (sk_SSL_CIPHER_find(skCipherOld, sk_SSL_CIPHER_value(skCipher, n)) < 0)
+ renegotiate = TRUE;
+ }
+ for (n = 0; !renegotiate && n < sk_SSL_CIPHER_num(skCipherOld); n++) {
+ if (sk_SSL_CIPHER_find(skCipher, sk_SSL_CIPHER_value(skCipherOld, n)) < 0)
+ renegotiate = TRUE;
}
}
}
- /* free old cipher suite */
+ /* cleanup */
if (skCipherOld != NULL)
- sk_free(skCipherOld);
+ sk_SSL_CIPHER_free(skCipherOld);
+ /* tracing */
+ if (renegotiate)
+ ssl_log(r->server, SSL_LOG_TRACE,
+ "Reconfigured cipher suite will force renegotiation");
}
/*
- * override of SSLVerifyDepth:
- * This is handled by us manually inside the verify callback
- * function and not by SSLeay internally. And our function is
- * aware of both the per-server and per-directory contexts.
- * All we have to do is to force the renegotiation when the
- * maximum allowed depth is changed.
+ * override of SSLVerifyDepth
+ *
+ * The depth checks are handled by us manually inside the verify callback
+ * function and not by OpenSSL internally (and our function is aware of
+ * both the per-server and per-directory contexts). So we cannot ask
+ * OpenSSL about the currently verify depth. Instead we remember it in our
+ * ap_ctx attached to the SSL* of OpenSSL. We've to force the
+ * renegotiation if the reconfigured/new verify depth is less than the
+ * currently active/remembered verify depth (because this means more
+ * restriction on the certificate chain).
*/
if (dc->nVerifyDepth != UNSET) {
- if (dc->nVerifyDepth != sc->nVerifyDepth)
+ apctx = SSL_get_app_data2(ssl);
+ if ((vp = ap_ctx_get(apctx, "ssl::verify::depth")) != NULL)
+ n = AP_CTX_PTR2NUM(vp);
+ else
+ n = sc->nVerifyDepth;
+ ap_ctx_set(apctx, "ssl::verify::depth",
+ AP_CTX_NUM2PTR(dc->nVerifyDepth));
+ /* determine whether a renegotiation has to be forced */
+ if (dc->nVerifyDepth < n) {
renegotiate = TRUE;
+ ssl_log(r->server, SSL_LOG_TRACE,
+ "Reduced client verification depth will force renegotiation");
+ }
}
- /*
+ /*
* override of SSLVerifyClient
+ *
+ * We force a renegotiation if the reconfigured/new verify type is
+ * stronger than the currently active verify type.
+ *
+ * The order is: none << optional_no_ca << optional << require
+ *
+ * Additionally the following optimization is possible here: When the
+ * currently active verify type is "none" but a client certificate is
+ * already known/present, it's enough to manually force a client
+ * verification but at least skip the I/O-intensive renegotation
+ * handshake.
*/
if (dc->nVerifyClient != SSL_CVERIFY_UNSET) {
- /* remember old verify mode */
+ /* remember old state */
nVerifyOld = SSL_get_verify_mode(ssl);
- /* configure new verify mode */
+ /* configure new state */
nVerify = SSL_VERIFY_NONE;
if (dc->nVerifyClient == SSL_CVERIFY_REQUIRE)
nVerify |= SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
@@ -694,9 +825,25 @@ int ssl_hook_Access(request_rec *r)
nVerify |= SSL_VERIFY_PEER;
SSL_set_verify(ssl, nVerify, ssl_callback_SSLVerify);
SSL_set_verify_result(ssl, X509_V_OK);
- /* determine whether the verify mode was actually changed */
- if (nVerify != nVerifyOld)
- renegotiate = TRUE;
+ /* determine whether we've to force a renegotiation */
+ if (nVerify != nVerifyOld) {
+ if ( ( (nVerifyOld == SSL_VERIFY_NONE)
+ && (nVerify != SSL_VERIFY_NONE))
+ || ( !(nVerifyOld & SSL_VERIFY_PEER)
+ && (nVerify & SSL_VERIFY_PEER))
+ || ( !(nVerifyOld & (SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
+ && (nVerify & (SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT)))) {
+ renegotiate = TRUE;
+ /* optimization */
+ if ( dc->nOptions & SSL_OPT_OPTRENEGOTIATE
+ && nVerifyOld == SSL_VERIFY_NONE
+ && SSL_get_peer_certificate(ssl) != NULL)
+ renegotiate_quick = TRUE;
+ ssl_log(r->server, SSL_LOG_TRACE,
+ "Changed client verification type will force %srenegotiation",
+ renegotiate_quick ? "quick " : "");
+ }
+ }
}
/*
@@ -710,13 +857,13 @@ int ssl_hook_Access(request_rec *r)
* chance to provide this functionality...
*/
#ifdef SSL_EXPERIMENTAL
- if ( ( dc->szCACertificateFile != NULL
- && ( sc->szCACertificateFile == NULL
- || ( sc->szCACertificateFile != NULL
+ if ( ( dc->szCACertificateFile != NULL
+ && ( sc->szCACertificateFile == NULL
+ || ( sc->szCACertificateFile != NULL
&& strNE(dc->szCACertificateFile, sc->szCACertificateFile))))
- || ( dc->szCACertificatePath != NULL
- && ( sc->szCACertificatePath == NULL
- || ( sc->szCACertificatePath != NULL
+ || ( dc->szCACertificatePath != NULL
+ && ( sc->szCACertificatePath == NULL
+ || ( sc->szCACertificatePath != NULL
&& strNE(dc->szCACertificatePath, sc->szCACertificatePath)))) ) {
cpCAFile = dc->szCACertificateFile != NULL ?
dc->szCACertificateFile : sc->szCACertificateFile;
@@ -724,8 +871,8 @@ int ssl_hook_Access(request_rec *r)
dc->szCACertificatePath : sc->szCACertificatePath;
/*
FIXME: This should be...
- if (!SSL_load_verify_locations(ssl, cpCAFile, cpCAPath)) {
- ...but SSLeay/OpenSSL still doesn't provide this!
+ if (!SSL_load_verify_locations(ssl, cpCAFile, cpCAPath)) {
+ ...but OpenSSL still doesn't provide this!
*/
if (!SSL_CTX_load_verify_locations(ctx, cpCAFile, cpCAPath)) {
ssl_log(r->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
@@ -733,7 +880,7 @@ int ssl_hook_Access(request_rec *r)
"for client authentication");
return FORBIDDEN;
}
- if ((skCAList = ssl_init_FindCAList(r->server, r->pool,
+ if ((skCAList = ssl_init_FindCAList(r->server, r->pool,
cpCAFile, cpCAPath)) == NULL) {
ssl_log(r->server, SSL_LOG_ERROR,
"Unable to determine list of available "
@@ -743,17 +890,33 @@ int ssl_hook_Access(request_rec *r)
SSL_set_client_CA_list(ssl, skCAList);
renegotiate = TRUE;
reconfigured_locations = TRUE;
+ ssl_log(r->server, SSL_LOG_TRACE,
+ "Changed client verification locations will force renegotiation");
}
#endif /* SSL_EXPERIMENTAL */
+#ifndef SSL_EXPERIMENTAL
/*
+ * SSL renegotiations in conjunction with HTTP
+ * requests using the POST method are not supported.
+ */
+ if (renegotiate && r->method_number == M_POST) {
+ ssl_log(r->server, SSL_LOG_ERROR,
+ "SSL Re-negotiation in conjunction with POST method not supported!");
+ ssl_log(r->server, SSL_LOG_INFO,
+ "There is only experimental support which has to be enabled first");
+ return METHOD_NOT_ALLOWED;
+ }
+#endif /* not SSL_EXPERIMENTAL */
+
+ /*
* now do the renegotiation if anything was actually reconfigured
*/
if (renegotiate) {
- /*
+ /*
* Now we force the SSL renegotation by sending the Hello Request
* message to the client. Here we have to do a workaround: Actually
- * SSLeay returns immediately after sending the Hello Request (the
+ * OpenSSL returns immediately after sending the Hello Request (the
* intent AFAIK is because the SSL/TLS protocol says it's not a must
* that the client replies to a Hello Request). But because we insist
* on a reply (anything else is an error for us) we have to go to the
@@ -762,33 +925,83 @@ int ssl_hook_Access(request_rec *r)
* state explicitly and continue the handshake manually.
*/
ssl_log(r->server, SSL_LOG_INFO, "Requesting connection re-negotiation");
- SSL_renegotiate(ssl);
- SSL_do_handshake(ssl);
- if (SSL_get_state(ssl) != SSL_ST_OK) {
- ssl_log(r->server, SSL_LOG_ERROR, "Re-negotation request failed");
- return FORBIDDEN;
+ if (renegotiate_quick) {
+ /* perform just a manual re-verification of the peer */
+ ssl_log(r->server, SSL_LOG_TRACE,
+ "Performing quick renegotiation: just re-verifying the peer");
+ certstore = SSL_CTX_get_cert_store(ctx);
+ if (certstore == NULL) {
+ ssl_log(r->server, SSL_LOG_ERROR, "Cannot find certificate storage");
+ return FORBIDDEN;
+ }
+ certstack = SSL_get_peer_cert_chain(ssl);
+ if (certstack == NULL || sk_X509_num(certstack) == 0) {
+ ssl_log(r->server, SSL_LOG_ERROR, "Cannot find peer certificate chain");
+ return FORBIDDEN;
+ }
+ cert = sk_X509_value(certstack, 0);
+ X509_STORE_CTX_init(&certstorectx, certstore, cert, certstack);
+ depth = SSL_get_verify_depth(ssl);
+ if (depth >= 0)
+ X509_STORE_CTX_set_depth(&certstorectx, depth);
+ X509_STORE_CTX_set_ex_data(&certstorectx,
+ SSL_get_ex_data_X509_STORE_CTX_idx(), (char *)ssl);
+ if (!X509_verify_cert(&certstorectx))
+ ssl_log(r->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
+ "Re-negotiation verification step failed");
+ SSL_set_verify_result(ssl, certstorectx.error);
+ X509_STORE_CTX_cleanup(&certstorectx);
}
- ssl_log(r->server, SSL_LOG_INFO, "Awaiting re-negotiation handshake");
- SSL_set_state(ssl, SSL_ST_ACCEPT);
- SSL_do_handshake(ssl);
- if (SSL_get_state(ssl) != SSL_ST_OK) {
- ssl_log(r->server, SSL_LOG_ERROR,
- "Re-negotiation handshake failed: Not accepted by client!?");
- return FORBIDDEN;
+ else {
+ /* do a full renegotiation */
+ ssl_log(r->server, SSL_LOG_TRACE,
+ "Performing full renegotiation: complete handshake protocol");
+ if (r->main != NULL)
+ SSL_set_session_id_context(ssl, (unsigned char *)&(r->main), sizeof(r->main));
+ else
+ SSL_set_session_id_context(ssl, (unsigned char *)&r, sizeof(r));
+#ifdef SSL_EXPERIMENTAL
+ ssl_io_suck(r, ssl);
+#endif
+ SSL_renegotiate(ssl);
+ SSL_do_handshake(ssl);
+ if (SSL_get_state(ssl) != SSL_ST_OK) {
+ ssl_log(r->server, SSL_LOG_ERROR, "Re-negotiation request failed");
+ return FORBIDDEN;
+ }
+ ssl_log(r->server, SSL_LOG_INFO, "Awaiting re-negotiation handshake");
+ SSL_set_state(ssl, SSL_ST_ACCEPT);
+ SSL_do_handshake(ssl);
+ if (SSL_get_state(ssl) != SSL_ST_OK) {
+ ssl_log(r->server, SSL_LOG_ERROR,
+ "Re-negotiation handshake failed: Not accepted by client!?");
+ return FORBIDDEN;
+ }
+ }
+
+ /*
+ * Remember the peer certificate's DN
+ */
+ if ((cert = SSL_get_peer_certificate(ssl)) != NULL) {
+ cp = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
+ ap_ctx_set(r->connection->client->ctx, "ssl::client::dn",
+ ap_pstrdup(r->connection->pool, cp));
+ free(cp);
}
/*
* Finally check for acceptable renegotiation results
*/
if (dc->nVerifyClient != SSL_CVERIFY_NONE) {
- if (SSL_get_verify_result(ssl) != X509_V_OK) {
- ssl_log(r->server, SSL_LOG_ERROR,
+ if ( dc->nVerifyClient == SSL_CVERIFY_REQUIRE
+ && SSL_get_verify_result(ssl) != X509_V_OK ) {
+ ssl_log(r->server, SSL_LOG_ERROR,
"Re-negotiation handshake failed: Client verification failed");
return FORBIDDEN;
}
- if ( dc->nVerifyClient == SSL_CVERIFY_REQUIRE
+ if ( dc->nVerifyClient == SSL_CVERIFY_REQUIRE
&& SSL_get_peer_certificate(ssl) == NULL ) {
- ssl_log(r->server, SSL_LOG_ERROR,
+ ssl_log(r->server, SSL_LOG_ERROR,
"Re-negotiation handshake failed: Client certificate missing");
return FORBIDDEN;
}
@@ -796,10 +1009,10 @@ int ssl_hook_Access(request_rec *r)
}
/*
- * Under old SSLeay we had to change the X509_STORE inside the SSL_CTX
- * instead inside the SSL structure, so we have to reconfigure it to the
- * old values. This should be changed with forthcoming OpenSSL version
- * when better functionality is avaiable.
+ * Under old OpenSSL we had to change the X509_STORE inside the
+ * SSL_CTX instead inside the SSL structure, so we have to reconfigure it
+ * to the old values. This should be changed with forthcoming OpenSSL
+ * versions when better functionality is avaiable.
*/
#ifdef SSL_EXPERIMENTAL
if (renegotiate && reconfigured_locations) {
@@ -817,7 +1030,7 @@ int ssl_hook_Access(request_rec *r)
* Check SSLRequire boolean expressions
*/
apRequirement = dc->aRequirement;
- pRequirements = (ssl_require_t *)apRequirement->elts;
+ pRequirements = (ssl_require_t *)apRequirement->elts;
for (i = 0; i < apRequirement->nelts; i++) {
pRequirement = &pRequirements[i];
ok = ssl_expr_exec(r, pRequirement->mpExpr);
@@ -825,6 +1038,8 @@ int ssl_hook_Access(request_rec *r)
cp = ap_psprintf(r->pool, "Failed to execute SSL requirement expression: %s",
ssl_expr_get_error());
ap_log_reason(cp, r->filename, r);
+ /* remember forbidden access for strict require option */
+ ap_table_setn(r->notes, "ssl-access-forbidden", (void *)1);
return FORBIDDEN;
}
if (ok != 1) {
@@ -835,14 +1050,97 @@ int ssl_hook_Access(request_rec *r)
"Failed expression: %s", pRequirement->cpExpr);
ap_log_reason("SSL requirement expression not fulfilled "
"(see SSL logfile for more details)", r->filename, r);
+ /* remember forbidden access for strict require option */
+ ap_table_setn(r->notes, "ssl-access-forbidden", (void *)1);
return FORBIDDEN;
}
}
/*
* Else access is granted...
+ * (except vendor handlers override)
*/
- return OK;
+ rc = OK;
+#ifdef SSL_VENDOR
+ ap_hook_use("ap::mod_ssl::vendor::access_handler",
+ AP_HOOK_SIG2(int,ptr), AP_HOOK_DECLINE(DECLINED),
+ &rc, r);
+#endif
+ return rc;
+}
+
+/*
+ * Auth Handler:
+ * Fake a Basic authentication from the X509 client certificate.
+ *
+ * This must be run fairly early on to prevent a real authentication from
+ * occuring, in particular it must be run before anything else that
+ * authenticates a user. This means that the Module statement for this
+ * module should be LAST in the Configuration file.
+ */
+int ssl_hook_Auth(request_rec *r)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(r->server);
+ SSLDirConfigRec *dc = myDirConfig(r);
+ char b1[MAX_STRING_LEN], b2[MAX_STRING_LEN];
+ char *clientdn;
+
+ /*
+ * Additionally forbid access (again)
+ * when strict require option is used.
+ */
+ if ( (dc->nOptions & SSL_OPT_STRICTREQUIRE)
+ && (ap_table_get(r->notes, "ssl-access-forbidden") != NULL))
+ return FORBIDDEN;
+
+ /*
+ * We decline operation in various situations...
+ */
+ if (!sc->bEnabled)
+ return DECLINED;
+ if (ap_ctx_get(r->connection->client->ctx, "ssl") == NULL)
+ return DECLINED;
+ if (!(dc->nOptions & SSL_OPT_FAKEBASICAUTH))
+ return DECLINED;
+ if (r->connection->user)
+ return DECLINED;
+ if ((clientdn = (char *)ap_ctx_get(r->connection->client->ctx, "ssl::client::dn")) == NULL)
+ return DECLINED;
+
+ /*
+ * Fake a password - which one would be immaterial, as, it seems, an empty
+ * password in the users file would match ALL incoming passwords, if only
+ * we were using the standard crypt library routine. Unfortunately, OpenSSL
+ * "fixes" a "bug" in crypt and thus prevents blank passwords from
+ * working. (IMHO what they really fix is a bug in the users of the code
+ * - failing to program correctly for shadow passwords). We need,
+ * therefore, to provide a password. This password can be matched by
+ * adding the string "xxj31ZMTZzkVA" as the password in the user file.
+ * This is just the crypted variant of the word "password" ;-)
+ */
+ ap_snprintf(b1, sizeof(b1), "%s:password", clientdn);
+ ssl_util_uuencode(b2, b1, FALSE);
+ ap_snprintf(b1, sizeof(b1), "Basic %s", b2);
+ ap_table_set(r->headers_in, "Authorization", b1);
+ ssl_log(r->server, SSL_LOG_INFO,
+ "Faking HTTP Basic Auth header: \"Authorization: %s\"", b1);
+
+ return DECLINED;
+}
+
+int ssl_hook_UserCheck(request_rec *r)
+{
+ SSLDirConfigRec *dc = myDirConfig(r);
+
+ /*
+ * Additionally forbid access (again)
+ * when strict require option is used.
+ */
+ if ( (dc->nOptions & SSL_OPT_STRICTREQUIRE)
+ && (ap_table_get(r->notes, "ssl-access-forbidden") != NULL))
+ return FORBIDDEN;
+
+ return DECLINED;
}
/*
@@ -901,6 +1199,7 @@ static const char *ssl_hook_Fixup_vars[] = {
"SSL_SERVER_I_DN_Email",
"SSL_SERVER_A_KEY",
"SSL_SERVER_A_SIG",
+ "SSL_SESSION_ID",
NULL
};
@@ -955,22 +1254,95 @@ int ssl_hook_Fixup(request_rec *r)
/* _________________________________________________________________
**
-** SSLeay Callback Functions
+** OpenSSL Callback Functions
** _________________________________________________________________
*/
/*
- * Handle out the already generated RSA key...
+ * Handle out temporary RSA private keys on demand
+ *
+ * The background of this as the TLSv1 standard explains it:
+ *
+ * | D.1. Temporary RSA keys
+ * |
+ * | US Export restrictions limit RSA keys used for encryption to 512
+ * | bits, but do not place any limit on lengths of RSA keys used for
+ * | signing operations. Certificates often need to be larger than 512
+ * | bits, since 512-bit RSA keys are not secure enough for high-value
+ * | transactions or for applications requiring long-term security. Some
+ * | certificates are also designated signing-only, in which case they
+ * | cannot be used for key exchange.
+ * |
+ * | When the public key in the certificate cannot be used for encryption,
+ * | the server signs a temporary RSA key, which is then exchanged. In
+ * | exportable applications, the temporary RSA key should be the maximum
+ * | allowable length (i.e., 512 bits). Because 512-bit RSA keys are
+ * | relatively insecure, they should be changed often. For typical
+ * | electronic commerce applications, it is suggested that keys be
+ * | changed daily or every 500 transactions, and more often if possible.
+ * | Note that while it is acceptable to use the same temporary key for
+ * | multiple transactions, it must be signed each time it is used.
+ * |
+ * | RSA key generation is a time-consuming process. In many cases, a
+ * | low-priority process can be assigned the task of key generation.
+ * | Whenever a new key is completed, the existing temporary key can be
+ * | replaced with the new one.
+ *
+ * So we generated 512 and 1024 bit temporary keys on startup
+ * which we now just handle out on demand....
+ *
*/
-RSA *ssl_callback_TmpRSA(SSL *pSSL, int nExport)
+RSA *ssl_callback_TmpRSA(SSL *pSSL, int nExport, int nKeyLen)
{
SSLModConfigRec *mc = myModConfig();
+ RSA *rsa;
+
+ rsa = NULL;
+ if (nExport) {
+ /* It's because an export cipher is used */
+ if (nKeyLen == 512)
+ rsa = mc->pRSATmpKey512;
+ else if (nKeyLen == 1024)
+ rsa = mc->pRSATmpKey1024;
+ else
+ /* it's too expensive to generate on-the-fly, so keep 1024bit */
+ rsa = mc->pRSATmpKey1024;
+ }
+ else {
+ /* It's because a sign-only certificate situation exists */
+ rsa = mc->pRSATmpKey1024;
+ }
+ return rsa;
+}
- return mc->pRSATmpKey;
+/*
+ * Handle out the already generated DH parameters...
+ */
+DH *ssl_callback_TmpDH(SSL *pSSL, int nExport, int nKeyLen)
+{
+ SSLModConfigRec *mc = myModConfig();
+ DH *dh;
+
+ dh = NULL;
+ if (nExport) {
+ /* It's because an export cipher is used */
+ if (nKeyLen == 512)
+ dh = mc->pDHTmpParam512;
+ else if (nKeyLen == 1024)
+ dh = mc->pDHTmpParam1024;
+ else
+ /* it's too expensive to generate on-the-fly, so keep 1024bit */
+ dh = mc->pDHTmpParam1024;
+ }
+ else {
+ /* It's because a sign-only certificate situation exists */
+ dh = mc->pDHTmpParam1024;
+ }
+ return dh;
}
/*
- * This SSLeay callback function is called when SSLeay
+ * This OpenSSL callback function is called when OpenSSL
* does client authentication and verifies the certificate chain.
*/
int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
@@ -981,19 +1353,22 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
request_rec *r;
SSLSrvConfigRec *sc;
SSLDirConfigRec *dc;
+ ap_ctx *actx;
X509 *xs;
int errnum;
int errdepth;
char *cp;
char *cp2;
int depth;
+ int verify;
/*
- * Get Apache context back through SSLeay context
+ * Get Apache context back through OpenSSL context
*/
ssl = (SSL *)X509_STORE_CTX_get_app_data(ctx);
conn = (conn_rec *)SSL_get_app_data(ssl);
- r = (request_rec *)SSL_get_app_data2(ssl);
+ actx = (ap_ctx *)SSL_get_app_data2(ssl);
+ r = (request_rec *)ap_ctx_get(actx, "ssl::request_rec");
s = conn->server;
sc = mySrvConfig(s);
dc = (r != NULL ? myDirConfig(r) : NULL);
@@ -1022,11 +1397,15 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
/*
* Check for optionally acceptable non-verifiable issuer situation
*/
+ if (dc != NULL && dc->nVerifyClient != SSL_CVERIFY_UNSET)
+ verify = dc->nVerifyClient;
+ else
+ verify = sc->nVerifyClient;
if ( ( errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
|| errnum == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
|| errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
|| errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE )
- && sc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA ) {
+ && verify == SSL_CVERIFY_OPTIONAL_NO_CA ) {
ssl_log(s, SSL_LOG_TRACE,
"Certificate Verification: Verifiable Issuer is configured as "
"optional, therefore we're accepting the certificate");
@@ -1034,6 +1413,14 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
}
/*
+ * Additionally perform CRL-based revocation checks
+ */
+ if (ok) {
+ ok = ssl_callback_SSLVerify_CRL(ok, ctx, s);
+ errnum = X509_STORE_CTX_get_error(ctx);
+ }
+
+ /*
* If we already know it's not ok, log the real reason
*/
if (!ok) {
@@ -1041,7 +1428,7 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
errnum, X509_verify_cert_error_string(errnum));
ap_ctx_set(conn->client->ctx, "ssl::client::dn", NULL);
ap_ctx_set(conn->client->ctx, "ssl::verify::error",
- X509_verify_cert_error_string(errnum));
+ (void *)X509_verify_cert_error_string(errnum));
}
/*
@@ -1049,27 +1436,191 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
*/
if (dc != NULL && dc->nVerifyDepth != UNSET)
depth = dc->nVerifyDepth;
- else
+ else
depth = sc->nVerifyDepth;
if (errdepth > depth) {
ssl_log(s, SSL_LOG_ERROR,
"Certificate Verification: Certificate Chain too long "
- "(chain has %d certificates, but maximum allowed are only %d)",
+ "(chain has %d certificates, but maximum allowed are only %d)",
errdepth, depth);
ap_ctx_set(conn->client->ctx, "ssl::verify::error",
- X509_verify_cert_error_string(X509_V_ERR_CERT_CHAIN_TOO_LONG));
+ (void *)X509_verify_cert_error_string(X509_V_ERR_CERT_CHAIN_TOO_LONG));
ok = FALSE;
}
/*
- * And finally signal SSLeay the (perhaps changed) state
+ * And finally signal OpenSSL the (perhaps changed) state
*/
return (ok);
}
+int ssl_callback_SSLVerify_CRL(
+ int ok, X509_STORE_CTX *ctx, server_rec *s)
+{
+ SSLSrvConfigRec *sc;
+ X509_OBJECT obj;
+ X509_NAME *subject;
+ X509_NAME *issuer;
+ X509 *xs;
+ X509_CRL *crl;
+ X509_REVOKED *revoked;
+ long serial;
+ BIO *bio;
+ int i, n, rc;
+ char *cp;
+ char *cp2;
+
+ /*
+ * Unless a revocation store for CRLs was created we
+ * cannot do any CRL-based verification, of course.
+ */
+ sc = mySrvConfig(s);
+ if (sc->pRevocationStore == NULL)
+ return ok;
+
+ /*
+ * Determine certificate ingredients in advance
+ */
+ xs = X509_STORE_CTX_get_current_cert(ctx);
+ subject = X509_get_subject_name(xs);
+ issuer = X509_get_issuer_name(xs);
+
+ /*
+ * OpenSSL provides the general mechanism to deal with CRLs but does not
+ * use them automatically when verifying certificates, so we do it
+ * explicitly here. We will check the CRL for the currently checked
+ * certificate, if there is such a CRL in the store.
+ *
+ * We come through this procedure for each certificate in the certificate
+ * chain, starting with the root-CA's certificate. At each step we've to
+ * both verify the signature on the CRL (to make sure it's a valid CRL)
+ * and it's revocation list (to make sure the current certificate isn't
+ * revoked). But because to check the signature on the CRL we need the
+ * public key of the issuing CA certificate (which was already processed
+ * one round before), we've a little problem. But we can both solve it and
+ * at the same time optimize the processing by using the following
+ * verification scheme (idea and code snippets borrowed from the GLOBUS
+ * project):
+ *
+ * 1. We'll check the signature of a CRL in each step when we find a CRL
+ * through the _subject_ name of the current certificate. This CRL
+ * itself will be needed the first time in the next round, of course.
+ * But we do the signature processing one round before this where the
+ * public key of the CA is available.
+ *
+ * 2. We'll check the revocation list of a CRL in each step when
+ * we find a CRL through the _issuer_ name of the current certificate.
+ * This CRLs signature was then already verified one round before.
+ *
+ * This verification scheme allows a CA to revoke its own certificate as
+ * well, of course.
+ */
+
+ /*
+ * Try to retrieve a CRL corresponding to the _subject_ of
+ * the current certificate in order to verify it's integrity.
+ */
+ memset((char *)&obj, 0, sizeof(obj));
+ rc = SSL_X509_STORE_lookup(sc->pRevocationStore, X509_LU_CRL, subject, &obj);
+ crl = obj.data.crl;
+ if (rc > 0 && crl != NULL) {
+ /*
+ * Log information about CRL
+ * (A little bit complicated because of ASN.1 and BIOs...)
+ */
+ if (ssl_log_applies(s, SSL_LOG_TRACE)) {
+ bio = BIO_new(BIO_s_mem());
+ BIO_printf(bio, "lastUpdate: ");
+ ASN1_UTCTIME_print(bio, X509_CRL_get_lastUpdate(crl));
+ BIO_printf(bio, ", nextUpdate: ");
+ ASN1_UTCTIME_print(bio, X509_CRL_get_nextUpdate(crl));
+ n = BIO_pending(bio);
+ cp = malloc(n+1);
+ n = BIO_read(bio, cp, n);
+ cp[n] = NUL;
+ BIO_free(bio);
+ cp2 = X509_NAME_oneline(subject, NULL, 0);
+ ssl_log(s, SSL_LOG_TRACE, "CA CRL: Issuer: %s, %s", cp2, cp);
+ free(cp2);
+ free(cp);
+ }
+
+ /*
+ * Verify the signature on this CRL
+ */
+ if (X509_CRL_verify(crl, X509_get_pubkey(xs)) <= 0) {
+ ssl_log(s, SSL_LOG_WARN, "Invalid signature on CRL");
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE);
+ X509_OBJECT_free_contents(&obj);
+ return FALSE;
+ }
+
+ /*
+ * Check date of CRL to make sure it's not expired
+ */
+ i = X509_cmp_current_time(X509_CRL_get_nextUpdate(crl));
+ if (i == 0) {
+ ssl_log(s, SSL_LOG_WARN, "Found CRL has invalid nextUpdate field");
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
+ X509_OBJECT_free_contents(&obj);
+ return FALSE;
+ }
+ if (i < 0) {
+ ssl_log(s, SSL_LOG_WARN,
+ "Found CRL is expired - "
+ "revoking all certificates until you get updated CRL");
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_HAS_EXPIRED);
+ X509_OBJECT_free_contents(&obj);
+ return FALSE;
+ }
+ X509_OBJECT_free_contents(&obj);
+ }
+
+ /*
+ * Try to retrieve a CRL corresponding to the _issuer_ of
+ * the current certificate in order to check for revocation.
+ */
+ memset((char *)&obj, 0, sizeof(obj));
+ rc = SSL_X509_STORE_lookup(sc->pRevocationStore, X509_LU_CRL, issuer, &obj);
+ crl = obj.data.crl;
+ if (rc > 0 && crl != NULL) {
+ /*
+ * Check if the current certificate is revoked by this CRL
+ */
+#if SSL_LIBRARY_VERSION < 0x00904000
+ n = sk_num(X509_CRL_get_REVOKED(crl));
+#else
+ n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
+#endif
+ for (i = 0; i < n; i++) {
+#if SSL_LIBRARY_VERSION < 0x00904000
+ revoked = (X509_REVOKED *)sk_value(X509_CRL_get_REVOKED(crl), i);
+#else
+ revoked = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
+#endif
+ if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(xs)) == 0) {
+
+ serial = ASN1_INTEGER_get(revoked->serialNumber);
+ cp = X509_NAME_oneline(issuer, NULL, 0);
+ ssl_log(s, SSL_LOG_INFO,
+ "Certificate with serial %ld (0x%lX) "
+ "revoked per CRL from issuer %s",
+ serial, serial, cp);
+ free(cp);
+
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED);
+ X509_OBJECT_free_contents(&obj);
+ return FALSE;
+ }
+ }
+ X509_OBJECT_free_contents(&obj);
+ }
+ return ok;
+}
+
/*
- * This callback function is executed by SSLeay whenever a new SSL_SESSION is
- * added to the internal SSLeay session cache. We use this hook to spread the
+ * This callback function is executed by OpenSSL whenever a new SSL_SESSION is
+ * added to the internal OpenSSL session cache. We use this hook to spread the
* SSL_SESSION also to the inter-process disk-cache to make share it with our
* other Apache pre-forked server processes.
*/
@@ -1079,16 +1630,17 @@ int ssl_callback_NewSessionCacheEntry(SSL *ssl, SSL_SESSION *pNew)
server_rec *s;
SSLSrvConfigRec *sc;
long t;
+ BOOL rc;
/*
- * Get Apache context back through SSLeay context
+ * Get Apache context back through OpenSSL context
*/
conn = (conn_rec *)SSL_get_app_data(ssl);
s = conn->server;
sc = mySrvConfig(s);
/*
- * Set the timeout also for the internal SSLeay cache, because this way
+ * Set the timeout also for the internal OpenSSL cache, because this way
* our inter-process cache is consulted only when it's really necessary.
*/
t = (SSL_get_time(pNew) + sc->nSessionCacheTimeout);
@@ -1098,26 +1650,27 @@ int ssl_callback_NewSessionCacheEntry(SSL *ssl, SSL_SESSION *pNew)
* Store the SSL_SESSION in the inter-process cache with the
* same expire time, so it expires automatically there, too.
*/
- ssl_scache_store(s, pNew, t);
+ rc = ssl_scache_store(s, pNew, t);
/*
* Log this cache operation
*/
ssl_log(s, SSL_LOG_TRACE, "Inter-Process Session Cache: "
- "request=SET id=%s timeout=%ds (session caching)",
+ "request=SET status=%s id=%s timeout=%ds (session caching)",
+ rc == TRUE ? "OK" : "BAD",
ssl_scache_id2sz(pNew->session_id, pNew->session_id_length),
t-time(NULL));
/*
- * return 0 which means to SSLeay that the pNew is still
+ * return 0 which means to OpenSSL that the pNew is still
* valid and was not freed by us with SSL_SESSION_free().
*/
return 0;
}
/*
- * This callback function is executed by SSLeay whenever a
- * SSL_SESSION is looked up in the internal SSLeay cache and it
+ * This callback function is executed by OpenSSL whenever a
+ * SSL_SESSION is looked up in the internal OpenSSL cache and it
* was not found. We use this to lookup the SSL_SESSION in the
* inter-process disk-cache where it was perhaps stored by one
* of our other Apache pre-forked server processes.
@@ -1130,7 +1683,7 @@ SSL_SESSION *ssl_callback_GetSessionCacheEntry(
SSL_SESSION *pSession;
/*
- * Get Apache context back through SSLeay context
+ * Get Apache context back through OpenSSL context
*/
conn = (conn_rec *)SSL_get_app_data(ssl);
s = conn->server;
@@ -1163,8 +1716,8 @@ SSL_SESSION *ssl_callback_GetSessionCacheEntry(
}
/*
- * This callback function is executed by SSLeay whenever a
- * SSL_SESSION is removed from the the internal SSLeay cache.
+ * This callback function is executed by OpenSSL whenever a
+ * SSL_SESSION is removed from the the internal OpenSSL cache.
* We use this to remove the SSL_SESSION in the inter-process
* disk-cache, too.
*/
@@ -1174,9 +1727,11 @@ void ssl_callback_DelSessionCacheEntry(
server_rec *s;
/*
- * Get Apache context back through SSLeay context
+ * Get Apache context back through OpenSSL context
*/
s = (server_rec *)SSL_CTX_get_app_data(ctx);
+ if (s == NULL) /* on server shutdown Apache is already gone */
+ return;
/*
* Remove the SSL_SESSION from the inter-process cache
@@ -1195,9 +1750,9 @@ void ssl_callback_DelSessionCacheEntry(
}
/*
- * This callback function is executed while SSLeay processes the
+ * This callback function is executed while OpenSSL processes the
* SSL handshake and does SSL record layer stuff. We use it to
- * trace SSLeay's processing in out SSL logfile.
+ * trace OpenSSL's processing in out SSL logfile.
*/
void ssl_callback_LogTracingState(SSL *ssl, int where, int rc)
{
@@ -1224,26 +1779,27 @@ void ssl_callback_LogTracingState(SSL *ssl, int where, int rc)
else if (where & SSL_CB_HANDSHAKE_DONE)
ssl_log(s, SSL_LOG_TRACE, "%s: Handshake: done", SSL_LIBRARY_NAME);
else if (where & SSL_CB_LOOP)
- ssl_log(s, SSL_LOG_TRACE, "%s: Loop: %s",
+ ssl_log(s, SSL_LOG_TRACE, "%s: Loop: %s",
SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
else if (where & SSL_CB_READ)
ssl_log(s, SSL_LOG_TRACE, "%s: Read: %s",
SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
else if (where & SSL_CB_WRITE)
- ssl_log(s, SSL_LOG_TRACE, "%s: Write: %s",
+ ssl_log(s, SSL_LOG_TRACE, "%s: Write: %s",
SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
else if (where & SSL_CB_ALERT) {
str = (where & SSL_CB_READ) ? "read" : "write";
- ssl_log(s, SSL_LOG_TRACE, "%s: Alert: %s:%s\n", SSL_LIBRARY_NAME,
+ ssl_log(s, SSL_LOG_TRACE, "%s: Alert: %s:%s:%s\n",
+ SSL_LIBRARY_NAME, str,
SSL_alert_type_string_long(rc),
SSL_alert_desc_string_long(rc));
}
else if (where & SSL_CB_EXIT) {
if (rc == 0)
- ssl_log(s, SSL_LOG_TRACE, "%s: Exit: failed in %s",
+ ssl_log(s, SSL_LOG_TRACE, "%s: Exit: failed in %s",
SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
else if (rc < 0)
- ssl_log(s, SSL_LOG_TRACE, "%s: Exit: error in %s",
+ ssl_log(s, SSL_LOG_TRACE, "%s: Exit: error in %s",
SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
}
}
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_log.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_log.c
index b020fd6f865..7b57f399056 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_log.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_log.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_engine_log.c
** Logging Facility
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -74,13 +74,27 @@
/*
* Open the SSL logfile
*/
-void ssl_log_open(server_rec *s, pool *p)
+void ssl_log_open(server_rec *s_main, server_rec *s, pool *p)
{
char *szLogFile;
+ SSLSrvConfigRec *sc_main = mySrvConfig(s_main);
SSLSrvConfigRec *sc = mySrvConfig(s);
piped_log *pl;
- if (sc->szLogFile != NULL) {
+ /*
+ * Short-circuit for inherited logfiles in order to save
+ * filedescriptors in mass-vhost situation. Be careful, this works
+ * fine because the close happens implicitly by the pool facility.
+ */
+ if ( s != s_main
+ && sc_main->fileLogFile != NULL
+ && ( (sc->szLogFile == NULL)
+ || ( sc->szLogFile != NULL
+ && sc_main->szLogFile != NULL
+ && strEQ(sc->szLogFile, sc_main->szLogFile)))) {
+ sc->fileLogFile = sc_main->fileLogFile;
+ }
+ else if (sc->szLogFile != NULL) {
if (strEQ(sc->szLogFile, "/dev/null"))
return;
else if (sc->szLogFile[0] == '|') {
@@ -128,6 +142,7 @@ static struct {
{ "*SSL3_READ_BYTES:sslv3*alert*bad*certificate*", "Subject CN in certificate not server name!?" },
{ "*self signed certificate in certificate chain*", "Client certificate signed by CA not known to server?" },
{ "*peer did not return a certificate*", "No CAs known to server for verification?" },
+ { "*no shared cipher*", "Too restrictive SSLCipherSuite or using DSA server certificate?" },
{ NULL, NULL }
};
@@ -146,6 +161,20 @@ static char *ssl_log_annotation(char *error)
return errstr;
}
+BOOL ssl_log_applies(server_rec *s, int level)
+{
+ SSLSrvConfigRec *sc;
+
+ sc = mySrvConfig(s);
+ if ( sc->fileLogFile == NULL
+ && !(level & SSL_LOG_ERROR))
+ return FALSE;
+ if ( level > sc->nLogLevel
+ && !(level & SSL_LOG_ERROR))
+ return FALSE;
+ return TRUE;
+}
+
void ssl_log(server_rec *s, int level, const char *msg, ...)
{
char tstr[80];
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_mutex.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_mutex.c
index 8d5a14132cc..266c797649b 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_mutex.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_mutex.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_engine_mutex.c
** Semaphore for Mutual Exclusion
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -75,18 +75,14 @@ void ssl_mutex_init(server_rec *s, pool *p)
{
SSLModConfigRec *mc = myModConfig();
- if (mc->nMutexMode == SSL_MUTEXMODE_FILE) {
+ if (mc->nMutexMode == SSL_MUTEXMODE_FILE)
ssl_mutex_file_create(s, p);
- ap_register_cleanup(p, (void *)s, ssl_mutex_file_remove, ap_null_cleanup);
- }
- else if (mc->nMutexMode == SSL_MUTEXMODE_SEM) {
+ else if (mc->nMutexMode == SSL_MUTEXMODE_SEM)
ssl_mutex_sem_create(s, p);
- ap_register_cleanup(p, (void *)s, ssl_mutex_sem_remove, ap_null_cleanup);
- }
return;
}
-void ssl_mutex_open(server_rec *s, pool *p)
+void ssl_mutex_reinit(server_rec *s, pool *p)
{
SSLModConfigRec *mc = myModConfig();
@@ -97,25 +93,42 @@ void ssl_mutex_open(server_rec *s, pool *p)
return;
}
-void ssl_mutex_on(void)
+void ssl_mutex_on(server_rec *s)
{
SSLModConfigRec *mc = myModConfig();
+ BOOL ok = TRUE;
if (mc->nMutexMode == SSL_MUTEXMODE_FILE)
- ssl_mutex_file_acquire();
+ ok = ssl_mutex_file_acquire();
else if (mc->nMutexMode == SSL_MUTEXMODE_SEM)
- ssl_mutex_sem_acquire();
+ ok = ssl_mutex_sem_acquire();
+ if (!ok)
+ ssl_log(s, SSL_LOG_WARN, "Failed to acquire global mutex lock");
return;
}
-void ssl_mutex_off(void)
+void ssl_mutex_off(server_rec *s)
{
SSLModConfigRec *mc = myModConfig();
+ BOOL ok = TRUE;
if (mc->nMutexMode == SSL_MUTEXMODE_FILE)
- ssl_mutex_file_release();
+ ok = ssl_mutex_file_release();
else if (mc->nMutexMode == SSL_MUTEXMODE_SEM)
- ssl_mutex_sem_release();
+ ok = ssl_mutex_sem_release();
+ if (!ok)
+ ssl_log(s, SSL_LOG_WARN, "Failed to release global mutex lock");
+ return;
+}
+
+void ssl_mutex_kill(server_rec *s)
+{
+ SSLModConfigRec *mc = myModConfig();
+
+ if (mc->nMutexMode == SSL_MUTEXMODE_FILE)
+ ssl_mutex_file_remove(s);
+ else if (mc->nMutexMode == SSL_MUTEXMODE_SEM)
+ ssl_mutex_sem_remove(s);
return;
}
@@ -140,9 +153,20 @@ void ssl_mutex_file_create(server_rec *s, pool *p)
mc->szMutexFile);
ssl_die();
}
+ ap_pclosef(p, mc->nMutexFD);
+
/* make sure the childs have access to this file */
if (geteuid() == 0 /* is superuser */)
chown(mc->szMutexFile, ap_user_id, -1 /* no gid change */);
+
+ /* open the lockfile for real */
+ if ((mc->nMutexFD = ap_popenf(p, mc->szMutexFile,
+ O_WRONLY, SSL_MUTEX_LOCK_MODE)) < 0) {
+ ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
+ "Parent could not open SSLMutex lockfile %s",
+ mc->szMutexFile);
+ ssl_die();
+ }
#endif
return;
}
@@ -154,7 +178,7 @@ void ssl_mutex_file_open(server_rec *s, pool *p)
/* open the lockfile (once per child) to get a unique fd */
if ((mc->nMutexFD = ap_popenf(p, mc->szMutexFile,
- O_WRONLY, SSL_MUTEX_LOCK_MODE)) < 0) {
+ O_WRONLY, SSL_MUTEX_LOCK_MODE)) < 0) {
ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
"Child could not open SSLMutex lockfile %s",
mc->szMutexFile);
@@ -312,7 +336,7 @@ BOOL ssl_mutex_sem_acquire(void)
rc = semop(mc->nMutexSEMID, sb, 2);
#endif
#ifdef SSL_HAVE_W32SEM
- rc = ap_acquire_mutex((mutex *)mc->nMutexSEMID);
+ rc = (ap_acquire_mutex((mutex *)mc->nMutexSEMID) == 0);
#endif
#endif
return rc;
@@ -326,7 +350,7 @@ BOOL ssl_mutex_sem_release(void)
#ifdef SSL_HAVE_IPCSEM
struct sembuf sb[] = {
- { 0, -1, SEM_UNDO } /* derements semaphore */
+ { 0, -1, SEM_UNDO } /* decrements semaphore */
};
rc = semop(mc->nMutexSEMID, sb, 1);
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_pphrase.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_pphrase.c
index f4caa4ad64d..11261aee565 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_pphrase.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_pphrase.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_engine_pphrase.c
** Pass Phrase Dialog
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -83,9 +83,9 @@ void ssl_pphrase_Handle(server_rec *s, pool *p)
server_rec *pServ;
char *cpVHostID;
char szPath[MAX_STRING_LEN];
+ EVP_PKEY *pPrivateKey;
ssl_asn1_t *asn1;
unsigned char *ucp;
- RSA *pRSAKey;
X509 *pX509Cert;
FILE *fp;
BOOL bReadable;
@@ -98,6 +98,10 @@ void ssl_pphrase_Handle(server_rec *s, pool *p)
int nPassPhraseDialogCur;
BOOL bPassPhraseDialogOnce;
char **cpp;
+ int i, j;
+ ssl_algo_t algoCert, algoKey, at;
+ char *an;
+ char *cp;
/*
* Start with a fresh pass phrase array
@@ -116,196 +120,245 @@ void ssl_pphrase_Handle(server_rec *s, pool *p)
continue;
cpVHostID = ssl_util_vhostid(p, pServ);
- ssl_log(pServ, SSL_LOG_INFO,
- "Init: Loading certificate & private key of SSL-aware server %s",
+ ssl_log(pServ, SSL_LOG_INFO,
+ "Init: Loading certificate & private key of SSL-aware server %s",
cpVHostID);
/*
- * Read in server certificate: This is the easy part
+ * Read in server certificate(s): This is the easy part
* because this file isn't encrypted in any way.
*/
- if (sc->szCertificateFile == NULL) {
+ if (sc->szPublicCertFile[0] == NULL) {
ssl_log(pServ, SSL_LOG_ERROR,
"Init: Server %s should be SSL-aware but has no certificate configured "
"[Hint: SSLCertifcateFile]", cpVHostID);
ssl_die();
}
- ap_cpystrn(szPath, sc->szCertificateFile, sizeof(szPath));
- if ((fp = ap_pfopen(p, szPath, "r")) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Init: Can't open server certificate file %s", szPath);
- ssl_die();
- }
- pX509Cert = X509_new();
- if (!PEM_read_X509(fp, &pX509Cert, NULL)) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: Unable to read server certificate from file %s", szPath);
- ssl_die();
- }
- ap_pfclose(p, fp);
+ algoCert = SSL_ALGO_UNKNOWN;
+ algoKey = SSL_ALGO_UNKNOWN;
+ for (i = 0, j = 0; i < SSL_AIDX_MAX && sc->szPublicCertFile[i] != NULL; i++) {
- /*
- * Insert the certificate into global module configuration to let it
- * survive the processing between the 1st Apache API init round (where
- * we operate here) and the 2nd Apache init round (where the
- * certificate is actually used to configure mod_ssl's per-server
- * configuration structures).
- */
- asn1 = (ssl_asn1_t *)ssl_ds_table_push(mc->tPublicCert, cpVHostID);
- asn1->nData = i2d_X509(pX509Cert, NULL);
- asn1->cpData = ap_palloc(mc->pPool, asn1->nData);
- ucp = asn1->cpData; i2d_X509(pX509Cert, &ucp); /* 2nd arg increments */
+ ap_cpystrn(szPath, sc->szPublicCertFile[i], sizeof(szPath));
+ if ((fp = ap_pfopen(p, szPath, "r")) == NULL) {
+ ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
+ "Init: Can't open server certificate file %s", szPath);
+ ssl_die();
+ }
+ if ((pX509Cert = SSL_read_X509(fp, NULL, NULL)) == NULL) {
+ ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
+ "Init: Unable to read server certificate from file %s", szPath);
+ ssl_die();
+ }
+ ap_pfclose(p, fp);
- /*
- * Free the X509 structure
- */
- X509_free(pX509Cert);
+ /*
+ * check algorithm type of certificate and make
+ * sure only one certificate per type is used.
+ */
+ at = ssl_util_algotypeof(pX509Cert, NULL);
+ an = ssl_util_algotypestr(at);
+ if (algoCert & at) {
+ ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
+ "Init: Multiple %s server certificates not allowed", an);
+ ssl_die();
+ }
+ algoCert |= at;
- /*
- * Read in the private key: This is the non-trivial part, because the
- * key is typically encrypted, so a pass phrase dialog has to be used
- * to request it from the user (or it has to be alternatively gathered
- * from a dialog program). The important point here is that ISPs
- * usually have hundrets of virtual servers configured and a lot of
- * them use SSL, so really we have to minimize the pass phrase
- * dialogs.
- *
- * The idea is this: When N virtual hosts are configured and all of
- * them use encrypted private keys with different pass phrases, we
- * have no chance and have to pop up N pass phrase dialogs. But
- * usually the admin is clever enough and uses the same pass phrase
- * for more private key files (typically he even uses one single pass
- * phrase for all). When this is the case we can minimize the dialogs
- * by trying to re-use already known/entered pass phrases.
- */
- if (sc->szKeyFile)
- ap_cpystrn(szPath, sc->szKeyFile, sizeof(szPath));
+ /*
+ * Insert the certificate into global module configuration to let it
+ * survive the processing between the 1st Apache API init round (where
+ * we operate here) and the 2nd Apache init round (where the
+ * certificate is actually used to configure mod_ssl's per-server
+ * configuration structures).
+ */
+ cp = ap_psprintf(mc->pPool, "%s:%s", cpVHostID, an);
+ asn1 = (ssl_asn1_t *)ssl_ds_table_push(mc->tPublicCert, cp);
+ asn1->nData = i2d_X509(pX509Cert, NULL);
+ asn1->cpData = ap_palloc(mc->pPool, asn1->nData);
+ ucp = asn1->cpData; i2d_X509(pX509Cert, &ucp); /* 2nd arg increments */
- /*
- * Spread context variables for callback function
- */
- myCtxVarSet(mc, 1, pServ);
- myCtxVarSet(mc, 2, p);
- myCtxVarSet(mc, 3, aPassPhrase);
- myCtxVarSet(mc, 4, &nPassPhraseCur);
- myCtxVarSet(mc, 5, &cpPassPhraseCur);
- myCtxVarSet(mc, 6, cpVHostID);
- myCtxVarSet(mc, 7, &nPassPhraseDialog);
- myCtxVarSet(mc, 8, &nPassPhraseDialogCur);
- myCtxVarSet(mc, 9, &bPassPhraseDialogOnce);
-
- pRSAKey = RSA_new();
- nPassPhraseCur = 0;
- nPassPhraseRetry = 0;
- nPassPhraseDialogCur = 0;
- bPassPhraseDialogOnce = TRUE;
+ /*
+ * Free the X509 structure
+ */
+ X509_free(pX509Cert);
+
+ /*
+ * Read in the private key: This is the non-trivial part, because the
+ * key is typically encrypted, so a pass phrase dialog has to be used
+ * to request it from the user (or it has to be alternatively gathered
+ * from a dialog program). The important point here is that ISPs
+ * usually have hundrets of virtual servers configured and a lot of
+ * them use SSL, so really we have to minimize the pass phrase
+ * dialogs.
+ *
+ * The idea is this: When N virtual hosts are configured and all of
+ * them use encrypted private keys with different pass phrases, we
+ * have no chance and have to pop up N pass phrase dialogs. But
+ * usually the admin is clever enough and uses the same pass phrase
+ * for more private key files (typically he even uses one single pass
+ * phrase for all). When this is the case we can minimize the dialogs
+ * by trying to re-use already known/entered pass phrases.
+ */
+ if (sc->szPrivateKeyFile[j] != NULL)
+ ap_cpystrn(szPath, sc->szPrivateKeyFile[j++], sizeof(szPath));
- for (;;) {
/*
* Try to read the private key file with the help of
* the callback function which serves the pass
- * phrases to SSLeay
+ * phrases to OpenSSL
*/
- if ((fp = ap_pfopen(p, szPath, "r")) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Init: Can't open server private key file %s", szPath);
+ myCtxVarSet(mc, 1, pServ);
+ myCtxVarSet(mc, 2, p);
+ myCtxVarSet(mc, 3, aPassPhrase);
+ myCtxVarSet(mc, 4, &nPassPhraseCur);
+ myCtxVarSet(mc, 5, &cpPassPhraseCur);
+ myCtxVarSet(mc, 6, cpVHostID);
+ myCtxVarSet(mc, 7, &nPassPhraseDialog);
+ myCtxVarSet(mc, 8, &nPassPhraseDialogCur);
+ myCtxVarSet(mc, 9, &bPassPhraseDialogOnce);
+
+ nPassPhraseCur = 0;
+ nPassPhraseRetry = 0;
+ nPassPhraseDialogCur = 0;
+ bPassPhraseDialogOnce = TRUE;
+
+ pPrivateKey = NULL;
+
+ for (;;) {
+ /*
+ * Try to read the private key file with the help of
+ * the callback function which serves the pass
+ * phrases to OpenSSL
+ */
+ if ((fp = ap_pfopen(p, szPath, "r")) == NULL) {
+ ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
+ "Init: Can't open server private key file %s", szPath);
+ ssl_die();
+ }
+ cpPassPhraseCur = NULL;
+ bReadable = ((pPrivateKey = SSL_read_PrivateKey(fp, NULL,
+ ssl_pphrase_Handle_CB)) != NULL ? TRUE : FALSE);
+ ap_pfclose(p, fp);
+
+ /*
+ * when the private key file now was readable,
+ * it's fine and we go out of the loop
+ */
+ if (bReadable)
+ break;
+
+ /*
+ * when we have more remembered pass phrases
+ * try to reuse these first.
+ */
+ if (nPassPhraseCur < nPassPhrase) {
+ nPassPhraseCur++;
+ continue;
+ }
+
+ /*
+ * else it's not readable and we have no more
+ * remembered pass phrases. Then this has to mean
+ * that the callback function popped up the dialog
+ * but a wrong pass phrase was entered. We give the
+ * user (but not the dialog program) a few more
+ * chances...
+ */
+ if ( sc->nPassPhraseDialogType == SSL_PPTYPE_BUILTIN
+ && cpPassPhraseCur != NULL
+ && nPassPhraseRetry < BUILTIN_DIALOG_RETRIES ) {
+ fprintf(stdout, "Apache:mod_ssl:Error: Pass phrase incorrect "
+ "(%d more retr%s permitted).\n",
+ (BUILTIN_DIALOG_RETRIES-nPassPhraseRetry),
+ (BUILTIN_DIALOG_RETRIES-nPassPhraseRetry) == 1 ? "y" : "ies");
+ nPassPhraseRetry++;
+ if (nPassPhraseRetry > BUILTIN_DIALOG_BACKOFF)
+ sleep((nPassPhraseRetry-BUILTIN_DIALOG_BACKOFF)*5);
+ continue;
+ }
+
+ /*
+ * Ok, anything else now means a fatal error.
+ */
+ if (cpPassPhraseCur == NULL)
+ ssl_log(pServ, SSL_LOG_ERROR|SSL_ADD_SSLERR, "Init: Private key not found.");
+ if (sc->nPassPhraseDialogType == SSL_PPTYPE_BUILTIN) {
+ fprintf(stdout, "Apache:mod_ssl:Error: Private key not found.\n");
+ fprintf(stdout, "**Stopped\n");
+ }
+ else {
+ ssl_log(pServ, SSL_LOG_ERROR|SSL_ADD_SSLERR, "Init: Pass phrase incorrect.");
+ if (sc->nPassPhraseDialogType == SSL_PPTYPE_BUILTIN) {
+ fprintf(stdout, "Apache:mod_ssl:Error: Pass phrase incorrect.\n");
+ fprintf(stdout, "**Stopped\n");
+ }
+ }
ssl_die();
}
- cpPassPhraseCur = NULL;
- bReadable = (PEM_read_RSAPrivateKey(fp, &pRSAKey,
- ssl_pphrase_Handle_CB) ? TRUE : FALSE);
- ap_pfclose(p, fp);
- /*
- * when the private key file now was readable,
- * it's fine and we go out of the loop
- */
- if (bReadable)
- break;
+ if (pPrivateKey == NULL) {
+ ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
+ "Init: Unable to read server private key from file %s", szPath);
+ ssl_die();
+ }
/*
- * when we have more remembered pass phrases
- * try to reuse these first.
+ * check algorithm type of private key and make
+ * sure only one private key per type is used.
*/
- if (nPassPhraseCur < nPassPhrase) {
- nPassPhraseCur++;
- continue;
+ at = ssl_util_algotypeof(NULL, pPrivateKey);
+ an = ssl_util_algotypestr(at);
+ if (algoKey & at) {
+ ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
+ "Init: Multiple %s server private keys not allowed", an);
+ ssl_die();
}
+ algoKey |= at;
/*
- * else it's not readable and we have no more
- * remembered pass phrases. Then this has to mean
- * that the callback function popped up the dialog
- * but a wrong pass phrase was entered. We give the
- * user (but not the dialog program) a few more
- * chances...
+ * Log the type of reading
*/
- if ( sc->nPassPhraseDialogType == SSL_PPTYPE_BUILTIN
- && cpPassPhraseCur != NULL
- && nPassPhraseRetry < BUILTIN_DIALOG_RETRIES ) {
- fprintf(stdout, "Apache:mod_ssl:Error: Pass phrase incorrect "
- "(%d more retr%s permitted).\n",
- (BUILTIN_DIALOG_RETRIES-nPassPhraseRetry),
- (BUILTIN_DIALOG_RETRIES-nPassPhraseRetry) == 1 ? "y" : "ies");
- nPassPhraseRetry++;
- if (nPassPhraseRetry > BUILTIN_DIALOG_BACKOFF)
- sleep((nPassPhraseRetry-BUILTIN_DIALOG_BACKOFF)*5);
- continue;
+ if (nPassPhraseDialogCur == 0)
+ ssl_log(pServ, SSL_LOG_TRACE,
+ "Init: (%s) unencrypted %s private key - pass phrase not required",
+ cpVHostID, an);
+ else {
+ if (cpPassPhraseCur != NULL)
+ ssl_log(pServ, SSL_LOG_TRACE,
+ "Init: (%s) encrypted %s private key - pass phrase requested",
+ cpVHostID, an);
+ else
+ ssl_log(pServ, SSL_LOG_TRACE,
+ "Init: (%s) encrypted %s private key - pass phrase reused",
+ cpVHostID, an);
}
/*
- * Ok, anything else now means a fatal error.
+ * Ok, when we have one more pass phrase store it
*/
- if (sc->nPassPhraseDialogType == SSL_PPTYPE_BUILTIN) {
- fprintf(stdout, "Apache:mod_ssl:Error: Pass phrase incorrect.\n");
- fprintf(stdout, "**Stopped\n");
+ if (cpPassPhraseCur != NULL) {
+ cpp = (char **)ssl_ds_array_push(aPassPhrase);
+ *cpp = cpPassPhraseCur;
+ nPassPhrase++;
}
- ssl_log(pServ, SSL_LOG_ERROR, "Init: Pass phrase incorrect.");
- ssl_die();
- }
- /*
- * Log the type of reading
- */
- if (nPassPhraseDialogCur == 0)
- ssl_log(pServ, SSL_LOG_TRACE,
- "Init: (%s) unencrypted private key - pass phrase not required",
- cpVHostID);
- else {
- if (cpPassPhraseCur != NULL)
- ssl_log(pServ, SSL_LOG_TRACE,
- "Init: (%s) encrypted private key - pass phrase requested",
- cpVHostID);
- else
- ssl_log(pServ, SSL_LOG_TRACE,
- "Init: (%s) encrypted private key - pass phrase reused",
- cpVHostID);
- }
+ /*
+ * Insert private key into the global module configuration
+ * (we convert it to a stand-alone DER byte sequence
+ * because the SSL library uses static variables inside a
+ * RSA structure which do not survive DSO reloads!)
+ */
+ cp = ap_psprintf(mc->pPool, "%s:%s", cpVHostID, an);
+ asn1 = (ssl_asn1_t *)ssl_ds_table_push(mc->tPrivateKey, cp);
+ asn1->nData = i2d_PrivateKey(pPrivateKey, NULL);
+ asn1->cpData = ap_palloc(mc->pPool, asn1->nData);
+ ucp = asn1->cpData; i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */
- /*
- * Ok, when have one more pass phrase store it
- */
- if (cpPassPhraseCur != NULL) {
- cpp = (char **)ssl_ds_array_push(aPassPhrase);
- *cpp = cpPassPhraseCur;
- nPassPhrase++;
+ /*
+ * Free the private key structure
+ */
+ EVP_PKEY_free(pPrivateKey);
}
-
- /*
- * Insert private key into the global module configuration
- * (we convert it to a stand-alone DER byte sequence
- * because the SSL library uses static variables inside a
- * RSA structure which do not survive DSO reloads!)
- */
- asn1 = (ssl_asn1_t *)ssl_ds_table_push(mc->tPrivateKey, cpVHostID);
- asn1->nData = i2d_RSAPrivateKey(pRSAKey, NULL);
- asn1->cpData = ap_palloc(mc->pPool, asn1->nData);
- ucp = asn1->cpData; i2d_RSAPrivateKey(pRSAKey, &ucp); /* 2nd arg increments */
-
- /*
- * Free the RSA structure
- */
- RSA_free(pRSAKey);
}
/*
@@ -332,7 +385,7 @@ void ssl_pphrase_Handle(server_rec *s, pool *p)
return;
}
-int ssl_pphrase_Handle_CB(char *buf, int bufsize, int w)
+int ssl_pphrase_Handle_CB(char *buf, int bufsize, int ask_twice)
{
SSLModConfigRec *mc = myModConfig();
server_rec *s;
@@ -411,19 +464,19 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int w)
}
/*
- * Emulate the SSLeay internal pass phrase dialog
+ * Emulate the OpenSSL internal pass phrase dialog
* (see crypto/pem/pem_lib.c:def_callback() for details)
*/
prompt = "Enter pass phrase:";
for (;;) {
- if ((i = EVP_read_pw_string(buf, bufsize, prompt, w)) != 0) {
+ if ((i = EVP_read_pw_string(buf, bufsize, prompt, ask_twice)) != 0) {
PEMerr(PEM_F_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD);
memset(buf, 0, (unsigned int)bufsize);
return (-1);
}
len = strlen(buf);
- if (len < 4)
- fprintf(stderr, "Apache:mod_ssl:Error: Pass phrase too short (needs to be at least 4 chars).\n");
+ if (len < 1)
+ fprintf(stderr, "Apache:mod_ssl:Error: Pass phrase empty (needs to be at least 1 character).\n");
else
break;
}
@@ -457,7 +510,7 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int w)
*cppPassPhraseCur = ap_pstrdup(p, buf);
/*
- * And return it's length to SSLeay...
+ * And return it's length to OpenSSL...
*/
return (len);
}
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_rand.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_rand.c
index fe150c8fb45..4ae847f8865 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_rand.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_rand.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_engine_rand.c
** Random Number Generator Seeding
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -58,7 +58,7 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
- /* ``The generation of random
+ /* ``The generation of random
numbers is too important
to be left to chance.'' */
@@ -108,13 +108,14 @@ int ssl_rand_seed(server_rec *s, pool *p, ssl_rsctx_t nCtx)
/*
* seed in contents generated by an external program
*/
- if ((fp = ssl_util_ppopen(s, p, pRandSeed->cpPath)) == NULL)
+ if ((fp = ssl_util_ppopen(s, p, ap_psprintf(p, "%s %d",
+ pRandSeed->cpPath, pRandSeed->nBytes))) == NULL)
continue;
nDone += ssl_rand_feedfp(p, fp, pRandSeed->nBytes);
ssl_util_ppclose(s, p, fp);
}
else if (pRandSeed->nSrc == SSL_RSSRC_BUILTIN) {
- /*
+ /*
* seed in the current time (usually just 4 bytes)
*/
t = time(NULL);
@@ -130,7 +131,7 @@ int ssl_rand_seed(server_rec *s, pool *p, ssl_rsctx_t nCtx)
RAND_seed((unsigned char *)&pid, l);
nDone += l;
- /*
+ /*
* seed in an 1KB extract of the current scoreboard
*/
if (ap_scoreboard_image != NULL) {
@@ -174,10 +175,10 @@ static int ssl_rand_feedfp(pool *p, FILE *fp, int nReq)
}
static int ssl_rand_choosenum(int l, int h)
-{
+{
int i;
char buf[50];
-
+
srand((unsigned int)time(NULL));
ap_snprintf(buf, sizeof(buf), "%.0f",
(((double)(rand()%RAND_MAX)/RAND_MAX)*(h-l)));
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_scache.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_scache.c
index 4ba070ce386..768cc3edaa6 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_scache.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_scache.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_engine_scache.c
** Session Cache
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -73,7 +73,7 @@
*/
/*
- * FIXME: There is no define in SSLeay, but SSLeay uses 1024*10,
+ * FIXME: There is no define in OpenSSL, but OpenSSL uses 1024*10,
* so 1024*20 should be ok.
*/
#define MAX_SESSION_DER 1024*20
@@ -84,16 +84,41 @@ void ssl_scache_init(server_rec *s, pool *p)
if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
ssl_scache_dbm_init(s, p);
- ssl_scache_expire(s);
+ else if (mc->nSessionCacheMode == SSL_SCMODE_SHM)
+ ssl_scache_shm_init(s, p);
+ ssl_scache_expire(s, time(NULL));
+
+#ifdef SSL_VENDOR
+ ap_hook_use("ap::mod_ssl::vendor::scache_init",
+ AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, s, p);
+#endif
+
+ return;
+}
+
+void ssl_scache_kill(server_rec *s)
+{
+ SSLModConfigRec *mc = myModConfig();
+
+ if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
+ ssl_scache_dbm_kill(s);
+ else if (mc->nSessionCacheMode == SSL_SCMODE_SHM)
+ ssl_scache_shm_kill(s);
+
+#ifdef SSL_VENDOR
+ ap_hook_use("ap::mod_ssl::vendor::scache_kill",
+ AP_HOOK_SIG1(void), AP_HOOK_ALL);
+#endif
return;
}
-void ssl_scache_store(server_rec *s, SSL_SESSION *pSession, int timeout)
+BOOL ssl_scache_store(server_rec *s, SSL_SESSION *pSession, int timeout)
{
SSLModConfigRec *mc = myModConfig();
ssl_scinfo_t SCI;
UCHAR buf[MAX_SESSION_DER];
UCHAR *b;
+ BOOL rc = FALSE;
/* add the key */
SCI.ucaKey = pSession->session_id;
@@ -106,9 +131,19 @@ void ssl_scache_store(server_rec *s, SSL_SESSION *pSession, int timeout)
/* and store it... */
if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
- ssl_scache_dbm_store(s, &SCI);
+ rc = ssl_scache_dbm_store(s, &SCI);
+ else if (mc->nSessionCacheMode == SSL_SCMODE_SHM)
+ rc = ssl_scache_shm_store(s, &SCI);
- return;
+#ifdef SSL_VENDOR
+ ap_hook_use("ap::mod_ssl::vendor::scache_store",
+ AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, s, &SCI);
+#endif
+
+ /* allow the regular expiring to occur */
+ ssl_scache_expire(s, time(NULL));
+
+ return rc;
}
SSL_SESSION *ssl_scache_retrieve(server_rec *s, UCHAR *id, int idlen)
@@ -118,6 +153,12 @@ SSL_SESSION *ssl_scache_retrieve(server_rec *s, UCHAR *id, int idlen)
ssl_scinfo_t SCI;
time_t tNow;
+ /* determine current time */
+ tNow = time(NULL);
+
+ /* allow the regular expiring to occur */
+ ssl_scache_expire(s, tNow);
+
/* create cache query */
SCI.ucaKey = id;
SCI.nKey = idlen;
@@ -128,16 +169,28 @@ SSL_SESSION *ssl_scache_retrieve(server_rec *s, UCHAR *id, int idlen)
/* perform cache query */
if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
ssl_scache_dbm_retrieve(s, &SCI);
+ else if (mc->nSessionCacheMode == SSL_SCMODE_SHM)
+ ssl_scache_shm_retrieve(s, &SCI);
+
+#ifdef SSL_VENDOR
+ ap_hook_use("ap::mod_ssl::vendor::scache_retrieve",
+ AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, s, &SCI);
+#endif
/* return immediately if not found */
if (SCI.ucaData == NULL)
return NULL;
/* check for expire time */
- tNow = time(NULL);
if (SCI.tExpiresAt <= tNow) {
if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
ssl_scache_dbm_remove(s, &SCI);
+ else if (mc->nSessionCacheMode == SSL_SCMODE_SHM)
+ ssl_scache_shm_remove(s, &SCI);
+#ifdef SSL_VENDOR
+ ap_hook_use("ap::mod_ssl::vendor::scache_remove",
+ AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, s, &SCI);
+#endif
return NULL;
}
@@ -161,16 +214,55 @@ void ssl_scache_remove(server_rec *s, SSL_SESSION *pSession)
/* perform remove */
if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
ssl_scache_dbm_remove(s, &SCI);
+ else if (mc->nSessionCacheMode == SSL_SCMODE_SHM)
+ ssl_scache_shm_remove(s, &SCI);
+
+#ifdef SSL_VENDOR
+ ap_hook_use("ap::mod_ssl::vendor::scache_remove",
+ AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, s, &SCI);
+#endif
return;
}
-void ssl_scache_expire(server_rec *s)
+void ssl_scache_expire(server_rec *s, time_t now)
{
SSLModConfigRec *mc = myModConfig();
+ SSLSrvConfigRec *sc = mySrvConfig(s);
+ static time_t last = 0;
+ /*
+ * make sure the expiration for still not-accessed session
+ * cache entries is done only from time to time
+ */
+ if (now < last+sc->nSessionCacheTimeout)
+ return;
+ last = now;
+
+ /*
+ * Now perform the expiration
+ */
if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
- ssl_scache_dbm_expire(s);
+ ssl_scache_dbm_expire(s, now);
+ else if (mc->nSessionCacheMode == SSL_SCMODE_SHM)
+ ssl_scache_shm_expire(s, now);
+
+ return;
+}
+
+void ssl_scache_status(server_rec *s, pool *p, void (*func)(char *, void *), void *arg)
+{
+ SSLModConfigRec *mc = myModConfig();
+
+ /* allow the regular expiring to occur */
+ ssl_scache_expire(s, time(NULL));
+
+ if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
+ ssl_scache_dbm_status(s, p, func, arg);
+ else if (mc->nSessionCacheMode == SSL_SCMODE_SHM)
+ ssl_scache_shm_status(s, p, func, arg);
+ else
+ func("N.A.", arg);
return;
}
@@ -213,75 +305,113 @@ void ssl_scache_dbm_init(server_rec *s, pool *p)
* Open it once to create it and to make sure it
* _can_ be created.
*/
- ssl_mutex_on();
+ ssl_mutex_on(s);
if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile,
O_RDWR|O_CREAT, SSL_DBM_FILE_MODE)) == NULL) {
ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
"Cannot create SSLSessionCache DBM file `%s'",
mc->szSessionCacheDataFile);
- ssl_mutex_off();
+ ssl_mutex_off(s);
return;
}
ssl_dbm_close(dbm);
-#ifndef WIN32
+#if !defined(OS2) && !defined(WIN32)
/*
- * we have to make sure the Apache child processes
- * have access to the DBM file...
+ * We have to make sure the Apache child processes
+ * have access to the DBM file. But because there
+ * are brain-dead platforms where we cannot exactly
+ * determine the suffixes we try all possibilities.
*/
if (geteuid() == 0 /* is superuser */) {
- chown(mc->szSessionCacheDataFile,
- ap_user_id, -1 /* no gid change */);
- chown(ap_pstrcat(p, mc->szSessionCacheDataFile,
- SSL_DBM_FILE_SUFFIX_DIR, NULL),
- ap_user_id, -1 /* no gid change */);
- chown(ap_pstrcat(p, mc->szSessionCacheDataFile,
- SSL_DBM_FILE_SUFFIX_PAG, NULL),
- ap_user_id, -1 /* no gid change */);
+ chown(mc->szSessionCacheDataFile, ap_user_id, -1 /* no gid change */);
+ if (chown(ap_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_DIR, NULL),
+ ap_user_id, -1) == -1) {
+ if (chown(ap_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL),
+ ap_user_id, -1) == -1)
+ chown(ap_pstrcat(p, mc->szSessionCacheDataFile, ".dir", NULL),
+ ap_user_id, -1);
+ }
+ if (chown(ap_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_PAG, NULL),
+ ap_user_id, -1) == -1) {
+ if (chown(ap_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL),
+ ap_user_id, -1) == -1)
+ chown(ap_pstrcat(p, mc->szSessionCacheDataFile, ".pag", NULL),
+ ap_user_id, -1);
+ }
}
#endif
- ssl_mutex_off();
+ ssl_mutex_off(s);
return;
}
-void ssl_scache_dbm_store(server_rec *s, ssl_scinfo_t *SCI)
+void ssl_scache_dbm_kill(server_rec *s)
+{
+ SSLModConfigRec *mc = myModConfig();
+ pool *p;
+
+ if ((p = ap_make_sub_pool(NULL)) != NULL) {
+ /* the correct way */
+ unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_DIR, NULL));
+ unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_PAG, NULL));
+ /* the additional ways to be sure */
+ unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, ".dir", NULL));
+ unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, ".pag", NULL));
+ unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL));
+ unlink(mc->szSessionCacheDataFile);
+ ap_destroy_pool(p);
+ }
+ return;
+}
+
+BOOL ssl_scache_dbm_store(server_rec *s, ssl_scinfo_t *SCI)
{
SSLModConfigRec *mc = myModConfig();
DBM *dbm;
datum dbmkey;
datum dbmval;
+ /* be careful: do not try to store too much bytes in a DBM file! */
+#ifdef SSL_USE_SDBM
+ if ((SCI->nKey + SCI->nData) >= PAIRMAX)
+ return FALSE;
+#else
+ if ((SCI->nKey + SCI->nData) >= 1024)
+ return FALSE;
+#endif
+
/* create DBM key */
- dbmkey.dptr = SCI->ucaKey;
+ dbmkey.dptr = (char *)(SCI->ucaKey);
dbmkey.dsize = SCI->nKey;
/* create DBM value */
dbmval.dsize = sizeof(time_t)+SCI->nData;
- dbmval.dptr = (UCHAR *)malloc(dbmval.dsize);
+ dbmval.dptr = (char *)malloc(dbmval.dsize);
if (dbmval.dptr == NULL)
- return;
- memcpy(dbmval.dptr, &SCI->tExpiresAt, sizeof(time_t));
+ return FALSE;
+ memcpy((char *)dbmval.dptr, &SCI->tExpiresAt, sizeof(time_t));
memcpy((char *)dbmval.dptr+sizeof(time_t), SCI->ucaData, SCI->nData);
/* and store it to the DBM file */
- ssl_mutex_on();
+ ssl_mutex_on(s);
if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile,
O_RDWR, SSL_DBM_FILE_MODE)) == NULL) {
ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
"Cannot open SSLSessionCache DBM file `%s' for writing (store)",
mc->szSessionCacheDataFile);
- ssl_mutex_off();
- return;
+ free(dbmval.dptr);
+ ssl_mutex_off(s);
+ return FALSE;
}
ssl_dbm_store(dbm, dbmkey, dbmval, DBM_INSERT);
ssl_dbm_close(dbm);
- ssl_mutex_off();
+ ssl_mutex_off(s);
/* free temporary buffers */
free(dbmval.dptr);
- return;
+ return TRUE;
}
void ssl_scache_dbm_retrieve(server_rec *s, ssl_scinfo_t *SCI)
@@ -297,22 +427,22 @@ void ssl_scache_dbm_retrieve(server_rec *s, ssl_scinfo_t *SCI)
SCI->tExpiresAt = 0;
/* create DBM key and values */
- dbmkey.dptr = SCI->ucaKey;
+ dbmkey.dptr = (char *)(SCI->ucaKey);
dbmkey.dsize = SCI->nKey;
/* and fetch it from the DBM file */
- ssl_mutex_on();
+ ssl_mutex_on(s);
if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile,
O_RDONLY, SSL_DBM_FILE_MODE)) == NULL) {
ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
"Cannot open SSLSessionCache DBM file `%s' for reading (fetch)",
mc->szSessionCacheDataFile);
- ssl_mutex_off();
+ ssl_mutex_off(s);
return;
}
dbmval = ssl_dbm_fetch(dbm, dbmkey);
ssl_dbm_close(dbm);
- ssl_mutex_off();
+ ssl_mutex_off(s);
/* immediately return if not found */
if (dbmval.dptr == NULL || dbmval.dsize < sizeof(time_t))
@@ -338,71 +468,423 @@ void ssl_scache_dbm_remove(server_rec *s, ssl_scinfo_t *SCI)
datum dbmkey;
/* create DBM key and values */
- dbmkey.dptr = SCI->ucaKey;
+ dbmkey.dptr = (char *)(SCI->ucaKey);
dbmkey.dsize = SCI->nKey;
/* and delete it from the DBM file */
- ssl_mutex_on();
+ ssl_mutex_on(s);
if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile,
O_RDWR, SSL_DBM_FILE_MODE)) == NULL) {
ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
"Cannot open SSLSessionCache DBM file `%s' for writing (delete)",
mc->szSessionCacheDataFile);
- ssl_mutex_off();
+ ssl_mutex_off(s);
return;
}
ssl_dbm_delete(dbm, dbmkey);
ssl_dbm_close(dbm);
- ssl_mutex_off();
+ ssl_mutex_off(s);
return;
}
-void ssl_scache_dbm_expire(server_rec *s)
+void ssl_scache_dbm_expire(server_rec *s, time_t tNow)
{
SSLModConfigRec *mc = myModConfig();
- static int nExpireCalls = 0;
DBM *dbm;
datum dbmkey;
datum dbmval;
- time_t tNow;
+ pool *p;
time_t tExpiresAt;
+ int nElements = 0;
+ int nDeleted = 0;
+ int bDelete;
+ datum *keylist;
+ int keyidx;
+ int i;
/*
- * It's to expensive to expire allways,
- * so do it only from time to time...
+ * Here we have to be very carefully: Not all DBM libraries are
+ * smart enough to allow one to iterate over the elements and at the
+ * same time delete expired ones. Some of them get totally crazy
+ * while others have no problems. So we have to do it the slower but
+ * more safe way: we first iterate over all elements and remember
+ * those which have to be expired. Then in a second pass we delete
+ * all those expired elements. Additionally we reopen the DBM file
+ * to be really safe in state.
*/
- if (nExpireCalls++ < 100)
- return;
- else
- nExpireCalls = 0;
- ssl_mutex_on();
+#define KEYMAX 1024
+
+ ssl_mutex_on(s);
+ for (;;) {
+ /* allocate the key array in a memory sub pool */
+ if ((p = ap_make_sub_pool(NULL)) == NULL)
+ break;
+ if ((keylist = ap_palloc(p, sizeof(dbmkey)*KEYMAX)) == NULL) {
+ ap_destroy_pool(p);
+ break;
+ }
+
+ /* pass 1: scan DBM database */
+ keyidx = 0;
+ if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile,
+ O_RDWR, SSL_DBM_FILE_MODE)) == NULL) {
+ ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
+ "Cannot open SSLSessionCache DBM file `%s' for scanning",
+ mc->szSessionCacheDataFile);
+ ap_destroy_pool(p);
+ break;
+ }
+ dbmkey = ssl_dbm_firstkey(dbm);
+ while (dbmkey.dptr != NULL) {
+ nElements++;
+ bDelete = FALSE;
+ dbmval = ssl_dbm_fetch(dbm, dbmkey);
+ if (dbmval.dsize < sizeof(time_t) || dbmval.dptr == NULL)
+ bDelete = TRUE;
+ else {
+ memcpy(&tExpiresAt, dbmval.dptr, sizeof(time_t));
+ if (tExpiresAt >= tNow)
+ bDelete = TRUE;
+ }
+ if (bDelete) {
+ if ((keylist[keyidx].dptr = ap_palloc(p, dbmkey.dsize)) != NULL) {
+ memcpy(keylist[keyidx].dptr, dbmkey.dptr, dbmkey.dsize);
+ keylist[keyidx].dsize = dbmkey.dsize;
+ keyidx++;
+ if (keyidx == KEYMAX)
+ break;
+ }
+ }
+ dbmkey = ssl_dbm_nextkey(dbm);
+ }
+ ssl_dbm_close(dbm);
+
+ /* pass 2: delete expired elements */
+ if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile,
+ O_RDWR, SSL_DBM_FILE_MODE)) == NULL) {
+ ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
+ "Cannot re-open SSLSessionCache DBM file `%s' for expiring",
+ mc->szSessionCacheDataFile);
+ ap_destroy_pool(p);
+ break;
+ }
+ for (i = 0; i < keyidx; i++) {
+ ssl_dbm_delete(dbm, keylist[i]);
+ nDeleted++;
+ }
+ ssl_dbm_close(dbm);
+
+ /* destroy temporary pool */
+ ap_destroy_pool(p);
+
+ if (keyidx < KEYMAX)
+ break;
+ }
+ ssl_mutex_off(s);
+
+ ssl_log(s, SSL_LOG_TRACE, "Inter-Process Session Cache (DBM) Expiry: "
+ "old: %d, new: %d, removed: %d", nElements, nElements-nDeleted, nDeleted);
+ return;
+}
+
+void ssl_scache_dbm_status(server_rec *s, pool *p, void (*func)(char *, void *), void *arg)
+{
+ SSLModConfigRec *mc = myModConfig();
+ DBM *dbm;
+ datum dbmkey;
+ datum dbmval;
+ int nElem;
+ int nSize;
+ int nAverage;
+
+ nElem = 0;
+ nSize = 0;
+ ssl_mutex_on(s);
if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile,
- O_RDWR, SSL_DBM_FILE_MODE)) == NULL) {
+ O_RDONLY, SSL_DBM_FILE_MODE)) == NULL) {
ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Cannot open SSLSessionCache DBM file `%s' for expiring",
+ "Cannot open SSLSessionCache DBM file `%s' for status retrival",
mc->szSessionCacheDataFile);
- ssl_mutex_off();
+ ssl_mutex_off(s);
return;
}
- tNow = time(NULL);
dbmkey = ssl_dbm_firstkey(dbm);
for ( ; dbmkey.dptr != NULL; dbmkey = ssl_dbm_nextkey(dbm)) {
dbmval = ssl_dbm_fetch(dbm, dbmkey);
if (dbmval.dptr == NULL)
continue;
- if (dbmval.dsize < sizeof(time_t)) {
- ssl_dbm_delete(dbm, dbmkey);
- continue;
- }
- memcpy(&tExpiresAt, dbmval.dptr, sizeof(time_t));
- if (tExpiresAt >= tNow)
- ssl_dbm_delete(dbm, dbmkey);
+ nElem += 1;
+ nSize += dbmval.dsize;
}
ssl_dbm_close(dbm);
- ssl_mutex_off();
+ ssl_mutex_off(s);
+ if (nSize > 0 && nElem > 0)
+ nAverage = nSize / nElem;
+ else
+ nAverage = 0;
+ func(ap_psprintf(p, "cache type: <b>DBM</b>, maximum size: <b>unlimited</b><br>"), arg);
+ func(ap_psprintf(p, "current sessions: <b>%d</b>, current size: <b>%d</b> bytes<br>", nElem, nSize), arg);
+ func(ap_psprintf(p, "average session size: <b>%d</b> bytes<br>", nAverage), arg);
+ return;
+}
+
+/* _________________________________________________________________
+**
+** Session Cache Support (SHM)
+** _________________________________________________________________
+*/
+
+/*
+ * Wrapper functions for table library which resemble malloc(3) & Co
+ * but use the variants from the MM shared memory library.
+ */
+
+static void *ssl_scache_shm_malloc(size_t size)
+{
+ SSLModConfigRec *mc = myModConfig();
+ return ap_mm_malloc(mc->pSessionCacheDataMM, size);
+}
+
+static void *ssl_scache_shm_calloc(size_t number, size_t size)
+{
+ SSLModConfigRec *mc = myModConfig();
+ return ap_mm_calloc(mc->pSessionCacheDataMM, number, size);
+}
+
+static void *ssl_scache_shm_realloc(void *ptr, size_t size)
+{
+ SSLModConfigRec *mc = myModConfig();
+ return ap_mm_realloc(mc->pSessionCacheDataMM, ptr, size);
+}
+
+static void ssl_scache_shm_free(void *ptr)
+{
+ SSLModConfigRec *mc = myModConfig();
+ ap_mm_free(mc->pSessionCacheDataMM, ptr);
+ return;
+}
+
+/*
+ * Now the actual session cache implementation
+ * based on a hash table inside a shared memory segment.
+ */
+
+void ssl_scache_shm_init(server_rec *s, pool *p)
+{
+ SSLModConfigRec *mc = myModConfig();
+ AP_MM *mm;
+ table_t *ta;
+ int ta_errno;
+ int avail;
+ int n;
+
+ /*
+ * Create shared memory segment
+ */
+ if (mc->szSessionCacheDataFile == NULL) {
+ ssl_log(s, SSL_LOG_ERROR, "SSLSessionCache required");
+ ssl_die();
+ }
+ if ((mm = ap_mm_create(mc->nSessionCacheDataSize,
+ mc->szSessionCacheDataFile)) == NULL) {
+ ssl_log(s, SSL_LOG_ERROR,
+ "Cannot allocate shared memory: %s", ap_mm_error());
+ ssl_die();
+ }
+ mc->pSessionCacheDataMM = mm;
+
+ /*
+ * Make sure the childs have access to the underlaying files
+ */
+ ap_mm_permission(mm, SSL_MM_FILE_MODE, ap_user_id, -1);
+
+ /*
+ * Create hash table in shared memory segment
+ */
+ avail = ap_mm_available(mm);
+ n = (avail/2) / 1024;
+ n = n < 10 ? 10 : n;
+ if ((ta = table_alloc(n, &ta_errno,
+ ssl_scache_shm_malloc,
+ ssl_scache_shm_calloc,
+ ssl_scache_shm_realloc,
+ ssl_scache_shm_free )) == NULL) {
+ ssl_log(s, SSL_LOG_ERROR,
+ "Cannot allocate hash table in shared memory: %s",
+ table_strerror(ta_errno));
+ ssl_die();
+ }
+ table_attr(ta, TABLE_FLAG_AUTO_ADJUST|TABLE_FLAG_ADJUST_DOWN);
+ table_set_data_alignment(ta, sizeof(char *));
+ table_clear(ta);
+ mc->tSessionCacheDataTable = ta;
+
+ /*
+ * Log the done work
+ */
+ ssl_log(s, SSL_LOG_INFO,
+ "Init: Created hash-table (%d buckets) "
+ "in shared memory (%d bytes) for SSL session cache", n, avail);
+ return;
+}
+
+void ssl_scache_shm_kill(server_rec *s)
+{
+ SSLModConfigRec *mc = myModConfig();
+
+ if (mc->pSessionCacheDataMM != NULL) {
+ ap_mm_destroy(mc->pSessionCacheDataMM);
+ mc->pSessionCacheDataMM = NULL;
+ }
+ return;
+}
+
+BOOL ssl_scache_shm_store(server_rec *s, ssl_scinfo_t *SCI)
+{
+ SSLModConfigRec *mc = myModConfig();
+ void *vp;
+
+ ssl_mutex_on(s);
+ if (table_insert_kd(mc->tSessionCacheDataTable,
+ SCI->ucaKey, SCI->nKey,
+ NULL, sizeof(time_t)+SCI->nData,
+ NULL, &vp, 1) != TABLE_ERROR_NONE) {
+ ssl_mutex_off(s);
+ return FALSE;
+ }
+ memcpy(vp, &SCI->tExpiresAt, sizeof(time_t));
+ memcpy((char *)vp+sizeof(time_t), SCI->ucaData, SCI->nData);
+ ssl_mutex_off(s);
+ return TRUE;
+}
+
+void ssl_scache_shm_retrieve(server_rec *s, ssl_scinfo_t *SCI)
+{
+ SSLModConfigRec *mc = myModConfig();
+ void *vp;
+ int n;
+ /* initialize result */
+ SCI->ucaData = NULL;
+ SCI->nData = 0;
+ SCI->tExpiresAt = 0;
+
+ /* lookup key in table */
+ ssl_mutex_on(s);
+ if (table_retrieve(mc->tSessionCacheDataTable,
+ SCI->ucaKey, SCI->nKey,
+ &vp, &n) != TABLE_ERROR_NONE) {
+ ssl_mutex_off(s);
+ return;
+ }
+
+ /* copy over the information to the SCI */
+ SCI->nData = n-sizeof(time_t);
+ SCI->ucaData = (UCHAR *)malloc(SCI->nData);
+ if (SCI->ucaData == NULL) {
+ SCI->nData = 0;
+ ssl_mutex_off(s);
+ return;
+ }
+ memcpy(&SCI->tExpiresAt, vp, sizeof(time_t));
+ memcpy(SCI->ucaData, (char *)vp+sizeof(time_t), SCI->nData);
+ ssl_mutex_off(s);
+
+ return;
+}
+
+void ssl_scache_shm_remove(server_rec *s, ssl_scinfo_t *SCI)
+{
+ SSLModConfigRec *mc = myModConfig();
+
+ /* remove value under key in table */
+ ssl_mutex_on(s);
+ table_delete(mc->tSessionCacheDataTable,
+ SCI->ucaKey, SCI->nKey, NULL, NULL);
+ ssl_mutex_off(s);
+ return;
+}
+
+void ssl_scache_shm_expire(server_rec *s, time_t tNow)
+{
+ SSLModConfigRec *mc = myModConfig();
+ table_linear_t iterator;
+ time_t tExpiresAt;
+ void *vpKey;
+ void *vpKeyThis;
+ void *vpData;
+ int nKey;
+ int nKeyThis;
+ int nData;
+ int nElements = 0;
+ int nDeleted = 0;
+ int bDelete;
+ int rc;
+
+ ssl_mutex_on(s);
+ if (table_first_r(mc->tSessionCacheDataTable, &iterator,
+ &vpKey, &nKey, &vpData, &nData) == TABLE_ERROR_NONE) {
+ do {
+ bDelete = FALSE;
+ nElements++;
+ if (nData < sizeof(time_t) || vpData == NULL)
+ bDelete = TRUE;
+ else {
+ memcpy(&tExpiresAt, vpData, sizeof(time_t));
+ if (tExpiresAt >= tNow)
+ bDelete = TRUE;
+ }
+ vpKeyThis = vpKey;
+ nKeyThis = nKey;
+ rc = table_next_r(mc->tSessionCacheDataTable, &iterator,
+ &vpKey, &nKey, &vpData, &nData);
+ if (bDelete) {
+ table_delete(mc->tSessionCacheDataTable,
+ vpKeyThis, nKeyThis, NULL, NULL);
+ nDeleted++;
+ }
+ } while (rc == TABLE_ERROR_NONE);
+ }
+ ssl_mutex_off(s);
+ ssl_log(s, SSL_LOG_TRACE, "Inter-Process Session Cache (SHM) Expiry: "
+ "old: %d, new: %d, removed: %d", nElements, nElements-nDeleted, nDeleted);
+ return;
+}
+
+void ssl_scache_shm_status(server_rec *s, pool *p, void (*func)(char *, void *), void *arg)
+{
+ SSLModConfigRec *mc = myModConfig();
+ void *vpKey;
+ void *vpData;
+ int nKey;
+ int nData;
+ int nElem;
+ int nSize;
+ int nAverage;
+
+ nElem = 0;
+ nSize = 0;
+ ssl_mutex_on(s);
+ if (table_first(mc->tSessionCacheDataTable,
+ &vpKey, &nKey, &vpData, &nData) == TABLE_ERROR_NONE) {
+ do {
+ if (vpKey == NULL || vpData == NULL)
+ continue;
+ nElem += 1;
+ nSize += nData;
+ } while (table_next(mc->tSessionCacheDataTable,
+ &vpKey, &nKey, &vpData, &nData) == TABLE_ERROR_NONE);
+ }
+ ssl_mutex_off(s);
+ if (nSize > 0 && nElem > 0)
+ nAverage = nSize / nElem;
+ else
+ nAverage = 0;
+ func(ap_psprintf(p, "cache type: <b>SHM</b>, maximum size: <b>%d</b> bytes<br>", mc->nSessionCacheDataSize), arg);
+ func(ap_psprintf(p, "current sessions: <b>%d</b>, current size: <b>%d</b> bytes<br>", nElem, nSize), arg);
+ func(ap_psprintf(p, "average session size: <b>%d</b> bytes<br>", nAverage), arg);
return;
}
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_vars.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_vars.c
index ef54924d3e1..e0c2c817c89 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_vars.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_vars.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_engine_vars.c
** Variable Lookup Facility
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -77,7 +77,7 @@ static char *ssl_var_lookup_ssl_cert(pool *p, X509 *xs, char *var);
static char *ssl_var_lookup_ssl_cert_dn(pool *p, X509_NAME *xsname, char *var);
static char *ssl_var_lookup_ssl_cert_valid(pool *p, ASN1_UTCTIME *tm);
static char *ssl_var_lookup_ssl_cert_serial(pool *p, X509 *xs);
-static char *ssl_var_lookup_ssl_cert_chain(pool *p, STACK *sk, char *var);
+static char *ssl_var_lookup_ssl_cert_chain(pool *p, STACK_OF(X509) *sk, char *var);
static char *ssl_var_lookup_ssl_cert_PEM(pool *p, X509 *xs);
static char *ssl_var_lookup_ssl_cipher(pool *p, conn_rec *c, char *var);
static void ssl_var_lookup_ssl_cipher_bits(char *cipher, int *usekeysize, int *algkeysize);
@@ -145,7 +145,7 @@ char *ssl_var_lookup(pool *p, server_rec *s, conn_rec *c, request_rec *r, char *
else if (strcEQ(var, "THE_REQUEST"))
result = r->the_request;
else if (strcEQ(var, "REQUEST_METHOD"))
- result = r->method;
+ result = (char *)(r->method);
else if (strcEQ(var, "REQUEST_SCHEME"))
result = ap_http_method(r);
else if (strcEQ(var, "REQUEST_URI"))
@@ -279,33 +279,35 @@ static char *ssl_var_lookup_ssl(pool *p, conn_rec *c, char *var)
{
char *result;
X509 *xs;
- STACK *sk;
+ STACK_OF(X509) *sk;
SSL *ssl;
result = NULL;
+ ssl = ap_ctx_get(c->client->ctx, "ssl");
if (strlen(var) > 8 && strcEQn(var, "VERSION_", 8)) {
result = ssl_var_lookup_ssl_version(p, var+8);
}
- else if (strcEQ(var, "PROTOCOL")) {
- ssl = ap_ctx_get(c->client->ctx, "ssl");
+ else if (ssl != NULL && strcEQ(var, "PROTOCOL")) {
result = SSL_get_version(ssl);
}
- else if (strlen(var) >= 6 && strcEQn(var, "CIPHER", 6)) {
+ else if (ssl != NULL && strcEQ(var, "SESSION_ID")) {
+ SSL_SESSION *pSession = SSL_get_session(ssl);
+ result = ap_pstrdup(p, ssl_scache_id2sz(pSession->session_id,
+ pSession->session_id_length));
+ }
+ else if (ssl != NULL && strlen(var) >= 6 && strcEQn(var, "CIPHER", 6)) {
result = ssl_var_lookup_ssl_cipher(p, c, var+6);
}
- else if (strlen(var) > 18 && strcEQn(var, "CLIENT_CERT_CHAIN_", 18)) {
- ssl = ap_ctx_get(c->client->ctx, "ssl");
+ else if (ssl != NULL && strlen(var) > 18 && strcEQn(var, "CLIENT_CERT_CHAIN_", 18)) {
sk = SSL_get_peer_cert_chain(ssl);
result = ssl_var_lookup_ssl_cert_chain(p, sk, var+17);
}
- else if (strlen(var) > 7 && strcEQn(var, "CLIENT_", 7)) {
- ssl = ap_ctx_get(c->client->ctx, "ssl");
+ else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "CLIENT_", 7)) {
if ((xs = SSL_get_peer_certificate(ssl)) != NULL)
result = ssl_var_lookup_ssl_cert(p, xs, var+7);
}
- else if (strlen(var) > 7 && strcEQn(var, "SERVER_", 7)) {
- ssl = ap_ctx_get(c->client->ctx, "ssl");
+ else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "SERVER_", 7)) {
if ((xs = SSL_get_certificate(ssl)) != NULL)
result = ssl_var_lookup_ssl_cert(p, xs, var+7);
}
@@ -403,12 +405,15 @@ static char *ssl_var_lookup_ssl_cert_dn(pool *p, X509_NAME *xsname, char *var)
for (i = 0; ssl_var_lookup_ssl_cert_dn_rec[i].name != NULL; i++) {
if (strEQ(var, ssl_var_lookup_ssl_cert_dn_rec[i].name)) {
- for (j = 0; j < sk_num(xsname->entries); j++) {
- xsne = (X509_NAME_ENTRY *)sk_value(xsname->entries, j);
+ for (j = 0; j < sk_X509_NAME_ENTRY_num(xsname->entries); j++) {
+ xsne = sk_X509_NAME_ENTRY_value(xsname->entries, j);
n = OBJ_obj2nid(xsne->object);
if (n == ssl_var_lookup_ssl_cert_dn_rec[i].nid) {
result = ap_palloc(p, xsne->value->length+1);
ap_cpystrn(result, (char *)xsne->value->data, xsne->value->length+1);
+#ifdef CHARSET_EBCDIC
+ ascii2ebcdic(result, result, xsne->value->length);
+#endif /* CHARSET_EBCDIC */
result[xsne->value->length] = NUL;
break;
}
@@ -439,7 +444,7 @@ static char *ssl_var_lookup_ssl_cert_valid(pool *p, ASN1_UTCTIME *tm)
static char *ssl_var_lookup_ssl_cert_serial(pool *p, X509 *xs)
{
char *result;
- BIO* bio;
+ BIO *bio;
int n;
if ((bio = BIO_new(BIO_s_mem())) == NULL)
@@ -453,7 +458,7 @@ static char *ssl_var_lookup_ssl_cert_serial(pool *p, X509 *xs)
return result;
}
-static char *ssl_var_lookup_ssl_cert_chain(pool *p, STACK *sk, char *var)
+static char *ssl_var_lookup_ssl_cert_chain(pool *p, STACK_OF(X509) *sk, char *var)
{
char *result;
X509 *xs;
@@ -463,8 +468,8 @@ static char *ssl_var_lookup_ssl_cert_chain(pool *p, STACK *sk, char *var)
if (strspn(var, "0123456789") == strlen(var)) {
n = atoi(var);
- if (sk_num(sk) >= n) {
- xs = (X509 *)sk_value(sk, n);
+ if (sk_X509_num(sk) >= n) {
+ xs = sk_X509_value(sk, n);
result = ssl_var_lookup_ssl_cert_PEM(p, xs);
}
}
@@ -502,24 +507,24 @@ static char *ssl_var_lookup_ssl_cipher(pool *p, conn_rec *c, char *var)
if (strEQ(var, "")) {
ssl = ap_ctx_get(c->client->ctx, "ssl");
- result = SSL_get_cipher_name(ssl);
+ result = (char *)SSL_get_cipher_name(ssl);
}
else if (strcEQ(var, "_EXPORT")) {
ssl = ap_ctx_get(c->client->ctx, "ssl");
- cipher = SSL_get_cipher_name(ssl);
+ cipher = (char *)SSL_get_cipher_name(ssl);
ssl_var_lookup_ssl_cipher_bits(cipher, &usekeysize, &algkeysize);
result = (usekeysize < 56 ? "true" : "false");
}
else if (strcEQ(var, "_USEKEYSIZE")) {
ssl = ap_ctx_get(c->client->ctx, "ssl");
- cipher = SSL_get_cipher_name(ssl);
+ cipher = (char *)SSL_get_cipher_name(ssl);
ssl_var_lookup_ssl_cipher_bits(cipher, &usekeysize, &algkeysize);
result = ap_psprintf(p, "%d", usekeysize);
resdup = FALSE;
}
else if (strcEQ(var, "_ALGKEYSIZE")) {
ssl = ap_ctx_get(c->client->ctx, "ssl");
- cipher = SSL_get_cipher_name(ssl);
+ cipher = (char *)SSL_get_cipher_name(ssl);
ssl_var_lookup_ssl_cipher_bits(cipher, &usekeysize, &algkeysize);
result = ap_psprintf(p, "%d", algkeysize);
resdup = FALSE;
@@ -532,7 +537,7 @@ static char *ssl_var_lookup_ssl_cipher(pool *p, conn_rec *c, char *var)
/*
* This structure is used instead of SSL_get_cipher_bits() because
- * this SSLeay function has rounding problems, but we want the
+ * this OpenSSL function has rounding problems, but we want the
* correct sizes.
*/
static const struct {
@@ -540,6 +545,11 @@ static const struct {
int nUseKeySize;
int nAlgKeySize;
} ssl_var_lookup_ssl_cipher_bits_rec[] = {
+
+ { TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5 /*EXP1024-RC4-MD5*/, 56, 128 },
+ { TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 /*EXP1024-RC2-CBC-MD5*/,56, 128 },
+ { TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA /*EXP1024-DES-CBC-SHA*/,56, 56 },
+
{ SSL3_TXT_RSA_IDEA_128_SHA /*IDEA-CBC-SHA*/, 128, 128 },
{ SSL3_TXT_RSA_NULL_MD5 /*NULL-MD5*/, 0, 0 },
{ SSL3_TXT_RSA_NULL_SHA /*NULL-SHA*/, 0, 0 },
@@ -571,12 +581,14 @@ static const struct {
{ SSL3_TXT_FZA_DMS_NULL_SHA /*FZA-NULL-SHA*/, 0, 0 },
{ SSL3_TXT_FZA_DMS_FZA_SHA /*FZA-FZA-CBC-SHA*/, 0, 0 },
{ SSL3_TXT_FZA_DMS_RC4_SHA /*FZA-RC4-SHA*/, 128, 128 },
+
{ SSL2_TXT_DES_64_CFB64_WITH_MD5_1 /*DES-CFB-M1*/, 56, 56 },
{ SSL2_TXT_RC2_128_CBC_WITH_MD5 /*RC2-CBC-MD5*/, 128, 128 },
{ SSL2_TXT_DES_64_CBC_WITH_MD5 /*DES-CBC-MD5*/, 56, 56 },
{ SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5 /*DES-CBC3-MD5*/, 168, 168 },
{ SSL2_TXT_RC4_64_WITH_MD5 /*RC4-64-MD5*/, 64, 64 },
{ SSL2_TXT_NULL /*NULL*/, 0, 0 },
+
{ NULL, 0, 0 }
};
@@ -614,7 +626,7 @@ static char *ssl_var_lookup_ssl_version(pool *p, char *var)
result = ap_psprintf(p, "mod_ssl/%s", MOD_SSL_VERSION);
}
else if (strEQ(var, "LIBRARY")) {
- result = ap_pstrdup(p, SSLeay_version(SSLEAY_VERSION));
+ result = ap_pstrdup(p, SSL_LIBRARY_TEXT);
if ((cp = strchr(result, ' ')) != NULL) {
*cp = '/';
if ((cp2 = strchr(cp, ' ')) != NULL)
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_expr.c b/usr.sbin/httpd/src/modules/ssl/ssl_expr.c
index 0015ea09ad5..8601468dca8 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_expr.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_expr.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_expr.c
** Expression Handling
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_expr.h b/usr.sbin/httpd/src/modules/ssl/ssl_expr.h
index b6851971038..42c6cdde9fb 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_expr.h
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_expr.h
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_expr.h
** Expression Handling (Header)
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_expr_eval.c b/usr.sbin/httpd/src/modules/ssl/ssl_expr_eval.c
index 61e6f826ac5..8fd58a59768 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_expr_eval.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_expr_eval.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_expr_eval.c
** Expression Evaluation
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_expr_parse.c b/usr.sbin/httpd/src/modules/ssl/ssl_expr_parse.c
index cbc42253136..f6b45840879 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_expr_parse.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_expr_parse.c
@@ -1,5 +1,3 @@
-#ifndef lint
-#endif
#include <stdlib.h>
#define YYBYACC 1
#define YYMAJOR 1
@@ -9,19 +7,16 @@
#define ssl_expr_yyclearin (ssl_expr_yychar=(YYEMPTY))
#define ssl_expr_yyerrok (ssl_expr_yyerrflag=0)
#define YYRECOVERING (ssl_expr_yyerrflag!=0)
-#if defined(c_plusplus) || defined(__cplusplus)
-#include <stdlib.h>
-#else
-extern char *getenv();
-extern void *realloc();
-#endif
static int ssl_expr_yygrowstack();
#define YYPREFIX "ssl_expr_yy"
+#line 72 "ssl_expr_parse.y"
#include "mod_ssl.h"
+#line 75 "ssl_expr_parse.y"
typedef union {
char *cpVal;
ssl_expr *exVal;
} YYSTYPE;
+#line 29 "y.tab.c"
#define T_TRUE 257
#define T_FALSE 258
#define T_DIGIT 259
@@ -218,6 +213,7 @@ short *ssl_expr_yyss;
short *ssl_expr_yysslim;
YYSTYPE *ssl_expr_yyvs;
int ssl_expr_yystacksize;
+#line 180 "ssl_expr_parse.y"
int ssl_expr_yyerror(char *s)
{
@@ -225,6 +221,7 @@ int ssl_expr_yyerror(char *s)
return 2;
}
+#line 232 "y.tab.c"
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int ssl_expr_yygrowstack()
{
@@ -394,75 +391,99 @@ ssl_expr_yyreduce:
switch (ssl_expr_yyn)
{
case 1:
+#line 118 "ssl_expr_parse.y"
{ ssl_expr_info.expr = ssl_expr_yyvsp[0].exVal; }
break;
case 2:
+#line 121 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_True, NULL, NULL); }
break;
case 3:
+#line 122 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_False, NULL, NULL); }
break;
case 4:
+#line 123 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_Not, ssl_expr_yyvsp[0].exVal, NULL); }
break;
case 5:
+#line 124 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_Or, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
break;
case 6:
+#line 125 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_And, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
break;
case 7:
+#line 126 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_Comp, ssl_expr_yyvsp[0].exVal, NULL); }
break;
case 8:
+#line 127 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_yyvsp[-1].exVal; }
break;
case 9:
+#line 130 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_EQ, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
break;
case 10:
+#line 131 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_NE, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
break;
case 11:
+#line 132 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_LT, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
break;
case 12:
+#line 133 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_LE, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
break;
case 13:
+#line 134 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_GT, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
break;
case 14:
+#line 135 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_GE, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
break;
case 15:
+#line 136 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_IN, ssl_expr_yyvsp[-4].exVal, ssl_expr_yyvsp[-1].exVal); }
break;
case 16:
+#line 137 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_REG, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
break;
case 17:
+#line 138 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_NRE, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
break;
case 18:
+#line 141 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_ListElement, ssl_expr_yyvsp[0].exVal, NULL); }
break;
case 19:
+#line 142 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_ListElement, ssl_expr_yyvsp[0].exVal, ssl_expr_yyvsp[-2].exVal); }
break;
case 20:
+#line 145 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_Digit, ssl_expr_yyvsp[0].cpVal, NULL); }
break;
case 21:
+#line 146 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_String, ssl_expr_yyvsp[0].cpVal, NULL); }
break;
case 22:
+#line 147 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_make(op_Var, ssl_expr_yyvsp[-1].cpVal, NULL); }
break;
case 23:
+#line 148 "ssl_expr_parse.y"
{ ssl_expr_yyval.exVal = ssl_expr_yyvsp[0].exVal; }
break;
case 24:
+#line 151 "ssl_expr_parse.y"
{
regex_t *regex;
if ((regex = ap_pregcomp(ssl_expr_info.pool, ssl_expr_yyvsp[0].cpVal,
@@ -475,6 +496,7 @@ case 24:
}
break;
case 25:
+#line 161 "ssl_expr_parse.y"
{
regex_t *regex;
if ((regex = ap_pregcomp(ssl_expr_info.pool, ssl_expr_yyvsp[0].cpVal,
@@ -487,11 +509,13 @@ case 25:
}
break;
case 26:
+#line 173 "ssl_expr_parse.y"
{
ssl_expr *args = ssl_expr_make(op_ListElement, ssl_expr_yyvsp[-1].cpVal, NULL);
ssl_expr_yyval.exVal = ssl_expr_make(op_Func, "file", args);
}
break;
+#line 526 "y.tab.c"
}
ssl_expr_yyssp -= ssl_expr_yym;
ssl_expr_yystate = *ssl_expr_yyssp;
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_expr_parse.y b/usr.sbin/httpd/src/modules/ssl/ssl_expr_parse.y
index cc4590ad824..f1819f46d8e 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_expr_parse.y
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_expr_parse.y
@@ -1,8 +1,8 @@
/* _ _
** _ __ ___ ___ __| | ___ ___| |
** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to OpenSSL
+** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.modssl.org/
** |_____|
** ssl_expr_parse.y
** Expression LR(1) Parser
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_expr_scan.c b/usr.sbin/httpd/src/modules/ssl/ssl_expr_scan.c
new file mode 100644
index 00000000000..6d422fdfaa7
--- /dev/null
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_expr_scan.c
@@ -0,0 +1,2002 @@
+#define yy_create_buffer ssl_expr_yy_create_buffer
+#define yy_delete_buffer ssl_expr_yy_delete_buffer
+#define yy_scan_buffer ssl_expr_yy_scan_buffer
+#define yy_scan_string ssl_expr_yy_scan_string
+#define yy_scan_bytes ssl_expr_yy_scan_bytes
+#define yy_flex_debug ssl_expr_yy_flex_debug
+#define yy_init_buffer ssl_expr_yy_init_buffer
+#define yy_flush_buffer ssl_expr_yy_flush_buffer
+#define yy_load_buffer_state ssl_expr_yy_load_buffer_state
+#define yy_switch_to_buffer ssl_expr_yy_switch_to_buffer
+#define yyin ssl_expr_yyin
+#define yyleng ssl_expr_yyleng
+#define yylex ssl_expr_yylex
+#define yyout ssl_expr_yyout
+#define yyrestart ssl_expr_yyrestart
+#define yytext ssl_expr_yytext
+
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator). This
+ * avoids problems with code like:
+ *
+ * if ( condition_holds )
+ * yyless( 5 );
+ * else
+ * do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ *yy_cp = yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+ };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+
+#define yywrap() 1
+#define YY_SKIP_YYWRAP
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yytext_ptr = yy_bp; \
+ yyleng = (int) (yy_cp - yy_bp); \
+ yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 46
+#define YY_END_OF_BUFFER 47
+static yyconst short int yy_accept[86] =
+ { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 47, 45,
+ 1, 38, 2, 45, 43, 24, 45, 28, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 45,
+ 13, 4, 3, 14, 16, 18, 17, 1, 22, 32,
+ 34, 43, 26, 20, 31, 30, 44, 44, 19, 44,
+ 44, 29, 27, 39, 25, 23, 15, 15, 21, 44,
+ 35, 44, 36, 13, 12, 5, 6, 10, 11, 7,
+ 8, 9, 33, 44, 44, 37, 44, 5, 6, 44,
+ 40, 41, 5, 42, 0
+ } ;
+
+static yyconst int yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 4, 5, 1, 1, 1, 6, 1, 1,
+ 1, 1, 1, 1, 7, 1, 1, 8, 8, 8,
+ 8, 8, 8, 8, 8, 9, 9, 1, 1, 10,
+ 11, 12, 1, 1, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 1, 14, 1, 1, 7, 1, 15, 16, 13, 17,
+
+ 18, 19, 20, 13, 21, 13, 13, 22, 23, 24,
+ 25, 13, 26, 27, 28, 29, 30, 13, 13, 13,
+ 13, 13, 1, 31, 1, 32, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst int yy_meta[33] =
+ { 0,
+ 1, 1, 2, 1, 3, 1, 4, 4, 4, 1,
+ 1, 1, 4, 3, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 1, 1
+ } ;
+
+static yyconst short int yy_base[93] =
+ { 0,
+ 0, 0, 30, 31, 0, 0, 82, 81, 101, 142,
+ 35, 28, 142, 94, 32, 88, 31, 87, 0, 69,
+ 66, 28, 28, 67, 29, 63, 30, 63, 62, 57,
+ 0, 142, 142, 88, 142, 142, 142, 48, 142, 142,
+ 142, 44, 142, 142, 142, 142, 0, 70, 0, 64,
+ 63, 0, 0, 0, 0, 0, 142, 0, 0, 55,
+ 0, 46, 142, 0, 142, 53, 62, 142, 142, 142,
+ 142, 142, 0, 44, 48, 0, 41, 70, 72, 38,
+ 0, 0, 74, 0, 142, 117, 121, 125, 50, 129,
+ 133, 137
+
+ } ;
+
+static yyconst short int yy_def[93] =
+ { 0,
+ 85, 1, 86, 86, 87, 87, 88, 88, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 89, 89,
+ 89, 89, 89, 89, 89, 90, 89, 89, 89, 85,
+ 91, 85, 85, 92, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 89, 89, 89, 89,
+ 89, 89, 89, 89, 89, 89, 85, 89, 89, 89,
+ 89, 89, 85, 91, 85, 85, 85, 85, 85, 85,
+ 85, 85, 89, 89, 89, 89, 89, 85, 85, 89,
+ 89, 89, 85, 89, 0, 85, 85, 85, 85, 85,
+ 85, 85
+
+ } ;
+
+static yyconst short int yy_nxt[175] =
+ { 0,
+ 10, 11, 11, 12, 13, 14, 10, 15, 15, 16,
+ 17, 18, 19, 10, 20, 19, 19, 21, 22, 23,
+ 24, 25, 26, 27, 28, 19, 19, 19, 29, 19,
+ 30, 10, 32, 32, 33, 33, 38, 38, 39, 42,
+ 42, 44, 50, 34, 34, 52, 55, 59, 51, 38,
+ 38, 42, 42, 47, 60, 84, 53, 56, 82, 40,
+ 78, 79, 45, 57, 57, 81, 57, 57, 57, 79,
+ 79, 80, 57, 57, 57, 77, 57, 83, 79, 79,
+ 79, 79, 79, 76, 75, 74, 73, 63, 62, 61,
+ 54, 49, 48, 57, 57, 66, 67, 46, 43, 41,
+
+ 85, 37, 37, 68, 85, 85, 69, 85, 85, 85,
+ 85, 70, 85, 85, 71, 85, 72, 31, 31, 31,
+ 31, 35, 35, 35, 35, 36, 36, 36, 36, 58,
+ 85, 58, 58, 64, 85, 85, 64, 65, 65, 65,
+ 65, 9, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85
+ } ;
+
+static yyconst short int yy_chk[175] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 3, 4, 3, 4, 11, 11, 12, 15,
+ 15, 17, 22, 3, 4, 23, 25, 27, 22, 38,
+ 38, 42, 42, 89, 27, 80, 23, 25, 77, 12,
+ 66, 66, 17, 26, 26, 75, 26, 26, 26, 67,
+ 67, 74, 26, 26, 26, 62, 26, 78, 78, 79,
+ 79, 83, 83, 60, 51, 50, 48, 30, 29, 28,
+ 24, 21, 20, 26, 26, 34, 34, 18, 16, 14,
+
+ 9, 8, 7, 34, 0, 0, 34, 0, 0, 0,
+ 0, 34, 0, 0, 34, 0, 34, 86, 86, 86,
+ 86, 87, 87, 87, 87, 88, 88, 88, 88, 90,
+ 0, 90, 90, 91, 0, 0, 91, 92, 92, 92,
+ 92, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85
+ } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "ssl_expr_scan.l"
+#define INITIAL 0
+/* _ _
+** _ __ ___ ___ __| | ___ ___| |
+** | '_ ` _ \ / _ \ / _` | / __/ __| |
+** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to OpenSSL
+** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.modssl.org/
+** |_____|
+** ssl_expr_scan.l
+** Expression Scanner
+*/
+/* ====================================================================
+ * Copyright (c) 1998-1999 Ralf S. Engelschall. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by
+ * Ralf S. Engelschall <rse@engelschall.com> for use in the
+ * mod_ssl project (http://www.modssl.org/)."
+ *
+ * 4. The names "mod_ssl" must not be used to endorse or promote
+ * products derived from this software without prior written
+ * permission. For written permission, please contact
+ * rse@engelschall.com.
+ *
+ * 5. Products derived from this software may not be called "mod_ssl"
+ * nor may "mod_ssl" appear in their names without prior
+ * written permission of Ralf S. Engelschall.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by
+ * Ralf S. Engelschall <rse@engelschall.com> for use in the
+ * mod_ssl project (http://www.modssl.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
+ * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+/* ``Killing for peace is
+like fucking for virginity.''
+-- Unknown */
+/* _________________________________________________________________
+**
+** Expression Scanner
+** _________________________________________________________________
+*/
+#line 73 "ssl_expr_scan.l"
+#include "mod_ssl.h"
+
+#include "ssl_expr_parse.h"
+
+#define YY_NO_UNPUT 1
+int yyinput(char *buf, int max_size);
+
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ (result = yyinput(buf, max_size))
+
+#define MAX_STR_LEN 2048
+/* %option stack */
+#define YY_NEVER_INTERACTIVE 1
+#define str 1
+
+#define regex 2
+#define regex_flags 3
+
+#line 537 "lex.ssl_expr_yy.c"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines. This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( yy_current_buffer->yy_is_interactive ) \
+ { \
+ int c = '*', n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+ && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+YY_DECL
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 94 "ssl_expr_scan.l"
+
+
+ char caStr[MAX_STR_LEN];
+ char *cpStr = NULL;
+ char caRegex[MAX_STR_LEN];
+ char *cpRegex = NULL;
+ char cRegexDel = NUL;
+
+ /*
+ * Whitespaces
+ */
+#line 700 "lex.ssl_expr_yy.c"
+
+ if ( yy_init )
+ {
+ yy_init = 0;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yy_start )
+ yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! yy_current_buffer )
+ yy_current_buffer =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_load_buffer_state();
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yy_start;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 86 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_current_state != 85 );
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+
+ YY_DO_BEFORE_ACTION;
+
+
+do_action: /* This label is used only to access EOF actions. */
+
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yy_hold_char;
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 105 "ssl_expr_scan.l"
+{
+ /* NOP */
+}
+ YY_BREAK
+/*
+ * C-style strings ("...")
+ */
+case 2:
+YY_RULE_SETUP
+#line 112 "ssl_expr_scan.l"
+{
+ cpStr = caStr;
+ BEGIN(str);
+}
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 116 "ssl_expr_scan.l"
+{
+ BEGIN(INITIAL);
+ *cpStr = NUL;
+ yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, caStr);
+ return T_STRING;
+}
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 122 "ssl_expr_scan.l"
+{
+ yyerror("Unterminated string");
+}
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 125 "ssl_expr_scan.l"
+{
+ int result;
+
+ (void)sscanf(yytext+1, "%o", &result);
+ if (result > 0xff)
+ yyerror("Escape sequence out of bound");
+ else
+ *cpStr++ = result;
+}
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 134 "ssl_expr_scan.l"
+{
+ yyerror("Bad escape sequence");
+}
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 137 "ssl_expr_scan.l"
+{ *cpStr++ = '\n'; }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 138 "ssl_expr_scan.l"
+{ *cpStr++ = '\r'; }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 139 "ssl_expr_scan.l"
+{ *cpStr++ = '\t'; }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 140 "ssl_expr_scan.l"
+{ *cpStr++ = '\b'; }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 141 "ssl_expr_scan.l"
+{ *cpStr++ = '\f'; }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 142 "ssl_expr_scan.l"
+{
+ *cpStr++ = yytext[1];
+}
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 145 "ssl_expr_scan.l"
+{
+ char *cp = yytext;
+ while (*cp != NUL)
+ *cpStr++ = *cp++;
+}
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 150 "ssl_expr_scan.l"
+{
+ *cpStr++ = yytext[1];
+}
+ YY_BREAK
+/*
+ * Regular Expression
+ */
+case 15:
+YY_RULE_SETUP
+#line 157 "ssl_expr_scan.l"
+{
+ cRegexDel = yytext[1];
+ cpRegex = caRegex;
+ BEGIN(regex);
+}
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 162 "ssl_expr_scan.l"
+{
+ if (yytext[0] == cRegexDel) {
+ *cpRegex = NUL;
+ BEGIN(regex_flags);
+ }
+ else {
+ *cpRegex++ = yytext[0];
+ }
+}
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 171 "ssl_expr_scan.l"
+{
+ yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, caRegex);
+ BEGIN(INITIAL);
+ return T_REGEX_I;
+}
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 176 "ssl_expr_scan.l"
+{
+ yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, caRegex);
+ yyless(0);
+ BEGIN(INITIAL);
+ return T_REGEX;
+}
+ YY_BREAK
+case YY_STATE_EOF(regex_flags):
+#line 182 "ssl_expr_scan.l"
+{
+ yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, caRegex);
+ BEGIN(INITIAL);
+ return T_REGEX;
+}
+ YY_BREAK
+/*
+ * Operators
+ */
+case 19:
+YY_RULE_SETUP
+#line 191 "ssl_expr_scan.l"
+{ return T_OP_EQ; }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 192 "ssl_expr_scan.l"
+{ return T_OP_EQ; }
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 193 "ssl_expr_scan.l"
+{ return T_OP_NE; }
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 194 "ssl_expr_scan.l"
+{ return T_OP_NE; }
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 195 "ssl_expr_scan.l"
+{ return T_OP_LT; }
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 196 "ssl_expr_scan.l"
+{ return T_OP_LT; }
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 197 "ssl_expr_scan.l"
+{ return T_OP_LE; }
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 198 "ssl_expr_scan.l"
+{ return T_OP_LE; }
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 199 "ssl_expr_scan.l"
+{ return T_OP_GT; }
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 200 "ssl_expr_scan.l"
+{ return T_OP_GT; }
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 201 "ssl_expr_scan.l"
+{ return T_OP_GE; }
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 202 "ssl_expr_scan.l"
+{ return T_OP_GE; }
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 203 "ssl_expr_scan.l"
+{ return T_OP_REG; }
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 204 "ssl_expr_scan.l"
+{ return T_OP_NRE; }
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 205 "ssl_expr_scan.l"
+{ return T_OP_AND; }
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 206 "ssl_expr_scan.l"
+{ return T_OP_AND; }
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 207 "ssl_expr_scan.l"
+{ return T_OP_OR; }
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 208 "ssl_expr_scan.l"
+{ return T_OP_OR; }
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 209 "ssl_expr_scan.l"
+{ return T_OP_NOT; }
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 210 "ssl_expr_scan.l"
+{ return T_OP_NOT; }
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 211 "ssl_expr_scan.l"
+{ return T_OP_IN; }
+ YY_BREAK
+/*
+ * Functions
+ */
+case 40:
+YY_RULE_SETUP
+#line 216 "ssl_expr_scan.l"
+{ return T_FUNC_FILE; }
+ YY_BREAK
+/*
+ * Specials
+ */
+case 41:
+YY_RULE_SETUP
+#line 221 "ssl_expr_scan.l"
+{ return T_TRUE; }
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 222 "ssl_expr_scan.l"
+{ return T_FALSE; }
+ YY_BREAK
+/*
+ * Digits
+ */
+case 43:
+YY_RULE_SETUP
+#line 227 "ssl_expr_scan.l"
+{
+ yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, yytext);
+ return T_DIGIT;
+}
+ YY_BREAK
+/*
+ * Identifiers
+ */
+case 44:
+YY_RULE_SETUP
+#line 235 "ssl_expr_scan.l"
+{
+ yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, yytext);
+ return T_ID;
+}
+ YY_BREAK
+/*
+ * Anything else is returned as is...
+ */
+case 45:
+YY_RULE_SETUP
+#line 243 "ssl_expr_scan.l"
+{
+ return yytext[0];
+}
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 247 "ssl_expr_scan.l"
+YY_FATAL_ERROR( "flex scanner jammed" );
+ YY_BREAK
+#line 1100 "lex.ssl_expr_yy.c"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(str):
+case YY_STATE_EOF(regex):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between yy_current_buffer and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yy_current_buffer->yy_input_file = yyin;
+ yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap() )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p =
+ yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yy_c_buf_p =
+ &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+ } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+ {
+ register char *dest = yy_current_buffer->yy_ch_buf;
+ register char *source = yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( yy_current_buffer->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+ YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = yy_current_buffer;
+
+ int yy_c_buf_p_offset =
+ (int) (yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yy_flex_realloc( (void *) b->yy_ch_buf,
+ b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = yy_current_buffer->yy_buf_size -
+ number_to_move - 1;
+#endif
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read );
+
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ if ( yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart( yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ yy_current_buffer->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yy_n_chars += number_to_move;
+ yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+ return ret_val;
+ }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = yy_start;
+
+ for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 86 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+ }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+ {
+ register int yy_is_jam;
+ register char *yy_cp = yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 86 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 85);
+
+ return yy_is_jam ? 0 : yy_current_state;
+ }
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+ {
+ register char *yy_cp = yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yy_hold_char;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yy_n_chars + 2;
+ register char *dest = &yy_current_buffer->yy_ch_buf[
+ yy_current_buffer->yy_buf_size + 2];
+ register char *source =
+ &yy_current_buffer->yy_ch_buf[number_to_move];
+
+ while ( source > yy_current_buffer->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ yy_current_buffer->yy_n_chars =
+ yy_n_chars = yy_current_buffer->yy_buf_size;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+
+ yytext_ptr = yy_bp;
+ yy_hold_char = *yy_cp;
+ yy_c_buf_p = yy_cp;
+ }
+#endif /* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+ {
+ int c;
+
+ *yy_c_buf_p = yy_hold_char;
+
+ if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ /* This was really a NUL. */
+ *yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yy_c_buf_p - yytext_ptr;
+ ++yy_c_buf_p;
+
+ switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart( yyin );
+
+ /* fall through */
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap() )
+ return EOF;
+
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */
+ *yy_c_buf_p = '\0'; /* preserve yytext */
+ yy_hold_char = *++yy_c_buf_p;
+
+
+ return c;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+ {
+ if ( ! yy_current_buffer )
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_init_buffer( yy_current_buffer, input_file );
+ yy_load_buffer_state();
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+ {
+ if ( yy_current_buffer == new_buffer )
+ return;
+
+ if ( yy_current_buffer )
+ {
+ /* Flush out information for old buffer. */
+ *yy_c_buf_p = yy_hold_char;
+ yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ yy_current_buffer = new_buffer;
+ yy_load_buffer_state();
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yy_did_buffer_switch_on_eof = 1;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+ {
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+ yyin = yy_current_buffer->yy_input_file;
+ yy_hold_char = *yy_c_buf_p;
+ }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer( b, file );
+
+ return b;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+ {
+ if ( ! b )
+ return;
+
+ if ( b == yy_current_buffer )
+ yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yy_flex_free( (void *) b->yy_ch_buf );
+
+ yy_flex_free( (void *) b );
+ }
+
+
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+ {
+ yy_flush_buffer( b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+ b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+ b->yy_is_interactive = 0;
+#else
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+ {
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == yy_current_buffer )
+ yy_load_buffer_state();
+ }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer( b );
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+ {
+ int len;
+ for ( len = 0; yy_str[len]; ++len )
+ ;
+
+ return yy_scan_bytes( yy_str, len );
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+ {
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = len + 2;
+ buf = (char *) yy_flex_alloc( n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < len; ++i )
+ buf[i] = bytes[i];
+
+ buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer( buf, n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+ {
+ if ( yy_start_stack_ptr >= yy_start_stack_depth )
+ {
+ yy_size_t new_size;
+
+ yy_start_stack_depth += YY_START_STACK_INCR;
+ new_size = yy_start_stack_depth * sizeof( int );
+
+ if ( ! yy_start_stack )
+ yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+ else
+ yy_start_stack = (int *) yy_flex_realloc(
+ (void *) yy_start_stack, new_size );
+
+ if ( ! yy_start_stack )
+ YY_FATAL_ERROR(
+ "out of memory expanding start-condition stack" );
+ }
+
+ yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+ BEGIN(new_state);
+ }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+ {
+ if ( --yy_start_stack_ptr < 0 )
+ YY_FATAL_ERROR( "start-condition stack underflow" );
+
+ BEGIN(yy_start_stack[yy_start_stack_ptr]);
+ }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+ {
+ return yy_start_stack[yy_start_stack_ptr - 1];
+ }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+ {
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+ }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ yytext[yyleng] = yy_hold_char; \
+ yy_c_buf_p = yytext + n; \
+ yy_hold_char = *yy_c_buf_p; \
+ *yy_c_buf_p = '\0'; \
+ yyleng = n; \
+ } \
+ while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+ {
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+ }
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+ {
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+ }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+ {
+ return (void *) malloc( size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+ {
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+ {
+ free( ptr );
+ }
+
+#if YY_MAIN
+int main()
+ {
+ yylex();
+ return 0;
+ }
+#endif
+#line 247 "ssl_expr_scan.l"
+
+
+int yyinput(char *buf, int max_size)
+{
+ int n;
+
+ if ((n = MIN(max_size, ssl_expr_info.inputbuf
+ + ssl_expr_info.inputlen
+ - ssl_expr_info.inputptr)) <= 0)
+ return YY_NULL;
+ memcpy(buf, ssl_expr_info.inputptr, n);
+ ssl_expr_info.inputptr += n;
+ return n;
+}
+
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_expr_scan.l b/usr.sbin/httpd/src/modules/ssl/ssl_expr_scan.l
index a6352724412..c111b41bdf7 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_expr_scan.l
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_expr_scan.l
@@ -1,8 +1,8 @@
/* _ _
** _ __ ___ ___ __| | ___ ___| |
** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to OpenSSL
+** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.modssl.org/
** |_____|
** ssl_expr_scan.l
** Expression Scanner
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_util.c b/usr.sbin/httpd/src/modules/ssl/ssl_util.c
index dd49b134be0..3159600be1b 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_util.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_util.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_util.c
** Utility Functions
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -121,8 +121,8 @@ char *ssl_util_vhostid(pool *p, server_rec *s)
char *id;
SSLSrvConfigRec *sc;
char *host;
- int port;
-
+ unsigned int port;
+
host = s->server_hostname;
if (s->port != 0)
port = s->port;
@@ -133,7 +133,7 @@ char *ssl_util_vhostid(pool *p, server_rec *s)
else
port = DEFAULT_HTTP_PORT;
}
- id = ap_psprintf(p, "%s:%d", host, port);
+ id = ap_psprintf(p, "%s:%u", host, port);
return id;
}
@@ -202,13 +202,48 @@ int ssl_util_ppopen_child(void *cmd, child_info *pinfo)
{
int child_pid = 1;
+ /*
+ * Prepare for exec
+ */
ap_cleanup_for_exec();
#ifdef SIGHUP
signal(SIGHUP, SIG_IGN);
#endif
-#if defined(__EMX__)
+
+ /*
+ * Exec() the child program
+ */
+#if defined(WIN32)
+ /* MS Windows */
+ {
+ char pCommand[MAX_STRING_LEN];
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ ap_snprintf(pCommand, sizeof(pCommand), "%s /C %s", SHELL_PATH, cmd);
+
+ memset(&si, 0, sizeof(si));
+ memset(&pi, 0, sizeof(pi));
+
+ si.cb = sizeof(si);
+ si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
+ si.wShowWindow = SW_HIDE;
+ si.hStdInput = pinfo->hPipeInputRead;
+ si.hStdOutput = pinfo->hPipeOutputWrite;
+ si.hStdError = pinfo->hPipeErrorWrite;
+
+ if (CreateProcess(NULL, pCommand, NULL, NULL, TRUE, 0,
+ environ, NULL, &si, &pi)) {
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ child_pid = pi.dwProcessId;
+ }
+ }
+#elif defined(OS2)
+ /* IBM OS/2 */
execl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
#else
+ /* Standard Unix */
execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
#endif
return (child_pid);
@@ -261,6 +296,46 @@ BOOL ssl_util_path_check(ssl_pathcheck_t pcm, char *path)
return TRUE;
}
+ssl_algo_t ssl_util_algotypeof(X509 *pCert, EVP_PKEY *pKey)
+{
+ ssl_algo_t t;
+
+ t = SSL_ALGO_UNKNOWN;
+ if (pCert != NULL)
+ pKey = X509_get_pubkey(pCert);
+ if (pKey != NULL) {
+ switch (EVP_PKEY_type(pKey->type)) {
+ case EVP_PKEY_RSA:
+ t = SSL_ALGO_RSA;
+ break;
+ case EVP_PKEY_DSA:
+ t = SSL_ALGO_DSA;
+ break;
+ default:
+ break;
+ }
+ }
+ return t;
+}
+
+char *ssl_util_algotypestr(ssl_algo_t t)
+{
+ char *cp;
+
+ cp = "UNKNOWN";
+ switch (t) {
+ case SSL_ALGO_RSA:
+ cp = "RSA";
+ break;
+ case SSL_ALGO_DSA:
+ cp = "DSA";
+ break;
+ default:
+ break;
+ }
+ return cp;
+}
+
char *ssl_util_ptxtsub(
pool *p, const char *cpLine, const char *cpMatch, char *cpSubst)
{
@@ -316,7 +391,7 @@ char *ssl_util_ptxtsub(
/* _________________________________________________________________
**
-** Special Functions for Win32/SSLeay
+** Special Functions for Win32/OpenSSL
** _________________________________________________________________
*/
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_util_sdbm.c b/usr.sbin/httpd/src/modules/ssl/ssl_util_sdbm.c
index 029335f88ba..4340f88ffad 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_util_sdbm.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_util_sdbm.c
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_util_sdbm.c
** Built-in Simple DBM
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_util_sdbm.h b/usr.sbin/httpd/src/modules/ssl/ssl_util_sdbm.h
index 076b8be5cdc..def1d3d94f7 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_util_sdbm.h
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_util_sdbm.h
@@ -1,8 +1,8 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_util_sdbm.c
** Built-in Simple DBM (Header)
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_util_ssl.c b/usr.sbin/httpd/src/modules/ssl/ssl_util_ssl.c
index 2d8632ae355..18a83ac8d5f 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_util_ssl.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_util_ssl.c
@@ -1,11 +1,11 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_util_ssl.c
-** Additional Utility Functions for SSLeay
+** Additional Utility Functions for OpenSSL
*/
/* ====================================================================
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -64,7 +64,7 @@
/* _________________________________________________________________
**
-** Additional High-Level Functions for SSLeay
+** Additional High-Level Functions for OpenSSL
** _________________________________________________________________
*/
@@ -73,9 +73,9 @@ int SSL_get_app_data2_idx(void)
static int app_data2_idx = -1;
if (app_data2_idx < 0) {
- app_data2_idx = SSL_get_ex_new_index(0,
+ app_data2_idx = SSL_get_ex_new_index(0,
"Second Application Data for SSL", NULL, NULL, NULL);
- app_data2_idx = SSL_get_ex_new_index(0,
+ app_data2_idx = SSL_get_ex_new_index(0,
"Second Application Data for SSL", NULL, NULL, NULL);
}
return(app_data2_idx);
@@ -92,3 +92,367 @@ void SSL_set_app_data2(SSL *ssl, void *arg)
return;
}
+/* _________________________________________________________________
+**
+** High-Level Certificate / Private Key Loading
+** _________________________________________________________________
+*/
+
+X509 *SSL_read_X509(FILE *fp, X509 **x509, int (*cb)())
+{
+ X509 *rc;
+ BIO *bioS;
+ BIO *bioF;
+
+ /* 1. try PEM (= DER+Base64+headers) */
+#if SSL_LIBRARY_VERSION < 0x00904000
+ rc = PEM_read_X509(fp, x509, cb);
+#else
+ rc = PEM_read_X509(fp, x509, cb, NULL);
+#endif
+ if (rc == NULL) {
+ /* 2. try DER+Base64 */
+ fseek(fp, 0L, SEEK_SET);
+ if ((bioS = BIO_new(BIO_s_fd())) == NULL)
+ return NULL;
+ BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
+ if ((bioF = BIO_new(BIO_f_base64())) == NULL) {
+ BIO_free(bioS);
+ return NULL;
+ }
+ bioS = BIO_push(bioF, bioS);
+ rc = d2i_X509_bio(bioS, NULL);
+ BIO_free_all(bioS);
+ if (rc == NULL) {
+ /* 3. try plain DER */
+ fseek(fp, 0L, SEEK_SET);
+ if ((bioS = BIO_new(BIO_s_fd())) == NULL)
+ return NULL;
+ BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
+ rc = d2i_X509_bio(bioS, NULL);
+ BIO_free(bioS);
+ }
+ }
+ if (rc != NULL && x509 != NULL) {
+ if (*x509 != NULL)
+ X509_free(*x509);
+ *x509 = rc;
+ }
+ return rc;
+}
+
+static EVP_PKEY *d2i_PrivateKey_bio(BIO *bio, EVP_PKEY *key)
+{
+ return ((EVP_PKEY *)ASN1_d2i_bio(
+ (char *(*)())EVP_PKEY_new,
+ (char *(*)())d2i_PrivateKey,
+ (bio), (unsigned char **)(key)));
+}
+
+EVP_PKEY *SSL_read_PrivateKey(FILE *fp, EVP_PKEY **key, int (*cb)())
+{
+ EVP_PKEY *rc;
+ BIO *bioS;
+ BIO *bioF;
+
+ /* 1. try PEM (= DER+Base64+headers) */
+#if SSL_LIBRARY_VERSION < 0x00904000
+ rc = PEM_read_PrivateKey(fp, key, cb);
+#else
+ rc = PEM_read_PrivateKey(fp, key, cb, NULL);
+#endif
+ if (rc == NULL) {
+ /* 2. try DER+Base64 */
+ fseek(fp, 0L, SEEK_SET);
+ if ((bioS = BIO_new(BIO_s_fd())) == NULL)
+ return NULL;
+ BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
+ if ((bioF = BIO_new(BIO_f_base64())) == NULL) {
+ BIO_free(bioS);
+ return NULL;
+ }
+ bioS = BIO_push(bioF, bioS);
+ rc = d2i_PrivateKey_bio(bioS, NULL);
+ BIO_free_all(bioS);
+ if (rc == NULL) {
+ /* 3. try plain DER */
+ fseek(fp, 0L, SEEK_SET);
+ if ((bioS = BIO_new(BIO_s_fd())) == NULL)
+ return NULL;
+ BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
+ rc = d2i_PrivateKey_bio(bioS, NULL);
+ BIO_free(bioS);
+ }
+ }
+ if (rc != NULL && key != NULL) {
+ if (*key != NULL)
+ EVP_PKEY_free(*key);
+ *key = rc;
+ }
+ return rc;
+}
+
+/* _________________________________________________________________
+**
+** Smart shutdown
+** _________________________________________________________________
+*/
+
+int SSL_smart_shutdown(SSL *ssl)
+{
+ int i;
+ int rc;
+
+ /*
+ * Repeat the calls, because SSL_shutdown internally dispatches through a
+ * little state machine. Usually only one or two interation should be
+ * needed, so we restrict the total number of restrictions in order to
+ * avoid process hangs in case the client played bad with the socket
+ * connection and OpenSSL cannot recognize it.
+ */
+ rc = 0;
+ for (i = 0; i < 4 /* max 2x pending + 2x data = 4 */; i++) {
+ if ((rc = SSL_shutdown(ssl)))
+ break;
+ }
+ return rc;
+}
+
+/* _________________________________________________________________
+**
+** Certificate Revocation List (CRL) Storage
+** _________________________________________________________________
+*/
+
+X509_STORE *SSL_X509_STORE_create(char *cpFile, char *cpPath)
+{
+ X509_STORE *pStore;
+ X509_LOOKUP *pLookup;
+
+ if (cpFile == NULL && cpPath == NULL)
+ return NULL;
+ if ((pStore = X509_STORE_new()) == NULL)
+ return NULL;
+ if (cpFile != NULL) {
+ if ((pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file())) == NULL) {
+ X509_STORE_free(pStore);
+ return NULL;
+ }
+ X509_LOOKUP_load_file(pLookup, cpFile, X509_FILETYPE_PEM);
+ }
+ if (cpPath != NULL) {
+ if ((pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_hash_dir())) == NULL) {
+ X509_STORE_free(pStore);
+ return NULL;
+ }
+ X509_LOOKUP_add_dir(pLookup, cpPath, X509_FILETYPE_PEM);
+ }
+ return pStore;
+}
+
+int SSL_X509_STORE_lookup(X509_STORE *pStore, int nType,
+ X509_NAME *pName, X509_OBJECT *pObj)
+{
+ X509_STORE_CTX pStoreCtx;
+ int rc;
+
+ X509_STORE_CTX_init(&pStoreCtx, pStore, NULL, NULL);
+ rc = X509_STORE_get_by_subject(&pStoreCtx, nType, pName, pObj);
+ X509_STORE_CTX_cleanup(&pStoreCtx);
+ return rc;
+}
+
+/* _________________________________________________________________
+**
+** Cipher Suite Spec String Creation
+** _________________________________________________________________
+*/
+
+char *SSL_make_ciphersuite(pool *p, SSL *ssl)
+{
+ STACK_OF(SSL_CIPHER) *sk;
+ SSL_CIPHER *c;
+ int i;
+ int l;
+ char *cpCipherSuite;
+ char *cp;
+
+ if (ssl == NULL)
+ return "";
+ sk = SSL_get_ciphers(ssl);
+ if (sk == NULL)
+ return "";
+ l = 0;
+ for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
+ c = sk_SSL_CIPHER_value(sk, i);
+ l += strlen(c->name+2+1);
+ }
+ cpCipherSuite = (char *)ap_palloc(p, l+1);
+ cp = cpCipherSuite;
+ for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
+ c = sk_SSL_CIPHER_value(sk, i);
+ l = strlen(c->name);
+ memcpy(cp, c->name, l);
+ cp += l;
+ *cp++ = '/';
+ *cp++ = (c->valid == 1 ? '1' : '0');
+ *cp++ = ':';
+ }
+ *cp = NUL;
+ return cpCipherSuite;
+}
+
+/* _________________________________________________________________
+**
+** Certificate Checks
+** _________________________________________________________________
+*/
+
+/* check whether cert contains extended key usage with a SGC tag */
+BOOL SSL_X509_isSGC(X509 *cert)
+{
+ X509_EXTENSION *ext;
+ int ext_nid;
+ STACK *sk;
+ BOOL is_sgc;
+ int idx;
+ int i;
+
+ is_sgc = FALSE;
+ idx = X509_get_ext_by_NID(cert, NID_ext_key_usage, -1);
+ if (idx >= 0) {
+ ext = X509_get_ext(cert, idx);
+ if ((sk = (STACK *)X509V3_EXT_d2i(ext)) != NULL) {
+ for (i = 0; i < sk_num(sk); i++) {
+ ext_nid = OBJ_obj2nid((ASN1_OBJECT *)sk_value(sk, i));
+ if (ext_nid == NID_ms_sgc || ext_nid == NID_ns_sgc) {
+ is_sgc = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ return is_sgc;
+}
+
+/* retrieve basic constraints ingredients */
+BOOL SSL_X509_getBC(X509 *cert, int *ca, int *pathlen)
+{
+ X509_EXTENSION *ext;
+ BASIC_CONSTRAINTS *bc;
+ int idx;
+ BIGNUM *bn = NULL;
+ char *cp;
+
+ if ((idx = X509_get_ext_by_NID(cert, NID_basic_constraints, -1)) < 0)
+ return FALSE;
+ ext = X509_get_ext(cert, idx);
+ if (ext == NULL)
+ return FALSE;
+ if ((bc = (BASIC_CONSTRAINTS *)X509V3_EXT_d2i(ext)) == NULL)
+ return FALSE;
+ *ca = bc->ca;
+ *pathlen = -1 /* unlimited */;
+ if (bc->pathlen != NULL) {
+ if ((bn = ASN1_INTEGER_to_BN(bc->pathlen, NULL)) == NULL)
+ return FALSE;
+ if ((cp = BN_bn2dec(bn)) == NULL)
+ return FALSE;
+ *pathlen = atoi(cp);
+ free(cp);
+ BN_free(bn);
+ }
+ BASIC_CONSTRAINTS_free(bc);
+ return TRUE;
+}
+
+/* retrieve subject CommonName of certificate */
+BOOL SSL_X509_getCN(pool *p, X509 *xs, char **cppCN)
+{
+ X509_NAME *xsn;
+ X509_NAME_ENTRY *xsne;
+ int i, nid;
+
+ xsn = X509_get_subject_name(xs);
+ for (i = 0; i < sk_X509_NAME_ENTRY_num(xsn->entries); i++) {
+ xsne = sk_X509_NAME_ENTRY_value(xsn->entries, i);
+ nid = OBJ_obj2nid(xsne->object);
+ if (nid == NID_commonName) {
+ *cppCN = ap_palloc(p, xsne->value->length+1);
+ ap_cpystrn(*cppCN, (char *)xsne->value->data, xsne->value->length+1);
+ (*cppCN)[xsne->value->length] = NUL;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/* _________________________________________________________________
+**
+** Extra Server Certificate Chain Support
+** _________________________________________________________________
+*/
+
+/*
+ * Read a file that optionally contains the server certificate in PEM
+ * format, possibly followed by a sequence of CA certificates that
+ * should be sent to the peer in the SSL Certificate message.
+ */
+int SSL_CTX_use_certificate_chain(
+ SSL_CTX *ctx, char *file, int skipfirst, int (*cb)())
+{
+ BIO *bio;
+ X509 *x509;
+ unsigned long err;
+ int n;
+
+ if ((bio = BIO_new(BIO_s_file_internal())) == NULL)
+ return -1;
+ if (BIO_read_filename(bio, file) <= 0) {
+ BIO_free(bio);
+ return -1;
+ }
+ /* optionally skip a leading server certificate */
+ if (skipfirst) {
+#if SSL_LIBRARY_VERSION < 0x00904000
+ if ((x509 = PEM_read_bio_X509(bio, NULL, cb)) == NULL) {
+#else
+ if ((x509 = PEM_read_bio_X509(bio, NULL, cb, NULL)) == NULL) {
+#endif
+ BIO_free(bio);
+ return -1;
+ }
+ X509_free(x509);
+ }
+ /* free a perhaps already configured extra chain */
+ if (ctx->extra_certs != NULL) {
+ sk_X509_pop_free(ctx->extra_certs, X509_free);
+ ctx->extra_certs = NULL;
+ }
+ /* create new extra chain by loading the certs */
+ n = 0;
+#if SSL_LIBRARY_VERSION < 0x00904000
+ while ((x509 = PEM_read_bio_X509(bio, NULL, cb)) != NULL) {
+#else
+ while ((x509 = PEM_read_bio_X509(bio, NULL, cb, NULL)) != NULL) {
+#endif
+ if (!SSL_CTX_add_extra_chain_cert(ctx, x509)) {
+ X509_free(x509);
+ BIO_free(bio);
+ return -1;
+ }
+ n++;
+ }
+ /* Make sure that only the error is just an EOF */
+ if ((err = ERR_peek_error()) > 0) {
+ if (!( ERR_GET_LIB(err) == ERR_LIB_PEM
+ && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
+ BIO_free(bio);
+ return -1;
+ }
+ while (ERR_get_error() > 0) ;
+ }
+ BIO_free(bio);
+ return n;
+}
+
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_util_ssl.h b/usr.sbin/httpd/src/modules/ssl/ssl_util_ssl.h
index 01e0cbe7f86..2b5f3ce6d92 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_util_ssl.h
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_util_ssl.h
@@ -1,11 +1,11 @@
/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to SSLeay
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
** |_____|
** ssl_util_ssl.h
-** Additional Utility Functions for SSLeay
+** Additional Utility Functions for OpenSSL
*/
/* ====================================================================
@@ -27,7 +27,7 @@
* software must display the following acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* 4. The names "mod_ssl" must not be used to endorse or promote
* products derived from this software without prior written
@@ -42,7 +42,7 @@
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.engelschall.com/sw/mod_ssl/)."
+ * mod_ssl project (http://www.modssl.org/)."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -68,14 +68,11 @@
#ifdef OPENSSL_VERSION_NUMBER
#define SSL_LIBRARY_VERSION OPENSSL_VERSION_NUMBER
#define SSL_LIBRARY_NAME "OpenSSL"
-#else
-#ifdef SSLEAY_VERSION_NUMBER
-#define SSL_LIBRARY_VERSION SSLEAY_VERSION_NUMBER
-#define SSL_LIBRARY_NAME "SSLeay"
+#define SSL_LIBRARY_TEXT OPENSSL_VERSION_TEXT
#else
#define SSL_LIBRARY_VERSION 0x0000
#define SSL_LIBRARY_NAME "OtherSSL"
-#endif
+#define SSL_LIBRARY_TEXT "OtherSSL 0.0.0 00 XXX 0000"
#endif
/*
@@ -89,8 +86,18 @@
/*
* Additional Functions
*/
-int SSL_get_app_data2_idx(void);
-void *SSL_get_app_data2(SSL *);
-void SSL_set_app_data2(SSL *, void *);
+int SSL_get_app_data2_idx(void);
+void *SSL_get_app_data2(SSL *);
+void SSL_set_app_data2(SSL *, void *);
+X509 *SSL_read_X509(FILE *, X509 **, int (*)());
+EVP_PKEY *SSL_read_PrivateKey(FILE *, EVP_PKEY **, int (*)());
+int SSL_smart_shutdown(SSL *ssl);
+X509_STORE *SSL_X509_STORE_create(char *, char *);
+int SSL_X509_STORE_lookup(X509_STORE *, int, X509_NAME *, X509_OBJECT *);
+char *SSL_make_ciphersuite(pool *, SSL *);
+BOOL SSL_X509_isSGC(X509 *);
+BOOL SSL_X509_getBC(X509 *, int *, int *);
+BOOL SSL_X509_getCN(pool *, X509 *, char **);
+int SSL_CTX_use_certificate_chain(SSL_CTX *, char *, int, int (*)());
#endif /* SSL_UTIL_SSL_H */
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_util_table.c b/usr.sbin/httpd/src/modules/ssl/ssl_util_table.c
new file mode 100644
index 00000000000..8a3fbea55b3
--- /dev/null
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_util_table.c
@@ -0,0 +1,2868 @@
+/* _ _
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
+** |_____|
+** ssl_util_table.c
+** High Performance Hash Table Functions
+*/
+
+/* ====================================================================
+ * Copyright (c) 1999 Ralf S. Engelschall. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by
+ * Ralf S. Engelschall <rse@engelschall.com> for use in the
+ * mod_ssl project (http://www.modssl.org/)."
+ *
+ * 4. The names "mod_ssl" must not be used to endorse or promote
+ * products derived from this software without prior written
+ * permission. For written permission, please contact
+ * rse@engelschall.com.
+ *
+ * 5. Products derived from this software may not be called "mod_ssl"
+ * nor may "mod_ssl" appear in their names without prior
+ * written permission of Ralf S. Engelschall.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by
+ * Ralf S. Engelschall <rse@engelschall.com> for use in the
+ * mod_ssl project (http://www.modssl.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
+ * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+/*
+ * Generic hash table handler
+ * Table 4.1.0 July-28-1998
+ *
+ * This library is a generic open hash table with buckets and
+ * linked lists. It is pretty high performance. Each element
+ * has a key and a data. The user indexes on the key to find the
+ * data.
+ *
+ * Copyright 1998 by Gray Watson <gray@letters.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose and without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies,
+ * and that the name of Gray Watson not be used in advertising or
+ * publicity pertaining to distribution of the document or software
+ * without specific, written prior permission.
+ *
+ * Gray Watson makes no representations about the suitability of the
+ * software described herein for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * Modified in March 1999 by Ralf S. Engelschall <rse@engelschall.com>
+ * for use in the mod_ssl project:
+ * o merged table_loc.h header into table.c
+ * o removed fillproto-comments from table.h
+ * o removed mmap() support because it's too unportable
+ * o added support for MM library via ta_{malloc,calloc,realloc,free}
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef WIN32
+#include <io.h>
+#include <errno.h>
+#else
+#include <unistd.h>
+#endif
+
+/* forward definitions for table.h */
+typedef struct table_st table_t;
+typedef struct table_entry_st table_entry_t;
+
+#define TABLE_PRIVATE
+#include "ssl_util_table.h"
+
+/****************************** local defines ******************************/
+
+#ifndef BITSPERBYTE
+#define BITSPERBYTE 8
+#endif
+#ifndef BITS
+#define BITS(type) (BITSPERBYTE * (int)sizeof(type))
+#endif
+
+#define TABLE_MAGIC 0xBADF00D /* very magic magicness */
+#define LINEAR_MAGIC 0xAD00D00 /* magic value for linear struct */
+#define DEFAULT_SIZE 1024 /* default table size */
+#define MAX_ALIGNMENT 128 /* max alignment value */
+#define MAX_SORT_SPLITS 128 /* qsort can handle 2^128 entries */
+
+/* returns 1 when we should grow or shrink the table */
+#define SHOULD_TABLE_GROW(tab) ((tab)->ta_entry_n > (tab)->ta_bucket_n * 2)
+#define SHOULD_TABLE_SHRINK(tab) ((tab)->ta_entry_n < (tab)->ta_bucket_n / 2)
+
+/*
+ * void HASH_MIX
+ *
+ * DESCRIPTION:
+ *
+ * Mix 3 32-bit values reversibly. For every delta with one or two bits
+ * set, and the deltas of all three high bits or all three low bits,
+ * whether the original value of a,b,c is almost all zero or is
+ * uniformly distributed.
+ *
+ * If HASH_MIX() is run forward or backward, at least 32 bits in a,b,c
+ * have at least 1/4 probability of changing. If mix() is run
+ * forward, every bit of c will change between 1/3 and 2/3 of the
+ * time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
+ *
+ * HASH_MIX() takes 36 machine instructions, but only 18 cycles on a
+ * superscalar machine (like a Pentium or a Sparc). No faster mixer
+ * seems to work, that's the result of my brute-force search. There
+ * were about 2^68 hashes to choose from. I only tested about a
+ * billion of those.
+ */
+#define HASH_MIX(a, b, c) \
+ do { \
+ a -= b; a -= c; a ^= (c >> 13); \
+ b -= c; b -= a; b ^= (a << 8); \
+ c -= a; c -= b; c ^= (b >> 13); \
+ a -= b; a -= c; a ^= (c >> 12); \
+ b -= c; b -= a; b ^= (a << 16); \
+ c -= a; c -= b; c ^= (b >> 5); \
+ a -= b; a -= c; a ^= (c >> 3); \
+ b -= c; b -= a; b ^= (a << 10); \
+ c -= a; c -= b; c ^= (b >> 15); \
+ } while(0)
+
+#define TABLE_POINTER(table, type, pnt) (pnt)
+
+/*
+ * Macros to get at the key and the data pointers
+ */
+#define ENTRY_KEY_BUF(entry_p) ((entry_p)->te_key_buf)
+#define ENTRY_DATA_BUF(tab_p, entry_p) \
+ (ENTRY_KEY_BUF(entry_p) + (entry_p)->te_key_size)
+
+/*
+ * Table structures...
+ */
+
+/*
+ * HACK: this should be equiv as the table_entry_t without the key_buf
+ * char. We use this with the ENTRY_SIZE() macro above which solves
+ * the problem with the lack of the [0] GNU hack. We use the
+ * table_entry_t structure to better map the memory and make things
+ * faster.
+ */
+typedef struct table_shell_st {
+ unsigned int te_key_size; /* size of data */
+ unsigned int te_data_size; /* size of data */
+ struct table_shell_st *te_next_p; /* pointer to next in the list */
+ /* NOTE: this does not have the te_key_buf field here */
+} table_shell_t;
+
+/*
+ * Elements in the bucket linked-lists. The key[1] is the start of
+ * the key with the rest of the key and all of the data information
+ * packed in memory directly after the end of this structure.
+ *
+ * NOTE: if this structure is changed, the table_shell_t must be changed
+ * to match.
+ */
+struct table_entry_st {
+ unsigned int te_key_size; /* size of data */
+ unsigned int te_data_size; /* size of data */
+ struct table_entry_st *te_next_p; /* pointer to next in the list */
+ unsigned char te_key_buf[1]; /* 1st byte of key buf */
+};
+
+/* external structure for debuggers be able to see void */
+typedef table_entry_t table_entry_ext_t;
+
+/* main table structure */
+struct table_st {
+ unsigned int ta_magic; /* magic number */
+ unsigned int ta_flags; /* table's flags defined in table.h */
+ unsigned int ta_bucket_n; /* num of buckets, should be 2^X */
+ unsigned int ta_entry_n; /* num of entries in all buckets */
+ unsigned int ta_data_align; /* data alignment value */
+ table_entry_t **ta_buckets; /* array of linked lists */
+ table_linear_t ta_linear; /* linear tracking */
+ unsigned long ta_file_size; /* size of on-disk space */
+ void *(*ta_malloc)(size_t size);
+ void *(*ta_calloc)(size_t number, size_t size);
+ void *(*ta_realloc)(void *ptr, size_t size);
+ void (*ta_free)(void *ptr);
+};
+
+/* external table structure for debuggers */
+typedef table_t table_ext_t;
+
+/* local comparison functions */
+typedef int (*compare_t) (const void *element1_p, const void *element2_p,
+ table_compare_t user_compare,
+ const table_t * table_p);
+
+/*
+ * to map error to string
+ */
+typedef struct {
+ int es_error; /* error number */
+ char *es_string; /* assocaited string */
+} error_str_t;
+
+static error_str_t errors[] =
+{
+ {TABLE_ERROR_NONE, "no error"},
+ {TABLE_ERROR_PNT, "invalid table pointer"},
+ {TABLE_ERROR_ARG_NULL, "buffer argument is null"},
+ {TABLE_ERROR_SIZE, "incorrect size argument"},
+ {TABLE_ERROR_OVERWRITE, "key exists and no overwrite"},
+ {TABLE_ERROR_NOT_FOUND, "key does not exist"},
+ {TABLE_ERROR_ALLOC, "error allocating memory"},
+ {TABLE_ERROR_LINEAR, "linear access not in progress"},
+ {TABLE_ERROR_OPEN, "could not open file"},
+ {TABLE_ERROR_SEEK, "could not seek to position in file"},
+ {TABLE_ERROR_READ, "could not read from file"},
+ {TABLE_ERROR_WRITE, "could not write to file"},
+ {TABLE_ERROR_EMPTY, "table is empty"},
+ {TABLE_ERROR_NOT_EMPTY, "table contains data"},
+ {TABLE_ERROR_ALIGNMENT, "invalid alignment value"},
+ {0}
+};
+
+#define INVALID_ERROR "invalid error code"
+
+/****************************** local functions ******************************/
+
+/*
+ * static table_entry_t *first_entry
+ *
+ * DESCRIPTION:
+ *
+ * Return the first entry in the table. It will set the linear
+ * structure counter to the position of the first entry.
+ *
+ * RETURNS:
+ *
+ * Success: A pointer to the first entry in the table.
+ *
+ * Failure: NULL if there is no first entry.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table whose next entry we are finding.
+ *
+ * linear_p - Pointer to a linear structure which we will advance and
+ * then find the corresponding entry.
+ */
+static table_entry_t *first_entry(table_t * table_p,
+ table_linear_t * linear_p)
+{
+ table_entry_t *entry_p;
+ unsigned int bucket_c = 0;
+
+ /* look for the first non-empty bucket */
+ for (bucket_c = 0; bucket_c < table_p->ta_bucket_n; bucket_c++) {
+ entry_p = table_p->ta_buckets[bucket_c];
+ if (entry_p != NULL) {
+ if (linear_p != NULL) {
+ linear_p->tl_bucket_c = bucket_c;
+ linear_p->tl_entry_c = 0;
+ }
+ return TABLE_POINTER(table_p, table_entry_t *, entry_p);
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * static table_entry_t *next_entry
+ *
+ * DESCRIPTION:
+ *
+ * Return the next entry in the table which is past the position in
+ * our linear pointer. It will advance the linear structure counters.
+ *
+ * RETURNS:
+ *
+ * Success: A pointer to the next entry in the table.
+ *
+ * Failure: NULL.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table whose next entry we are finding.
+ *
+ * linear_p - Pointer to a linear structure which we will advance and
+ * then find the corresponding entry.
+ *
+ * error_p - Pointer to an integer which when the routine returns will
+ * contain a table error code.
+ */
+static table_entry_t *next_entry(table_t * table_p, table_linear_t * linear_p,
+ int *error_p)
+{
+ table_entry_t *entry_p;
+ int entry_c;
+
+ /* can't next if we haven't first-ed */
+ if (linear_p == NULL) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_LINEAR;
+ return NULL;
+ }
+
+ if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) {
+ /*
+ * NOTE: this might happen if we delete an item which shortens the
+ * table bucket numbers.
+ */
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_NOT_FOUND;
+ return NULL;
+ }
+
+ linear_p->tl_entry_c++;
+
+ /* find the entry which is the nth in the list */
+ entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];
+ /* NOTE: we swap the order here to be more efficient */
+ for (entry_c = linear_p->tl_entry_c; entry_c > 0; entry_c--) {
+ /* did we reach the end of the list? */
+ if (entry_p == NULL)
+ break;
+ entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p;
+ }
+
+ /* did we find an entry in the current bucket? */
+ if (entry_p != NULL) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_NONE;
+ return TABLE_POINTER(table_p, table_entry_t *, entry_p);
+ }
+
+ /* find the first entry in the next non-empty bucket */
+
+ linear_p->tl_entry_c = 0;
+ for (linear_p->tl_bucket_c++; linear_p->tl_bucket_c < table_p->ta_bucket_n;
+ linear_p->tl_bucket_c++) {
+ entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];
+ if (entry_p != NULL) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_NONE;
+ return TABLE_POINTER(table_p, table_entry_t *, entry_p);
+ }
+ }
+
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_NOT_FOUND;
+ return NULL;
+}
+
+/*
+ * static unsigned int hash
+ *
+ * DESCRIPTION:
+ *
+ * Hash a variable-length key into a 32-bit value. Every bit of the
+ * key affects every bit of the return value. Every 1-bit and 2-bit
+ * delta achieves avalanche. About (6 * len + 35) instructions. The
+ * best hash table sizes are powers of 2. There is no need to use mod
+ * (sooo slow!). If you need less than 32 bits, use a bitmask. For
+ * example, if you need only 10 bits, do h = (h & hashmask(10)); In
+ * which case, the hash table should have hashsize(10) elements.
+ *
+ * By Bob Jenkins, 1996. bob_jenkins@compuserve.com. You may use
+ * this code any way you wish, private, educational, or commercial.
+ * It's free. See
+ * http://ourworld.compuserve.com/homepages/bob_jenkins/evahash.htm
+ * Use for hash table lookup, or anything where one collision in 2^^32
+ * is acceptable. Do NOT use for cryptographic purposes.
+ *
+ * RETURNS:
+ *
+ * Returns a 32-bit hash value.
+ *
+ * ARGUMENTS:
+ *
+ * key - Key (the unaligned variable-length array of bytes) that we
+ * are hashing.
+ *
+ * length - Length of the key in bytes.
+ *
+ * init_val - Initialization value of the hash if you need to hash a
+ * number of strings together. For instance, if you are hashing N
+ * strings (unsigned char **)keys, do it like this:
+ *
+ * for (i=0, h=0; i<N; ++i) h = hash( keys[i], len[i], h);
+ */
+static unsigned int hash(const unsigned char *key,
+ const unsigned int length,
+ const unsigned int init_val)
+{
+ const unsigned char *key_p = key;
+ unsigned int a, b, c, len;
+
+ /* set up the internal state */
+ a = 0x9e3779b9; /* the golden ratio; an arbitrary value */
+ b = 0x9e3779b9;
+ c = init_val; /* the previous hash value */
+
+ /* handle most of the key */
+ for (len = length; len >= 12; len -= 12) {
+ a += (key_p[0]
+ + ((unsigned long) key_p[1] << 8)
+ + ((unsigned long) key_p[2] << 16)
+ + ((unsigned long) key_p[3] << 24));
+ b += (key_p[4]
+ + ((unsigned long) key_p[5] << 8)
+ + ((unsigned long) key_p[6] << 16)
+ + ((unsigned long) key_p[7] << 24));
+ c += (key_p[8]
+ + ((unsigned long) key_p[9] << 8)
+ + ((unsigned long) key_p[10] << 16)
+ + ((unsigned long) key_p[11] << 24));
+ HASH_MIX(a, b, c);
+ key_p += 12;
+ }
+
+ c += length;
+
+ /* all the case statements fall through to the next */
+ switch (len) {
+ case 11:
+ c += ((unsigned long) key_p[10] << 24);
+ case 10:
+ c += ((unsigned long) key_p[9] << 16);
+ case 9:
+ c += ((unsigned long) key_p[8] << 8);
+ /* the first byte of c is reserved for the length */
+ case 8:
+ b += ((unsigned long) key_p[7] << 24);
+ case 7:
+ b += ((unsigned long) key_p[6] << 16);
+ case 6:
+ b += ((unsigned long) key_p[5] << 8);
+ case 5:
+ b += key_p[4];
+ case 4:
+ a += ((unsigned long) key_p[3] << 24);
+ case 3:
+ a += ((unsigned long) key_p[2] << 16);
+ case 2:
+ a += ((unsigned long) key_p[1] << 8);
+ case 1:
+ a += key_p[0];
+ /* case 0: nothing left to add */
+ }
+ HASH_MIX(a, b, c);
+
+ return c;
+}
+
+/*
+ * static int entry_size
+ *
+ * DESCRIPTION:
+ *
+ * Calculates the appropriate size of an entry to include the key and
+ * data sizes as well as any associated alignment to the data.
+ *
+ * RETURNS:
+ *
+ * The associated size of the entry.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table associated with the entries whose size we are
+ * determining.
+ *
+ * key_size - Size of the entry key.
+ *
+ * data - Size of the entry data.
+ */
+static int entry_size(const table_t * table_p, const unsigned int key_size,
+ const unsigned int data_size)
+{
+ int size, left;
+
+ /* initial size -- key is already aligned if right after struct */
+ size = sizeof(struct table_shell_st) + key_size;
+
+ /* if there is no alignment then it is easy */
+ if (table_p->ta_data_align == 0)
+ return size + data_size;
+ /* add in our alignement */
+ left = size & (table_p->ta_data_align - 1);
+ if (left > 0)
+ size += table_p->ta_data_align - left;
+ /* we add the data size here after the alignment */
+ size += data_size;
+
+ return size;
+}
+
+/*
+ * static unsigned char *entry_data_buf
+ *
+ * DESCRIPTION:
+ *
+ * Companion to the ENTRY_DATA_BUF macro but this handles any
+ * associated alignment to the data in the entry.
+ *
+ * RETURNS:
+ *
+ * Pointer to the data segment of the entry.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table associated with the entry.
+ *
+ * entry_p - Entry whose data pointer we are determining.
+ */
+static unsigned char *entry_data_buf(const table_t * table_p,
+ const table_entry_t * entry_p)
+{
+ const unsigned char *buf_p;
+ int size, pad;
+
+ buf_p = entry_p->te_key_buf + entry_p->te_key_size;
+
+ /* if there is no alignment then it is easy */
+ if (table_p->ta_data_align == 0)
+ return (unsigned char *) buf_p;
+ /* we need the size of the space before the data */
+ size = sizeof(struct table_shell_st) + entry_p->te_key_size;
+
+ /* add in our alignment */
+ pad = size & (table_p->ta_data_align - 1);
+ if (pad > 0)
+ pad = table_p->ta_data_align - pad;
+ return (unsigned char *) buf_p + pad;
+}
+
+/******************************* sort routines *******************************/
+
+/*
+ * static int our_compare
+ *
+ * DESCRIPTION:
+ *
+ * Compare two entries by calling user's compare program or by using
+ * memcmp.
+ *
+ * RETURNS:
+ *
+ * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2.
+ *
+ * ARGUMENTS:
+ *
+ * p1 - First entry pointer to compare.
+ *
+ * p2 - Second entry pointer to compare.
+ *
+ * compare - User comparison function. Ignored.
+ *
+ * table_p - Associated table being ordered. Ignored.
+ */
+static int local_compare(const void *p1, const void *p2,
+ table_compare_t compare, const table_t * table_p)
+{
+ const table_entry_t *const *ent1_p = p1, *const *ent2_p = p2;
+ int cmp;
+ unsigned int size;
+
+ /* compare as many bytes as we can */
+ size = (*ent1_p)->te_key_size;
+ if ((*ent2_p)->te_key_size < size)
+ size = (*ent2_p)->te_key_size;
+ cmp = memcmp(ENTRY_KEY_BUF(*ent1_p), ENTRY_KEY_BUF(*ent2_p), size);
+ /* if common-size equal, then if next more bytes, it is larger */
+ if (cmp == 0)
+ cmp = (*ent1_p)->te_key_size - (*ent2_p)->te_key_size;
+ return cmp;
+}
+
+/*
+ * static int external_compare
+ *
+ * DESCRIPTION:
+ *
+ * Compare two entries by calling user's compare program or by using
+ * memcmp.
+ *
+ * RETURNS:
+ *
+ * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2.
+ *
+ * ARGUMENTS:
+ *
+ * p1 - First entry pointer to compare.
+ *
+ * p2 - Second entry pointer to compare.
+ *
+ * user_compare - User comparison function.
+ *
+ * table_p - Associated table being ordered.
+ */
+static int external_compare(const void *p1, const void *p2,
+ table_compare_t user_compare,
+ const table_t * table_p)
+{
+ const table_entry_t *const *ent1_p = p1, *const *ent2_p = p2;
+ /* since we know we are not aligned we can use the EXTRY_DATA_BUF macro */
+ return user_compare(ENTRY_KEY_BUF(*ent1_p), (*ent1_p)->te_key_size,
+ ENTRY_DATA_BUF(table_p, *ent1_p),
+ (*ent1_p)->te_data_size,
+ ENTRY_KEY_BUF(*ent2_p), (*ent2_p)->te_key_size,
+ ENTRY_DATA_BUF(table_p, *ent2_p),
+ (*ent2_p)->te_data_size);
+}
+
+/*
+ * static int external_compare_align
+ *
+ * DESCRIPTION:
+ *
+ * Compare two entries by calling user's compare program or by using
+ * memcmp. Alignment information is necessary.
+ *
+ * RETURNS:
+ *
+ * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2.
+ *
+ * ARGUMENTS:
+ *
+ * p1 - First entry pointer to compare.
+ *
+ * p2 - Second entry pointer to compare.
+ *
+ * user_compare - User comparison function.
+ *
+ * table_p - Associated table being ordered.
+ */
+static int external_compare_align(const void *p1, const void *p2,
+ table_compare_t user_compare,
+ const table_t * table_p)
+{
+ const table_entry_t *const *ent1_p = p1, *const *ent2_p = p2;
+ /* since we are aligned we have to use the entry_data_buf function */
+ return user_compare(ENTRY_KEY_BUF(*ent1_p), (*ent1_p)->te_key_size,
+ entry_data_buf(table_p, *ent1_p),
+ (*ent1_p)->te_data_size,
+ ENTRY_KEY_BUF(*ent2_p), (*ent2_p)->te_key_size,
+ entry_data_buf(table_p, *ent2_p),
+ (*ent2_p)->te_data_size);
+}
+
+/*
+ * static void split
+ *
+ * DESCRIPTION:
+ *
+ * This sorts an array of longs via the quick sort algorithm (it's
+ * pretty quick)
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * first_p - Start of the list that we are splitting.
+ *
+ * last_p - Last entry in the list that we are splitting.
+ *
+ * compare - Comparison function which is handling the actual
+ * elements. This is either a local function or a function to setup
+ * the problem element key and data pointers which then hands off to
+ * the user function.
+ *
+ * user_compare - User comparison function. Could be NULL if we are
+ * just using a local comparison function.
+ *
+ * table_p - Associated table being sorted.
+ */
+static void split(void *first_p, void *last_p, compare_t compare,
+ table_compare_t user_compare, table_t * table_p)
+{
+ void *pivot_p, *left_p, *right_p, *left_last_p, *right_first_p;
+ void *firsts[MAX_SORT_SPLITS], *lasts[MAX_SORT_SPLITS];
+ int split_c = 0;
+
+ for (;;) {
+
+ /* no need to split the list if it is < 2 elements */
+ while (first_p >= last_p) {
+ if (split_c == 0) {
+ /* we are done */
+ return;
+ }
+ split_c--;
+ first_p = firsts[split_c];
+ last_p = lasts[split_c];
+ }
+
+ left_p = first_p;
+ right_p = last_p;
+ pivot_p = first_p;
+
+ do {
+ /* scan from right hand side */
+ while (right_p > left_p
+ && compare(right_p, pivot_p, user_compare, table_p) > 0)
+ right_p = (char *) right_p - sizeof(table_entry_t *);
+ /* scan from left hand side */
+ while (right_p > left_p
+ && compare(pivot_p, left_p, user_compare, table_p) >= 0)
+ left_p = (char *) left_p + sizeof(table_entry_t *);
+ /* if the pointers haven't met then swap values */
+ if (right_p > left_p) {
+ /* swap_bytes(left_p, right_p) */
+ table_entry_t *temp;
+
+ temp = *(table_entry_t **) left_p;
+ *(table_entry_t **) left_p = *(table_entry_t **) right_p;
+ *(table_entry_t **) right_p = temp;
+ }
+ } while (right_p > left_p);
+
+ /* now we swap the pivot with the right-hand side */
+ {
+ /* swap_bytes(pivot_p, right_p); */
+ table_entry_t *temp;
+
+ temp = *(table_entry_t **) pivot_p;
+ *(table_entry_t **) pivot_p = *(table_entry_t **) right_p;
+ *(table_entry_t **) right_p = temp;
+ }
+ pivot_p = right_p;
+
+ /* save the section to the right of the pivot in our stack */
+ right_first_p = (char *) pivot_p + sizeof(table_entry_t *);
+ left_last_p = (char *) pivot_p - sizeof(table_entry_t *);
+
+ /* do we need to save the righthand side? */
+ if (right_first_p < last_p) {
+ if (split_c >= MAX_SORT_SPLITS) {
+ /* sanity check here -- we should never get here */
+ abort();
+ }
+ firsts[split_c] = right_first_p;
+ lasts[split_c] = last_p;
+ split_c++;
+ }
+
+ /* do the left hand side of the pivot */
+ /* first_p = first_p */
+ last_p = left_last_p;
+ }
+}
+
+/*************************** exported routines *******************************/
+
+/*
+ * table_t *table_alloc
+ *
+ * DESCRIPTION:
+ *
+ * Allocate a new table structure.
+ *
+ * RETURNS:
+ *
+ * A pointer to the new table structure which must be passed to
+ * table_free to be deallocated. On error a NULL is returned.
+ *
+ * ARGUMENTS:
+ *
+ * bucket_n - Number of buckets for the hash table. Our current hash
+ * value works best with base two numbers. Set to 0 to take the
+ * library default of 1024.
+ *
+ * error_p - Pointer to an integer which, if not NULL, will contain a
+ * table error code.
+ *
+ * malloc_f, realloc_f, free_f - Pointers to malloc(3)-, realloc(3)-
+ * and free(3)-style functions.
+ */
+table_t *table_alloc(const unsigned int bucket_n, int *error_p,
+ void *(*malloc_f)(size_t size),
+ void *(*calloc_f)(size_t number, size_t size),
+ void *(*realloc_f)(void *ptr, size_t size),
+ void (*free_f)(void *ptr))
+{
+ table_t *table_p = NULL;
+ unsigned int buck_n;
+
+ /* allocate a table structure */
+ if (malloc_f != NULL)
+ table_p = malloc_f(sizeof(table_t));
+ else
+ table_p = malloc(sizeof(table_t));
+ if (table_p == NULL) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_ALLOC;
+ return NULL;
+ }
+
+ if (bucket_n > 0)
+ buck_n = bucket_n;
+ else
+ buck_n = DEFAULT_SIZE;
+ /* allocate the buckets which are NULLed */
+ if (calloc_f != NULL)
+ table_p->ta_buckets = (table_entry_t **)calloc_f(buck_n, sizeof(table_entry_t *));
+ else
+ table_p->ta_buckets = (table_entry_t **)calloc(buck_n, sizeof(table_entry_t *));
+ if (table_p->ta_buckets == NULL) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_ALLOC;
+ if (free_f != NULL)
+ free_f(table_p);
+ else
+ free(table_p);
+ return NULL;
+ }
+
+ /* initialize structure */
+ table_p->ta_magic = TABLE_MAGIC;
+ table_p->ta_flags = 0;
+ table_p->ta_bucket_n = buck_n;
+ table_p->ta_entry_n = 0;
+ table_p->ta_data_align = 0;
+ table_p->ta_linear.tl_magic = 0;
+ table_p->ta_linear.tl_bucket_c = 0;
+ table_p->ta_linear.tl_entry_c = 0;
+ table_p->ta_file_size = 0;
+ table_p->ta_malloc = malloc_f != NULL ? malloc_f : malloc;
+ table_p->ta_calloc = calloc_f != NULL ? calloc_f : calloc;
+ table_p->ta_realloc = realloc_f != NULL ? realloc_f : realloc;
+ table_p->ta_free = free_f != NULL ? free_f : free;
+
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_NONE;
+ return table_p;
+}
+
+/*
+ * int table_attr
+ *
+ * DESCRIPTION:
+ *
+ * Set the attributes for the table. The available attributes are
+ * specified at the top of table.h.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Pointer to a table structure which we will be altering.
+ *
+ * attr - Attribute(s) that we will be applying to the table.
+ */
+int table_attr(table_t * table_p, const int attr)
+{
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ table_p->ta_flags = attr;
+
+ return TABLE_ERROR_NONE;
+}
+
+/*
+ * int table_set_data_alignment
+ *
+ * DESCRIPTION:
+ *
+ * Set the alignment for the data in the table. For data elements
+ * sizeof(long) is recommended unless you use smaller data types
+ * exclusively.
+ *
+ * WARNING: This must be done before any data gets put into the table.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Pointer to a table structure which we will be altering.
+ *
+ * alignment - Alignment requested for the data. Must be a power of
+ * 2. Set to 0 for none.
+ */
+int table_set_data_alignment(table_t * table_p, const int alignment)
+{
+ int val;
+
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ if (table_p->ta_entry_n > 0)
+ return TABLE_ERROR_NOT_EMPTY;
+ /* defaults */
+ if (alignment < 2)
+ table_p->ta_data_align = 0;
+ else {
+ /* verify we have a base 2 number */
+ for (val = 2; val < MAX_ALIGNMENT; val *= 2) {
+ if (val == alignment)
+ break;
+ }
+ if (val >= MAX_ALIGNMENT)
+ return TABLE_ERROR_ALIGNMENT;
+ table_p->ta_data_align = alignment;
+ }
+
+ return TABLE_ERROR_NONE;
+}
+
+/*
+ * int table_clear
+ *
+ * DESCRIPTION:
+ *
+ * Clear out and free all elements in a table structure.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer that we will be clearing.
+ */
+int table_clear(table_t * table_p)
+{
+ table_entry_t *entry_p, *next_p;
+ table_entry_t **bucket_p, **bounds_p;
+
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ /* free the table allocation and table structure */
+ bounds_p = table_p->ta_buckets + table_p->ta_bucket_n;
+ for (bucket_p = table_p->ta_buckets; bucket_p < bounds_p; bucket_p++) {
+ for (entry_p = *bucket_p; entry_p != NULL; entry_p = next_p) {
+ /* record the next pointer before we free */
+ next_p = entry_p->te_next_p;
+ table_p->ta_free(entry_p);
+ }
+
+ /* clear the bucket entry after we free its entries */
+ *bucket_p = NULL;
+ }
+
+ /* reset table state info */
+ table_p->ta_entry_n = 0;
+ table_p->ta_linear.tl_magic = 0;
+ table_p->ta_linear.tl_bucket_c = 0;
+ table_p->ta_linear.tl_entry_c = 0;
+
+ return TABLE_ERROR_NONE;
+}
+
+/*
+ * int table_free
+ *
+ * DESCRIPTION:
+ *
+ * Deallocates a table structure.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer that we will be freeing.
+ */
+int table_free(table_t * table_p)
+{
+ int ret;
+
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ ret = table_clear(table_p);
+
+ if (table_p->ta_buckets != NULL)
+ table_p->ta_free(table_p->ta_buckets);
+ table_p->ta_magic = 0;
+ table_p->ta_free(table_p);
+
+ return ret;
+}
+
+/*
+ * int table_insert_kd
+ *
+ * DESCRIPTION:
+ *
+ * Like table_insert except it passes back a pointer to the key and
+ * the data buffers after they have been inserted into the table
+ * structure.
+ *
+ * This routine adds a key/data pair both of which are made up of a
+ * buffer of bytes and an associated size. Both the key and the data
+ * will be copied into buffers allocated inside the table. If the key
+ * exists already, the associated data will be replaced if the
+ * overwrite flag is set, otherwise an error is returned.
+ *
+ * NOTE: be very careful changing the values since the table library
+ * provides the pointers to its memory. The key can _never_ be
+ * changed otherwise you will not find it again. The data can be
+ * changed but its length can never be altered unless you delete and
+ * re-insert it into the table.
+ *
+ * WARNING: The pointers to the key and data are not in any specific
+ * alignment. Accessing the key and/or data as an short, integer, or
+ * long pointer directly can cause problems.
+ *
+ * WARNING: Replacing a data cell (not inserting) will cause the table
+ * linked list to be temporarily invalid. Care must be taken with
+ * multiple threaded programs which are relying on the first/next
+ * linked list to be always valid.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer into which we will be inserting a
+ * new key/data pair.
+ *
+ * key_buf - Buffer of bytes of the key that we are inserting. If you
+ * are storing an (int) as the key (for example) then key_buf should
+ * be a (int *).
+ *
+ * key_size - Size of the key_buf buffer. If set to < 0 then the
+ * library will do a strlen of key_buf and add 1 for the '\0'. If you
+ * are storing an (int) as the key (for example) then key_size should
+ * be sizeof(int).
+ *
+ * data_buf - Buffer of bytes of the data that we are inserting. If
+ * it is NULL then the library will allocate space for the data in the
+ * table without copying in any information. If data_buf is NULL and
+ * data_size is 0 then the library will associate a NULL data pointer
+ * with the key. If you are storing a (long) as the data (for
+ * example) then data_buf should be a (long *).
+ *
+ * data_size - Size of the data_buf buffer. If set to < 0 then the
+ * library will do a strlen of data_buf and add 1 for the '\0'. If
+ * you are storing an (long) as the key (for example) then key_size
+ * should be sizeof(long).
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the key storage that was allocated in the table. If you are
+ * storing an (int) as the key (for example) then key_buf_p should be
+ * (int **) i.e. the address of a (int *).
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that was allocated in the table. If you are
+ * storing an (long) as the data (for example) then data_buf_p should
+ * be (long **) i.e. the address of a (long *).
+ *
+ * overwrite - Flag which, if set to 1, will allow the overwriting of
+ * the data in the table with the new data if the key already exists
+ * in the table.
+ */
+int table_insert_kd(table_t * table_p,
+ const void *key_buf, const int key_size,
+ const void *data_buf, const int data_size,
+ void **key_buf_p, void **data_buf_p,
+ const char overwrite_b)
+{
+ int bucket;
+ unsigned int ksize, dsize;
+ table_entry_t *entry_p, *last_p;
+ void *key_copy_p, *data_copy_p;
+
+ /* check the arguments */
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ if (key_buf == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ /* data_buf can be null but size must be >= 0, if it isn't null size != 0 */
+ if ((data_buf == NULL && data_size < 0)
+ || (data_buf != NULL && data_size == 0))
+ return TABLE_ERROR_SIZE;
+ /* determine sizes of key and data */
+ if (key_size < 0)
+ ksize = strlen((char *) key_buf) + sizeof(char);
+ else
+ ksize = key_size;
+ if (data_size < 0)
+ dsize = strlen((char *) data_buf) + sizeof(char);
+ else
+ dsize = data_size;
+ /* get the bucket number via a hash function */
+ bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n;
+
+ /* look for the entry in this bucket, only check keys of the same size */
+ last_p = NULL;
+ for (entry_p = table_p->ta_buckets[bucket];
+ entry_p != NULL;
+ last_p = entry_p, entry_p = entry_p->te_next_p) {
+ if (entry_p->te_key_size == ksize
+ && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0)
+ break;
+ }
+
+ /* did we find it? then we are in replace mode. */
+ if (entry_p != NULL) {
+
+ /* can we not overwrite existing data? */
+ if (!overwrite_b) {
+ if (key_buf_p != NULL)
+ *key_buf_p = ENTRY_KEY_BUF(entry_p);
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0)
+ *data_buf_p = NULL;
+ else {
+ if (table_p->ta_data_align == 0)
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ else
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ return TABLE_ERROR_OVERWRITE;
+ }
+
+ /* re-alloc entry's data if the new size != the old */
+ if (dsize != entry_p->te_data_size) {
+
+ /*
+ * First we delete it from the list to keep the list whole.
+ * This properly preserves the linked list in case we have a
+ * thread marching through the linked list while we are
+ * inserting. Maybe this is an unnecessary protection but it
+ * should not harm that much.
+ */
+ if (last_p == NULL)
+ table_p->ta_buckets[bucket] = entry_p->te_next_p;
+ else
+ last_p->te_next_p = entry_p->te_next_p;
+ /*
+ * Realloc the structure which may change its pointer. NOTE:
+ * this may change any previous data_key_p and data_copy_p
+ * pointers.
+ */
+ entry_p = (table_entry_t *) table_p->ta_realloc(entry_p,
+ entry_size(table_p,
+ entry_p->te_key_size,
+ dsize));
+ if (entry_p == NULL)
+ return TABLE_ERROR_ALLOC;
+ /* add it back to the front of the list */
+ entry_p->te_data_size = dsize;
+ entry_p->te_next_p = table_p->ta_buckets[bucket];
+ table_p->ta_buckets[bucket] = entry_p;
+ }
+
+ /* copy or replace data in storage */
+ if (dsize > 0) {
+ if (table_p->ta_data_align == 0)
+ data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
+ else
+ data_copy_p = entry_data_buf(table_p, entry_p);
+ if (data_buf != NULL)
+ memcpy(data_copy_p, data_buf, dsize);
+ }
+ else
+ data_copy_p = NULL;
+ if (key_buf_p != NULL)
+ *key_buf_p = ENTRY_KEY_BUF(entry_p);
+ if (data_buf_p != NULL)
+ *data_buf_p = data_copy_p;
+ /* returning from the section where we were overwriting table data */
+ return TABLE_ERROR_NONE;
+ }
+
+ /*
+ * It is a new entry.
+ */
+
+ /* allocate a new entry */
+ entry_p = (table_entry_t *) table_p->ta_malloc(entry_size(table_p, ksize, dsize));
+ if (entry_p == NULL)
+ return TABLE_ERROR_ALLOC;
+ /* copy key into storage */
+ entry_p->te_key_size = ksize;
+ key_copy_p = ENTRY_KEY_BUF(entry_p);
+ memcpy(key_copy_p, key_buf, ksize);
+
+ /* copy data in */
+ entry_p->te_data_size = dsize;
+ if (dsize > 0) {
+ if (table_p->ta_data_align == 0)
+ data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
+ else
+ data_copy_p = entry_data_buf(table_p, entry_p);
+ if (data_buf != NULL)
+ memcpy(data_copy_p, data_buf, dsize);
+ }
+ else
+ data_copy_p = NULL;
+ if (key_buf_p != NULL)
+ *key_buf_p = key_copy_p;
+ if (data_buf_p != NULL)
+ *data_buf_p = data_copy_p;
+ /* insert into list, no need to append */
+ entry_p->te_next_p = table_p->ta_buckets[bucket];
+ table_p->ta_buckets[bucket] = entry_p;
+
+ table_p->ta_entry_n++;
+
+ /* do we need auto-adjust? */
+ if (table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST
+ && SHOULD_TABLE_GROW(table_p))
+ return table_adjust(table_p, table_p->ta_entry_n);
+ return TABLE_ERROR_NONE;
+}
+
+/*
+ * int table_insert
+ *
+ * DESCRIPTION:
+ *
+ * Exactly the same as table_insert_kd except it does not pass back a
+ * pointer to the key after they have been inserted into the table
+ * structure. This is still here for backwards compatibility.
+ *
+ * See table_insert_kd for more information.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer into which we will be inserting a
+ * new key/data pair.
+ *
+ * key_buf - Buffer of bytes of the key that we are inserting. If you
+ * are storing an (int) as the key (for example) then key_buf should
+ * be a (int *).
+ *
+ * key_size - Size of the key_buf buffer. If set to < 0 then the
+ * library will do a strlen of key_buf and add 1 for the '\0'. If you
+ * are storing an (int) as the key (for example) then key_size should
+ * be sizeof(int).
+ *
+ * data_buf - Buffer of bytes of the data that we are inserting. If
+ * it is NULL then the library will allocate space for the data in the
+ * table without copying in any information. If data_buf is NULL and
+ * data_size is 0 then the library will associate a NULL data pointer
+ * with the key. If you are storing a (long) as the data (for
+ * example) then data_buf should be a (long *).
+ *
+ * data_size - Size of the data_buf buffer. If set to < 0 then the
+ * library will do a strlen of data_buf and add 1 for the '\0'. If
+ * you are storing an (long) as the key (for example) then key_size
+ * should be sizeof(long).
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that was allocated in the table. If you are
+ * storing an (long) as the data (for example) then data_buf_p should
+ * be (long **) i.e. the address of a (long *).
+ *
+ * overwrite - Flag which, if set to 1, will allow the overwriting of
+ * the data in the table with the new data if the key already exists
+ * in the table.
+ */
+int table_insert(table_t * table_p,
+ const void *key_buf, const int key_size,
+ const void *data_buf, const int data_size,
+ void **data_buf_p, const char overwrite_b)
+{
+ return table_insert_kd(table_p, key_buf, key_size, data_buf, data_size,
+ NULL, data_buf_p, overwrite_b);
+}
+
+/*
+ * int table_retrieve
+ *
+ * DESCRIPTION:
+ *
+ * This routine looks up a key made up of a buffer of bytes and an
+ * associated size in the table. If found then it returns the
+ * associated data information.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer into which we will be searching
+ * for the key.
+ *
+ * key_buf - Buffer of bytes of the key that we are searching for. If
+ * you are looking for an (int) as the key (for example) then key_buf
+ * should be a (int *).
+ *
+ * key_size - Size of the key_buf buffer. If set to < 0 then the
+ * library will do a strlen of key_buf and add 1 for the '\0'. If you
+ * are looking for an (int) as the key (for example) then key_size
+ * should be sizeof(int).
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that was allocated in the table and that is
+ * associated with the key. If a (long) was stored as the data (for
+ * example) then data_buf_p should be (long **) i.e. the address of a
+ * (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data stored in the table that is associated with
+ * the key.
+ */
+int table_retrieve(table_t * table_p,
+ const void *key_buf, const int key_size,
+ void **data_buf_p, int *data_size_p)
+{
+ int bucket;
+ unsigned int ksize;
+ table_entry_t *entry_p, **buckets;
+
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ if (key_buf == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ /* find key size */
+ if (key_size < 0)
+ ksize = strlen((char *) key_buf) + sizeof(char);
+ else
+ ksize = key_size;
+ /* get the bucket number via a has function */
+ bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n;
+
+ /* look for the entry in this bucket, only check keys of the same size */
+ buckets = table_p->ta_buckets;
+ for (entry_p = buckets[bucket];
+ entry_p != NULL;
+ entry_p = entry_p->te_next_p) {
+ entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p);
+ if (entry_p->te_key_size == ksize
+ && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0)
+ break;
+ }
+
+ /* not found? */
+ if (entry_p == NULL)
+ return TABLE_ERROR_NOT_FOUND;
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0)
+ *data_buf_p = NULL;
+ else {
+ if (table_p->ta_data_align == 0)
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ else
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ if (data_size_p != NULL)
+ *data_size_p = entry_p->te_data_size;
+ return TABLE_ERROR_NONE;
+}
+
+/*
+ * int table_delete
+ *
+ * DESCRIPTION:
+ *
+ * This routine looks up a key made up of a buffer of bytes and an
+ * associated size in the table. If found then it will be removed
+ * from the table. The associated data can be passed back to the user
+ * if requested.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * NOTE: this could be an allocation error if the library is to return
+ * the data to the user.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we will be deleteing
+ * the key.
+ *
+ * key_buf - Buffer of bytes of the key that we are searching for to
+ * delete. If you are deleting an (int) key (for example) then
+ * key_buf should be a (int *).
+ *
+ * key_size - Size of the key_buf buffer. If set to < 0 then the
+ * library will do a strlen of key_buf and add 1 for the '\0'. If you
+ * are deleting an (int) key (for example) then key_size should be
+ * sizeof(int).
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that was allocated in the table and that was
+ * associated with the key. If a (long) was stored as the data (for
+ * example) then data_buf_p should be (long **) i.e. the address of a
+ * (long *). If a pointer is passed in, the caller is responsible for
+ * freeing it after use. If data_buf_p is NULL then the library will
+ * free up the data allocation itself.
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that was stored in the table and that was
+ * associated with the key.
+ */
+int table_delete(table_t * table_p,
+ const void *key_buf, const int key_size,
+ void **data_buf_p, int *data_size_p)
+{
+ int bucket;
+ unsigned int ksize;
+ unsigned char *data_copy_p;
+ table_entry_t *entry_p, *last_p;
+
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ if (key_buf == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ /* get the key size */
+ if (key_size < 0)
+ ksize = strlen((char *) key_buf) + sizeof(char);
+ else
+ ksize = key_size;
+ /* find our bucket */
+ bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n;
+
+ /* look for the entry in this bucket, only check keys of the same size */
+ for (last_p = NULL, entry_p = table_p->ta_buckets[bucket]; entry_p != NULL;
+ last_p = entry_p, entry_p = entry_p->te_next_p) {
+ if (entry_p->te_key_size == ksize
+ && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0)
+ break;
+ }
+
+ /* did we find it? */
+ if (entry_p == NULL)
+ return TABLE_ERROR_NOT_FOUND;
+ /*
+ * NOTE: we may want to adjust the linear counters here if the entry
+ * we are deleting is the one we are pointing on or is ahead of the
+ * one in the bucket list
+ */
+
+ /* remove entry from the linked list */
+ if (last_p == NULL)
+ table_p->ta_buckets[bucket] = entry_p->te_next_p;
+ else
+ last_p->te_next_p = entry_p->te_next_p;
+ /* free entry */
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0)
+ *data_buf_p = NULL;
+ else {
+ /*
+ * if we were storing it compacted, we now need to malloc some
+ * space if the user wants the value after the delete.
+ */
+ *data_buf_p = table_p->ta_malloc(entry_p->te_data_size);
+ if (*data_buf_p == NULL)
+ return TABLE_ERROR_ALLOC;
+ if (table_p->ta_data_align == 0)
+ data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
+ else
+ data_copy_p = entry_data_buf(table_p, entry_p);
+ memcpy(*data_buf_p, data_copy_p, entry_p->te_data_size);
+ }
+ }
+ if (data_size_p != NULL)
+ *data_size_p = entry_p->te_data_size;
+ table_p->ta_free(entry_p);
+
+ table_p->ta_entry_n--;
+
+ /* do we need auto-adjust down? */
+ if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST)
+ && (table_p->ta_flags & TABLE_FLAG_ADJUST_DOWN)
+ && SHOULD_TABLE_SHRINK(table_p))
+ return table_adjust(table_p, table_p->ta_entry_n);
+ return TABLE_ERROR_NONE;
+}
+
+/*
+ * int table_delete_first
+ *
+ * DESCRIPTION:
+ *
+ * This is like the table_delete routines except it deletes the first
+ * key/data pair in the table instead of an entry corresponding to a
+ * particular key. The associated key and data information can be
+ * passed back to the user if requested. This routines is handy to
+ * clear out a table.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * NOTE: this could be an allocation error if the library is to return
+ * the data to the user.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we will be deleteing
+ * the first key.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of the first key that was allocated in the table.
+ * If an (int) was stored as the first key (for example) then
+ * key_buf_p should be (int **) i.e. the address of a (int *). If a
+ * pointer is passed in, the caller is responsible for freeing it
+ * after use. If key_buf_p is NULL then the library will free up the
+ * key allocation itself.
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that was stored in the table and that was
+ * associated with the key.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that was allocated in the table and that was
+ * associated with the key. If a (long) was stored as the data (for
+ * example) then data_buf_p should be (long **) i.e. the address of a
+ * (long *). If a pointer is passed in, the caller is responsible for
+ * freeing it after use. If data_buf_p is NULL then the library will
+ * free up the data allocation itself.
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that was stored in the table and that was
+ * associated with the key.
+ */
+int table_delete_first(table_t * table_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
+{
+ unsigned char *data_copy_p;
+ table_entry_t *entry_p;
+ table_linear_t linear;
+
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ /* take the first entry */
+ entry_p = first_entry(table_p, &linear);
+ if (entry_p == NULL)
+ return TABLE_ERROR_NOT_FOUND;
+ /*
+ * NOTE: we may want to adjust the linear counters here if the entry
+ * we are deleting is the one we are pointing on or is ahead of the
+ * one in the bucket list
+ */
+
+ /* remove entry from the linked list */
+ table_p->ta_buckets[linear.tl_bucket_c] = entry_p->te_next_p;
+
+ /* free entry */
+ if (key_buf_p != NULL) {
+ if (entry_p->te_key_size == 0)
+ *key_buf_p = NULL;
+ else {
+ /*
+ * if we were storing it compacted, we now need to malloc some
+ * space if the user wants the value after the delete.
+ */
+ *key_buf_p = table_p->ta_malloc(entry_p->te_key_size);
+ if (*key_buf_p == NULL)
+ return TABLE_ERROR_ALLOC;
+ memcpy(*key_buf_p, ENTRY_KEY_BUF(entry_p), entry_p->te_key_size);
+ }
+ }
+ if (key_size_p != NULL)
+ *key_size_p = entry_p->te_key_size;
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0)
+ *data_buf_p = NULL;
+ else {
+ /*
+ * if we were storing it compacted, we now need to malloc some
+ * space if the user wants the value after the delete.
+ */
+ *data_buf_p = table_p->ta_malloc(entry_p->te_data_size);
+ if (*data_buf_p == NULL)
+ return TABLE_ERROR_ALLOC;
+ if (table_p->ta_data_align == 0)
+ data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
+ else
+ data_copy_p = entry_data_buf(table_p, entry_p);
+ memcpy(*data_buf_p, data_copy_p, entry_p->te_data_size);
+ }
+ }
+ if (data_size_p != NULL)
+ *data_size_p = entry_p->te_data_size;
+ table_p->ta_free(entry_p);
+
+ table_p->ta_entry_n--;
+
+ /* do we need auto-adjust down? */
+ if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST)
+ && (table_p->ta_flags & TABLE_FLAG_ADJUST_DOWN)
+ && SHOULD_TABLE_SHRINK(table_p))
+ return table_adjust(table_p, table_p->ta_entry_n);
+ return TABLE_ERROR_NONE;
+}
+
+/*
+ * int table_info
+ *
+ * DESCRIPTION:
+ *
+ * Get some information about a table_p structure.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting
+ * information.
+ *
+ * num_buckets_p - Pointer to an integer which, if not NULL, will
+ * contain the number of buckets in the table.
+ *
+ * num_entries_p - Pointer to an integer which, if not NULL, will
+ * contain the number of entries stored in the table.
+ */
+int table_info(table_t * table_p, int *num_buckets_p, int *num_entries_p)
+{
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ if (num_buckets_p != NULL)
+ *num_buckets_p = table_p->ta_bucket_n;
+ if (num_entries_p != NULL)
+ *num_entries_p = table_p->ta_entry_n;
+ return TABLE_ERROR_NONE;
+}
+
+/*
+ * int table_adjust
+ *
+ * DESCRIPTION:
+ *
+ * Set the number of buckets in a table to a certain value.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer of which we are adjusting.
+ *
+ * bucket_n - Number buckets to adjust the table to. Set to 0 to
+ * adjust the table to its number of entries.
+ */
+int table_adjust(table_t * table_p, const int bucket_n)
+{
+ table_entry_t *entry_p, *next_p;
+ table_entry_t **buckets, **bucket_p, **bounds_p;
+ int bucket;
+ unsigned int buck_n;
+
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ /*
+ * NOTE: we walk through the entries and rehash them. If we stored
+ * the hash value as a full int in the table-entry, all we would
+ * have to do is remod it.
+ */
+
+ /* normalize to the number of entries */
+ if (bucket_n == 0)
+ buck_n = table_p->ta_entry_n;
+ else
+ buck_n = bucket_n;
+ /* we must have at least 1 bucket */
+ if (buck_n == 0)
+ buck_n = 1;
+ /* make sure we have somethign to do */
+ if (buck_n == table_p->ta_bucket_n)
+ return TABLE_ERROR_NONE;
+ /* allocate a new bucket list */
+ buckets = (table_entry_t **) table_p->ta_calloc(buck_n, sizeof(table_entry_t *));
+ if (table_p->ta_buckets == NULL)
+ return TABLE_ERROR_ALLOC;
+ /*
+ * run through each of the items in the current table and rehash
+ * them into the newest bucket sizes
+ */
+ bounds_p = table_p->ta_buckets + table_p->ta_bucket_n;
+ for (bucket_p = table_p->ta_buckets; bucket_p < bounds_p; bucket_p++) {
+ for (entry_p = *bucket_p; entry_p != NULL; entry_p = next_p) {
+
+ /* hash the old data into the new table size */
+ bucket = hash(ENTRY_KEY_BUF(entry_p), entry_p->te_key_size, 0) % buck_n;
+
+ /* record the next one now since we overwrite next below */
+ next_p = entry_p->te_next_p;
+
+ /* insert into new list, no need to append */
+ entry_p->te_next_p = buckets[bucket];
+ buckets[bucket] = entry_p;
+
+ /*
+ * NOTE: we may want to adjust the bucket_c linear entry here to
+ * keep it current
+ */
+ }
+ /* remove the old table pointers as we go by */
+ *bucket_p = NULL;
+ }
+
+ /* replace the table buckets with the new ones */
+ table_p->ta_free(table_p->ta_buckets);
+ table_p->ta_buckets = buckets;
+ table_p->ta_bucket_n = buck_n;
+
+ return TABLE_ERROR_NONE;
+}
+
+/*
+ * const char *table_strerror
+ *
+ * DESCRIPTION:
+ *
+ * Return the corresponding string for the error number.
+ *
+ * RETURNS:
+ *
+ * Success - String equivalient of the error.
+ *
+ * Failure - String "invalid error code"
+ *
+ * ARGUMENTS:
+ *
+ * error - Error number that we are converting.
+ */
+const char *table_strerror(const int error)
+{
+ error_str_t *err_p;
+
+ for (err_p = errors; err_p->es_error != 0; err_p++) {
+ if (err_p->es_error == error)
+ return err_p->es_string;
+ }
+
+ return INVALID_ERROR;
+}
+
+/*
+ * int table_type_size
+ *
+ * DESCRIPTION:
+ *
+ * Return the size of the internal table type.
+ *
+ * RETURNS:
+ *
+ * The size of the table_t type.
+ *
+ * ARGUMENTS:
+ *
+ * None.
+ */
+int table_type_size(void)
+{
+ return sizeof(table_t);
+}
+
+/************************* linear access routines ****************************/
+
+/*
+ * int table_first
+ *
+ * DESCRIPTION:
+ *
+ * Find first element in a table and pass back information about the
+ * key/data pair. If any of the key/data pointers are NULL then they
+ * are ignored.
+ *
+ * NOTE: This function is not reentrant. More than one thread cannot
+ * be doing a first and next on the same table at the same time. Use
+ * the table_first_r version below for this.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * first element.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of the first key that is allocated in the table. If
+ * an (int) is stored as the first key (for example) then key_buf_p
+ * should be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that is stored in the table and that is
+ * associated with the first key.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that is allocated in the table and that is
+ * associated with the first key. If a (long) is stored as the data
+ * (for example) then data_buf_p should be (long **) i.e. the address
+ * of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table and that is
+ * associated with the first key.
+ */
+int table_first(table_t * table_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
+{
+ table_entry_t *entry_p;
+
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ /* initialize our linear magic number */
+ table_p->ta_linear.tl_magic = LINEAR_MAGIC;
+
+ entry_p = first_entry(table_p, &table_p->ta_linear);
+ if (entry_p == NULL)
+ return TABLE_ERROR_NOT_FOUND;
+ if (key_buf_p != NULL)
+ *key_buf_p = ENTRY_KEY_BUF(entry_p);
+ if (key_size_p != NULL)
+ *key_size_p = entry_p->te_key_size;
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0)
+ *data_buf_p = NULL;
+ else {
+ if (table_p->ta_data_align == 0)
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ else
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ if (data_size_p != NULL)
+ *data_size_p = entry_p->te_data_size;
+ return TABLE_ERROR_NONE;
+}
+
+/*
+ * int table_next
+ *
+ * DESCRIPTION:
+ *
+ * Find the next element in a table and pass back information about
+ * the key/data pair. If any of the key/data pointers are NULL then
+ * they are ignored.
+ *
+ * NOTE: This function is not reentrant. More than one thread cannot
+ * be doing a first and next on the same table at the same time. Use
+ * the table_next_r version below for this.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * next element.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of the next key that is allocated in the table. If
+ * an (int) is stored as the next key (for example) then key_buf_p
+ * should be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that is stored in the table and that is
+ * associated with the next key.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that is allocated in the table and that is
+ * associated with the next key. If a (long) is stored as the data
+ * (for example) then data_buf_p should be (long **) i.e. the address
+ * of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table and that is
+ * associated with the next key.
+ */
+int table_next(table_t * table_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
+{
+ table_entry_t *entry_p;
+ int error;
+
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ if (table_p->ta_linear.tl_magic != LINEAR_MAGIC)
+ return TABLE_ERROR_LINEAR;
+ /* move to the next entry */
+ entry_p = next_entry(table_p, &table_p->ta_linear, &error);
+ if (entry_p == NULL)
+ return error;
+ if (key_buf_p != NULL)
+ *key_buf_p = ENTRY_KEY_BUF(entry_p);
+ if (key_size_p != NULL)
+ *key_size_p = entry_p->te_key_size;
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0)
+ *data_buf_p = NULL;
+ else {
+ if (table_p->ta_data_align == 0)
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ else
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ if (data_size_p != NULL)
+ *data_size_p = entry_p->te_data_size;
+ return TABLE_ERROR_NONE;
+}
+
+/*
+ * int table_this
+ *
+ * DESCRIPTION:
+ *
+ * Find the current element in a table and pass back information about
+ * the key/data pair. If any of the key/data pointers are NULL then
+ * they are ignored.
+ *
+ * NOTE: This function is not reentrant. Use the table_current_r
+ * version below.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * current element.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of the current key that is allocated in the table.
+ * If an (int) is stored as the current key (for example) then
+ * key_buf_p should be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that is stored in the table and that is
+ * associated with the current key.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that is allocated in the table and that is
+ * associated with the current key. If a (long) is stored as the data
+ * (for example) then data_buf_p should be (long **) i.e. the address
+ * of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table and that is
+ * associated with the current key.
+ */
+int table_this(table_t * table_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
+{
+ table_entry_t *entry_p = NULL;
+ int entry_c;
+
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ if (table_p->ta_linear.tl_magic != LINEAR_MAGIC)
+ return TABLE_ERROR_LINEAR;
+ /* if we removed an item that shorted the bucket list, we may get this */
+ if (table_p->ta_linear.tl_bucket_c >= table_p->ta_bucket_n) {
+ /*
+ * NOTE: this might happen if we delete an item which shortens the
+ * table bucket numbers.
+ */
+ return TABLE_ERROR_NOT_FOUND;
+ }
+
+ /* find the entry which is the nth in the list */
+ entry_p = table_p->ta_buckets[table_p->ta_linear.tl_bucket_c];
+ /* NOTE: we swap the order here to be more efficient */
+ for (entry_c = table_p->ta_linear.tl_entry_c; entry_c > 0; entry_c--) {
+ /* did we reach the end of the list? */
+ if (entry_p == NULL)
+ break;
+ entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p;
+ }
+
+ /* is this a NOT_FOUND or a LINEAR error */
+ if (entry_p == NULL)
+ return TABLE_ERROR_NOT_FOUND;
+ if (key_buf_p != NULL)
+ *key_buf_p = ENTRY_KEY_BUF(entry_p);
+ if (key_size_p != NULL)
+ *key_size_p = entry_p->te_key_size;
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0)
+ *data_buf_p = NULL;
+ else {
+ if (table_p->ta_data_align == 0)
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ else
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ if (data_size_p != NULL)
+ *data_size_p = entry_p->te_data_size;
+ return TABLE_ERROR_NONE;
+}
+
+/*
+ * int table_first_r
+ *
+ * DESCRIPTION:
+ *
+ * Reetrant version of the table_first routine above. Find first
+ * element in a table and pass back information about the key/data
+ * pair. If any of the key/data pointers are NULL then they are
+ * ignored.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * first element.
+ *
+ * linear_p - Pointer to a table linear structure which is initialized
+ * here. The same pointer should then be passed to table_next_r
+ * below.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of the first key that is allocated in the table. If
+ * an (int) is stored as the first key (for example) then key_buf_p
+ * should be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that is stored in the table and that is
+ * associated with the first key.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that is allocated in the table and that is
+ * associated with the first key. If a (long) is stored as the data
+ * (for example) then data_buf_p should be (long **) i.e. the address
+ * of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table and that is
+ * associated with the first key.
+ */
+int table_first_r(table_t * table_p, table_linear_t * linear_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
+{
+ table_entry_t *entry_p;
+
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ if (linear_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ /* initialize our linear magic number */
+ linear_p->tl_magic = LINEAR_MAGIC;
+
+ entry_p = first_entry(table_p, linear_p);
+ if (entry_p == NULL)
+ return TABLE_ERROR_NOT_FOUND;
+ if (key_buf_p != NULL)
+ *key_buf_p = ENTRY_KEY_BUF(entry_p);
+ if (key_size_p != NULL)
+ *key_size_p = entry_p->te_key_size;
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0)
+ *data_buf_p = NULL;
+ else {
+ if (table_p->ta_data_align == 0)
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ else
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ if (data_size_p != NULL)
+ *data_size_p = entry_p->te_data_size;
+ return TABLE_ERROR_NONE;
+}
+
+/*
+ * int table_next_r
+ *
+ * DESCRIPTION:
+ *
+ * Reetrant version of the table_next routine above. Find next
+ * element in a table and pass back information about the key/data
+ * pair. If any of the key/data pointers are NULL then they are
+ * ignored.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * next element.
+ *
+ * linear_p - Pointer to a table linear structure which is incremented
+ * here. The same pointer must have been passed to table_first_r
+ * first so that it can be initialized.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of the next key that is allocated in the table. If
+ * an (int) is stored as the next key (for example) then key_buf_p
+ * should be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL will be set
+ * to the size of the key that is stored in the table and that is
+ * associated with the next key.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that is allocated in the table and that is
+ * associated with the next key. If a (long) is stored as the data
+ * (for example) then data_buf_p should be (long **) i.e. the address
+ * of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table and that is
+ * associated with the next key.
+ */
+int table_next_r(table_t * table_p, table_linear_t * linear_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
+{
+ table_entry_t *entry_p;
+ int error;
+
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ if (linear_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (linear_p->tl_magic != LINEAR_MAGIC)
+ return TABLE_ERROR_LINEAR;
+ /* move to the next entry */
+ entry_p = next_entry(table_p, linear_p, &error);
+ if (entry_p == NULL)
+ return error;
+ if (key_buf_p != NULL)
+ *key_buf_p = ENTRY_KEY_BUF(entry_p);
+ if (key_size_p != NULL)
+ *key_size_p = entry_p->te_key_size;
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0)
+ *data_buf_p = NULL;
+ else {
+ if (table_p->ta_data_align == 0)
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ else
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ if (data_size_p != NULL)
+ *data_size_p = entry_p->te_data_size;
+ return TABLE_ERROR_NONE;
+}
+
+/*
+ * int table_this_r
+ *
+ * DESCRIPTION:
+ *
+ * Reetrant version of the table_this routine above. Find current
+ * element in a table and pass back information about the key/data
+ * pair. If any of the key/data pointers are NULL then they are
+ * ignored.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * current element.
+ *
+ * linear_p - Pointer to a table linear structure which is accessed
+ * here. The same pointer must have been passed to table_first_r
+ * first so that it can be initialized.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of the current key that is allocated in the table.
+ * If an (int) is stored as the current key (for example) then
+ * key_buf_p should be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that is stored in the table and that is
+ * associated with the current key.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that is allocated in the table and that is
+ * associated with the current key. If a (long) is stored as the data
+ * (for example) then data_buf_p should be (long **) i.e. the address
+ * of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table and that is
+ * associated with the current key.
+ */
+int table_this_r(table_t * table_p, table_linear_t * linear_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
+{
+ table_entry_t *entry_p;
+ int entry_c;
+
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ if (linear_p->tl_magic != LINEAR_MAGIC)
+ return TABLE_ERROR_LINEAR;
+ /* if we removed an item that shorted the bucket list, we may get this */
+ if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) {
+ /*
+ * NOTE: this might happen if we delete an item which shortens the
+ * table bucket numbers.
+ */
+ return TABLE_ERROR_NOT_FOUND;
+ }
+
+ /* find the entry which is the nth in the list */
+ for (entry_c = linear_p->tl_entry_c,
+ entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];
+ entry_p != NULL && entry_c > 0;
+ entry_c--, entry_p = TABLE_POINTER(table_p, table_entry_t *,
+ entry_p)->te_next_p) {
+ }
+
+ if (entry_p == NULL)
+ return TABLE_ERROR_NOT_FOUND;
+ if (key_buf_p != NULL)
+ *key_buf_p = ENTRY_KEY_BUF(entry_p);
+ if (key_size_p != NULL)
+ *key_size_p = entry_p->te_key_size;
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0)
+ *data_buf_p = NULL;
+ else {
+ if (table_p->ta_data_align == 0)
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ else
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ if (data_size_p != NULL)
+ *data_size_p = entry_p->te_data_size;
+ return TABLE_ERROR_NONE;
+}
+
+/******************************* file routines *******************************/
+
+/*
+ * int table_read
+ *
+ * DESCRIPTION:
+ *
+ * Read in a table from a file that had been written to disk earlier
+ * via table_write.
+ *
+ * RETURNS:
+ *
+ * Success - Pointer to the new table structure which must be passed
+ * to table_free to be deallocated.
+ *
+ * Failure - NULL
+ *
+ * ARGUMENTS:
+ *
+ * path - Table file to read in.
+ *
+ * error_p - Pointer to an integer which, if not NULL, will contain a
+ * table error code.
+ */
+table_t *table_read(const char *path, int *error_p,
+ void *(*malloc_f)(size_t size),
+ void *(*calloc_f)(size_t number, size_t size),
+ void *(*realloc_f)(void *ptr, size_t size),
+ void (*free_f)(void *ptr))
+{
+ unsigned int size;
+ int fd, ent_size;
+ FILE *infile;
+ table_entry_t entry, **bucket_p, *entry_p = NULL, *last_p;
+ unsigned long pos;
+ table_t *table_p;
+
+ /* open the file */
+ fd = open(path, O_RDONLY, 0);
+ if (fd < 0) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_OPEN;
+ return NULL;
+ }
+
+ /* allocate a table structure */
+ if (malloc_f != NULL)
+ table_p = malloc_f(sizeof(table_t));
+ else
+ table_p = malloc(sizeof(table_t));
+ if (table_p == NULL) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_ALLOC;
+ return NULL;
+ }
+
+ /* now open the fd to get buffered i/o */
+ infile = fdopen(fd, "r");
+ if (infile == NULL) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_OPEN;
+ return NULL;
+ }
+
+ /* read the main table struct */
+ if (fread(table_p, sizeof(table_t), 1, infile) != 1) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_READ;
+ if (free_f != NULL)
+ free_f(table_p);
+ else
+ free(table_p);
+ return NULL;
+ }
+ table_p->ta_file_size = 0;
+
+ table_p->ta_malloc = malloc_f != NULL ? malloc_f : malloc;
+ table_p->ta_calloc = calloc_f != NULL ? calloc_f : calloc;
+ table_p->ta_realloc = realloc_f != NULL ? realloc_f : realloc;
+ table_p->ta_free = free_f != NULL ? free_f : free;
+
+ /* is the file contain bad info or maybe another system type? */
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_PNT;
+ return NULL;
+ }
+
+ /* allocate the buckets */
+ table_p->ta_buckets = (table_entry_t **)table_p->ta_calloc(table_p->ta_bucket_n, sizeof(table_entry_t *));
+ if (table_p->ta_buckets == NULL) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_ALLOC;
+ table_p->ta_free(table_p);
+ return NULL;
+ }
+
+ if (fread(table_p->ta_buckets, sizeof(table_entry_t *), table_p->ta_bucket_n,
+ infile) != (size_t) table_p->ta_bucket_n) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_READ;
+ table_p->ta_free(table_p->ta_buckets);
+ table_p->ta_free(table_p);
+ return NULL;
+ }
+
+ /* read in the entries */
+ for (bucket_p = table_p->ta_buckets;
+ bucket_p < table_p->ta_buckets + table_p->ta_bucket_n;
+ bucket_p++) {
+
+ /* skip null buckets */
+ if (*bucket_p == NULL)
+ continue;
+ /* run through the entry list */
+ last_p = NULL;
+ for (pos = *(unsigned long *) bucket_p;;
+ pos = (unsigned long) entry_p->te_next_p) {
+
+ /* read in the entry */
+ if (fseek(infile, pos, SEEK_SET) != 0) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_SEEK;
+ table_p->ta_free(table_p->ta_buckets);
+ if (entry_p != NULL)
+ table_p->ta_free(entry_p);
+ table_p->ta_free(table_p);
+ /* the other table elements will not be freed */
+ return NULL;
+ }
+ if (fread(&entry, sizeof(struct table_shell_st), 1, infile) != 1) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_READ;
+ table_p->ta_free(table_p->ta_buckets);
+ if (entry_p != NULL)
+ table_p->ta_free(entry_p);
+ table_p->ta_free(table_p);
+ /* the other table elements will not be freed */
+ return NULL;
+ }
+
+ /* make a new entry */
+ ent_size = entry_size(table_p, entry.te_key_size, entry.te_data_size);
+ entry_p = (table_entry_t *)table_p->ta_malloc(ent_size);
+ if (entry_p == NULL) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_ALLOC;
+ table_p->ta_free(table_p->ta_buckets);
+ table_p->ta_free(table_p);
+ /* the other table elements will not be freed */
+ return NULL;
+ }
+ entry_p->te_key_size = entry.te_key_size;
+ entry_p->te_data_size = entry.te_data_size;
+ entry_p->te_next_p = entry.te_next_p;
+
+ if (last_p == NULL)
+ *bucket_p = entry_p;
+ else
+ last_p->te_next_p = entry_p;
+ /* determine how much more we have to read */
+ size = ent_size - sizeof(struct table_shell_st);
+ if (fread(ENTRY_KEY_BUF(entry_p), sizeof(char), size, infile) != size) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_READ;
+ table_p->ta_free(table_p->ta_buckets);
+ table_p->ta_free(entry_p);
+ table_p->ta_free(table_p);
+ /* the other table elements will not be freed */
+ return NULL;
+ }
+
+ /* we are done if the next pointer is null */
+ if (entry_p->te_next_p == (unsigned long) 0)
+ break;
+ last_p = entry_p;
+ }
+ }
+
+ (void) fclose(infile);
+
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_NONE;
+ return table_p;
+}
+
+/*
+ * int table_write
+ *
+ * DESCRIPTION:
+ *
+ * Write a table from memory to file.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Pointer to the table that we are writing to the file.
+ *
+ * path - Table file to write out to.
+ *
+ * mode - Mode of the file. This argument is passed on to open when
+ * the file is created.
+ */
+int table_write(const table_t * table_p, const char *path, const int mode)
+{
+ int fd, rem, ent_size;
+ unsigned int bucket_c;
+ unsigned long size;
+ table_entry_t *entry_p, **buckets, **bucket_p, *next_p;
+ table_t tmain;
+ FILE *outfile;
+
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ fd = open(path, O_WRONLY | O_CREAT, mode);
+ if (fd < 0)
+ return TABLE_ERROR_OPEN;
+ outfile = fdopen(fd, "w");
+ if (outfile == NULL)
+ return TABLE_ERROR_OPEN;
+ /* allocate a block of sizes for each bucket */
+ buckets = (table_entry_t **) table_p->ta_malloc(sizeof(table_entry_t *) *
+ table_p->ta_bucket_n);
+ if (buckets == NULL)
+ return TABLE_ERROR_ALLOC;
+ /* make a copy of the tmain struct */
+ tmain = *table_p;
+
+ /* start counting the bytes */
+ size = 0;
+ size += sizeof(table_t);
+
+ /* buckets go right after tmain struct */
+ tmain.ta_buckets = (table_entry_t **) size;
+ size += sizeof(table_entry_t *) * table_p->ta_bucket_n;
+
+ /* run through and count the buckets */
+ for (bucket_c = 0; bucket_c < table_p->ta_bucket_n; bucket_c++) {
+ bucket_p = table_p->ta_buckets + bucket_c;
+ if (*bucket_p == NULL) {
+ buckets[bucket_c] = NULL;
+ continue;
+ }
+ buckets[bucket_c] = (table_entry_t *) size;
+ for (entry_p = *bucket_p; entry_p != NULL; entry_p = entry_p->te_next_p) {
+ size += entry_size(table_p, entry_p->te_key_size, entry_p->te_data_size);
+ /*
+ * We now have to round the file to the nearest long so the
+ * mmaping of the longs in the entry structs will work.
+ */
+ rem = size & (sizeof(long) - 1);
+ if (rem > 0)
+ size += sizeof(long) - rem;
+ }
+ }
+ /* add a \0 at the end to fill the last section */
+ size++;
+
+ /* set the tmain fields */
+ tmain.ta_linear.tl_magic = 0;
+ tmain.ta_linear.tl_bucket_c = 0;
+ tmain.ta_linear.tl_entry_c = 0;
+ tmain.ta_file_size = size;
+
+ /*
+ * Now we can start the writing because we got the bucket offsets.
+ */
+
+ /* write the tmain table struct */
+ size = 0;
+ if (fwrite(&tmain, sizeof(table_t), 1, outfile) != 1) {
+ table_p->ta_free(buckets);
+ return TABLE_ERROR_WRITE;
+ }
+ size += sizeof(table_t);
+ if (fwrite(buckets, sizeof(table_entry_t *), table_p->ta_bucket_n,
+ outfile) != (size_t) table_p->ta_bucket_n) {
+ table_p->ta_free(buckets);
+ return TABLE_ERROR_WRITE;
+ }
+ size += sizeof(table_entry_t *) * table_p->ta_bucket_n;
+
+ /* write out the entries */
+ for (bucket_p = table_p->ta_buckets;
+ bucket_p < table_p->ta_buckets + table_p->ta_bucket_n;
+ bucket_p++) {
+ for (entry_p = *bucket_p; entry_p != NULL; entry_p = entry_p->te_next_p) {
+
+ ent_size = entry_size(table_p, entry_p->te_key_size,
+ entry_p->te_data_size);
+ size += ent_size;
+ /* round to nearest long here so we can write copy */
+ rem = size & (sizeof(long) - 1);
+ if (rem > 0)
+ size += sizeof(long) - rem;
+ next_p = entry_p->te_next_p;
+ if (next_p != NULL)
+ entry_p->te_next_p = (table_entry_t *) size;
+ /* now write to disk */
+ if (fwrite(entry_p, ent_size, 1, outfile) != 1) {
+ table_p->ta_free(buckets);
+ return TABLE_ERROR_WRITE;
+ }
+
+ /* restore the next pointer */
+ if (next_p != NULL)
+ entry_p->te_next_p = next_p;
+ /* now write the padding information */
+ if (rem > 0) {
+ rem = sizeof(long) - rem;
+ /*
+ * NOTE: this won't leave fseek'd space at the end but we
+ * don't care there because there is no accessed memory
+ * afterwards. We write 1 \0 at the end to make sure.
+ */
+ if (fseek(outfile, rem, SEEK_CUR) != 0) {
+ table_p->ta_free(buckets);
+ return TABLE_ERROR_SEEK;
+ }
+ }
+ }
+ }
+ /*
+ * Write a \0 at the end of the file to make sure that the last
+ * fseek filled with nulls.
+ */
+ (void) fputc('\0', outfile);
+
+ (void) fclose(outfile);
+ table_p->ta_free(buckets);
+
+ return TABLE_ERROR_NONE;
+}
+
+/******************************** table order ********************************/
+
+/*
+ * table_entry_t *table_order
+ *
+ * DESCRIPTION:
+ *
+ * Order a table by building an array of table entry pointers and then
+ * sorting this array using the qsort function. To retrieve the
+ * sorted entries, you can then use the table_entry routine to access
+ * each entry in order.
+ *
+ * NOTE: This routine is now thread safe in that two table_order calls
+ * can now happen at the same time, even on the same table.
+ *
+ * RETURNS:
+ *
+ * An allocated list of entry pointers which must be freed later.
+ * Returns null on error.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Pointer to the table that we are ordering.
+ *
+ * compare - Comparison function defined by the user. Its definition
+ * is at the top of the table.h file. If this is NULL then it will
+ * order the table my memcmp-ing the keys.
+ *
+ * num_entries_p - Pointer to an integer which, if not NULL, will
+ * contain the number of entries in the returned entry pointer array.
+ *
+ * error_p - Pointer to an integer which, if not NULL, will contain a
+ * table error code.
+ */
+table_entry_t **table_order(table_t * table_p, table_compare_t compare,
+ int *num_entries_p, int *error_p)
+{
+ table_entry_t *entry_p, **entries, **entries_p;
+ table_linear_t linear;
+ compare_t comp_func;
+ int error;
+
+ if (table_p == NULL) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_ARG_NULL;
+ return NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_PNT;
+ return NULL;
+ }
+
+ /* there must be at least 1 element in the table for this to work */
+ if (table_p->ta_entry_n == 0) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_EMPTY;
+ return NULL;
+ }
+
+ entries = (table_entry_t **) table_p->ta_malloc(table_p->ta_entry_n *
+ sizeof(table_entry_t *));
+ if (entries == NULL) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_ALLOC;
+ return NULL;
+ }
+
+ /* get a pointer to all entries */
+ entry_p = first_entry(table_p, &linear);
+ if (entry_p == NULL) {
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_NOT_FOUND;
+ return NULL;
+ }
+
+ /* add all of the entries to the array */
+ for (entries_p = entries;
+ entry_p != NULL;
+ entry_p = next_entry(table_p, &linear, &error))
+ *entries_p++ = entry_p;
+ if (error != TABLE_ERROR_NOT_FOUND) {
+ if (error_p != NULL)
+ *error_p = error;
+ return NULL;
+ }
+
+ if (compare == NULL) {
+ /* this is regardless of the alignment */
+ comp_func = local_compare;
+ }
+ else if (table_p->ta_data_align == 0)
+ comp_func = external_compare;
+ else
+ comp_func = external_compare_align;
+ /* now qsort the entire entries array from first to last element */
+ split(entries, entries + table_p->ta_entry_n - 1, comp_func, compare,
+ table_p);
+
+ if (num_entries_p != NULL)
+ *num_entries_p = table_p->ta_entry_n;
+ if (error_p != NULL)
+ *error_p = TABLE_ERROR_NONE;
+ return entries;
+}
+
+/*
+ * int table_entry
+ *
+ * DESCRIPTION:
+ *
+ * Get information about an element. The element is one from the
+ * array returned by the table_order function. If any of the key/data
+ * pointers are NULL then they are ignored.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * element.
+ *
+ * entry_p - Pointer to a table entry from the array returned by the
+ * table_order function.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of this entry that is allocated in the table. If an
+ * (int) is stored as this entry (for example) then key_buf_p should
+ * be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that is stored in the table.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage of this entry that is allocated in the table.
+ * If a (long) is stored as this entry data (for example) then
+ * data_buf_p should be (long **) i.e. the address of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table.
+ */
+int table_entry_info(table_t * table_p, table_entry_t * entry_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
+{
+ if (table_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (table_p->ta_magic != TABLE_MAGIC)
+ return TABLE_ERROR_PNT;
+ if (entry_p == NULL)
+ return TABLE_ERROR_ARG_NULL;
+ if (key_buf_p != NULL)
+ *key_buf_p = ENTRY_KEY_BUF(entry_p);
+ if (key_size_p != NULL)
+ *key_size_p = entry_p->te_key_size;
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0)
+ *data_buf_p = NULL;
+ else {
+ if (table_p->ta_data_align == 0)
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ else
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ if (data_size_p != NULL)
+ *data_size_p = entry_p->te_data_size;
+ return TABLE_ERROR_NONE;
+}
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_util_table.h b/usr.sbin/httpd/src/modules/ssl/ssl_util_table.h
new file mode 100644
index 00000000000..5ad7a2a33ca
--- /dev/null
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_util_table.h
@@ -0,0 +1,189 @@
+/* _ _
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
+** |_____|
+** ssl_util_table.h
+** High Performance Hash Table Header
+*/
+
+/* ====================================================================
+ * Copyright (c) 1999 Ralf S. Engelschall. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by
+ * Ralf S. Engelschall <rse@engelschall.com> for use in the
+ * mod_ssl project (http://www.modssl.org/)."
+ *
+ * 4. The names "mod_ssl" must not be used to endorse or promote
+ * products derived from this software without prior written
+ * permission. For written permission, please contact
+ * rse@engelschall.com.
+ *
+ * 5. Products derived from this software may not be called "mod_ssl"
+ * nor may "mod_ssl" appear in their names without prior
+ * written permission of Ralf S. Engelschall.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by
+ * Ralf S. Engelschall <rse@engelschall.com> for use in the
+ * mod_ssl project (http://www.modssl.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
+ * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+/*
+ * Generic hash table defines
+ * Table 4.1.0 July-28-1998
+ *
+ * This library is a generic open hash table with buckets and
+ * linked lists. It is pretty high performance. Each element
+ * has a key and a data. The user indexes on the key to find the
+ * data.
+ *
+ * Copyright 1998 by Gray Watson <gray@letters.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose and without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies,
+ * and that the name of Gray Watson not be used in advertising or
+ * publicity pertaining to distribution of the document or software
+ * without specific, written prior permission.
+ *
+ * Gray Watson makes no representations about the suitability of the
+ * software described herein for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ */
+
+#ifndef SSL_UTIL_TABLE_H
+#define SSL_UTIL_TABLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * To build a "key" in any of the below routines, pass in a pointer to
+ * the key and its size [i.e. sizeof(int), etc]. With any of the
+ * "key" or "data" arguments, if their size is < 0, it will do an
+ * internal strlen of the item and add 1 for the \0.
+ *
+ * If you are using firstkey() and nextkey() functions, be careful if,
+ * after starting your firstkey loop, you use delete or insert, it
+ * will not crash but may produce interesting results. If you are
+ * deleting from firstkey to NULL it will work fine.
+ */
+
+/* return types for table functions */
+#define TABLE_ERROR_NONE 1 /* no error from function */
+#define TABLE_ERROR_PNT 2 /* bad table pointer */
+#define TABLE_ERROR_ARG_NULL 3 /* buffer args were null */
+#define TABLE_ERROR_SIZE 4 /* size of data was bad */
+#define TABLE_ERROR_OVERWRITE 5 /* key exists and we cant overwrite */
+#define TABLE_ERROR_NOT_FOUND 6 /* key does not exist */
+#define TABLE_ERROR_ALLOC 7 /* memory allocation error */
+#define TABLE_ERROR_LINEAR 8 /* no linear access started */
+#define TABLE_ERROR_OPEN 9 /* could not open file */
+#define TABLE_ERROR_SEEK 10 /* could not seek to pos in file */
+#define TABLE_ERROR_READ 11 /* could not read from file */
+#define TABLE_ERROR_WRITE 12 /* could not write to file */
+#define TABLE_ERROR_EMPTY 13 /* table is empty */
+#define TABLE_ERROR_NOT_EMPTY 14 /* table contains data */
+#define TABLE_ERROR_ALIGNMENT 15 /* invalid alignment value */
+
+/*
+ * Table flags set with table_attr.
+ */
+
+/*
+ * Automatically adjust the number of table buckets on the fly.
+ * Whenever the number of entries gets above some threshold, the
+ * number of buckets is realloced to a new size and each entry is
+ * re-hashed. Although this may take some time when it re-hashes, the
+ * table will perform better over time.
+ */
+#define TABLE_FLAG_AUTO_ADJUST (1<<0)
+
+/*
+ * If the above auto-adjust flag is set, also adjust the number of
+ * table buckets down as we delete entries.
+ */
+#define TABLE_FLAG_ADJUST_DOWN (1<<1)
+
+/* structure to walk through the fields in a linear order */
+typedef struct {
+ unsigned int tl_magic; /* magic structure to ensure correct init */
+ unsigned int tl_bucket_c; /* where in the table buck array we are */
+ unsigned int tl_entry_c; /* in the bucket, which entry we are on */
+} table_linear_t;
+
+typedef int (*table_compare_t)(const void *key1, const int key1_size,
+ const void *data1, const int data1_size,
+ const void *key2, const int key2_size,
+ const void *data2, const int data2_size);
+
+#ifndef TABLE_PRIVATE
+typedef void table_t;
+typedef void table_entry_t;
+#endif
+
+/*
+ * Prototypes
+ */
+extern table_t *table_alloc(const unsigned int bucket_n, int *error_p, void *(*malloc_f)(size_t size), void *(*calloc_f)(size_t number, size_t size), void *(*realloc_f)(void *ptr, size_t size), void (*free_f)(void *ptr));
+extern int table_attr(table_t *table_p, const int attr);
+extern int table_set_data_alignment(table_t *table_p, const int alignment);
+extern int table_clear(table_t *table_p);
+extern int table_free(table_t *table_p);
+extern int table_insert_kd(table_t *table_p, const void *key_buf, const int key_size, const void *data_buf, const int data_size, void **key_buf_p, void **data_buf_p, const char overwrite_b);
+extern int table_insert(table_t *table_p, const void *key_buf, const int key_size, const void *data_buf, const int data_size, void **data_buf_p, const char overwrite_b);
+extern int table_retrieve(table_t *table_p, const void *key_buf, const int key_size, void **data_buf_p, int *data_size_p);
+extern int table_delete(table_t *table_p, const void *key_buf, const int key_size, void **data_buf_p, int *data_size_p);
+extern int table_delete_first(table_t *table_p, void **key_buf_p, int *key_size_p, void **data_buf_p, int *data_size_p);
+extern int table_info(table_t *table_p, int *num_buckets_p, int *num_entries_p);
+extern int table_adjust(table_t *table_p, const int bucket_n);
+extern const char *table_strerror(const int error);
+extern int table_type_size(void);
+extern int table_first(table_t *table_p, void **key_buf_p, int *key_size_p, void **data_buf_p, int *data_size_p);
+extern int table_next(table_t *table_p, void **key_buf_p, int *key_size_p, void **data_buf_p, int *data_size_p);
+extern int table_this(table_t *table_p, void **key_buf_p, int *key_size_p, void **data_buf_p, int *data_size_p);
+extern int table_first_r(table_t *table_p, table_linear_t *linear_p, void **key_buf_p, int *key_size_p, void **data_buf_p, int *data_size_p);
+extern int table_next_r(table_t *table_p, table_linear_t *linear_p, void **key_buf_p, int *key_size_p, void **data_buf_p, int *data_size_p);
+extern int table_this_r(table_t *table_p, table_linear_t *linear_p, void **key_buf_p, int *key_size_p, void **data_buf_p, int *data_size_p);
+extern table_t *table_read(const char *path, int *error_p, void *(*malloc_f)(size_t size), void *(*calloc_f)(size_t number, size_t size), void *(*realloc_f)(void *ptr, size_t size), void (*free_f)(void *ptr));
+extern int table_write(const table_t *table_p, const char *path, const int mode);
+extern table_entry_t **table_order(table_t *table_p, table_compare_t compare, int *num_entries_p, int *error_p);
+extern int table_entry_info(table_t *table_p, table_entry_t *entry_p, void **key_buf_p, int *key_size_p, void **data_buf_p, int *data_size_p);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* ! SSL_UTIL_TABLE_H */
diff --git a/usr.sbin/httpd/src/modules/standard/Makefile.OS2 b/usr.sbin/httpd/src/modules/standard/Makefile.OS2
new file mode 100644
index 00000000000..49df7d25f97
--- /dev/null
+++ b/usr.sbin/httpd/src/modules/standard/Makefile.OS2
@@ -0,0 +1,115 @@
+# Extra rules for making DLLs for OS/2
+
+define mkdll
+$(LD_SHLIB) $(LDFLAGS_SHLIB) -o $* $(<:%.c=%.o) $(LIBS_SHLIB) $(LIBS1) $(<:%.o=%.def) && \
+emxbind -b -q -s -h0 -d$(<:%.o=%.def) $* && \
+rm $*
+endef
+
+
+%.def : %.c
+ echo "LIBRARY $* INITINSTANCE" > $@
+ echo "EXPORTS" >> $@
+ grep "^module .*=" $< | sed "s/module.* \(.*\) =.*/ \1/" >> $@
+
+access.dll: mod_access.o mod_access.def
+ $(mkdll)
+
+actions.dll: mod_actions.o mod_actions.def
+ $(mkdll)
+
+alias.dll: mod_alias.o mod_alias.def
+ $(mkdll)
+
+asis.dll: mod_asis.o mod_asis.def
+ $(mkdll)
+
+auth.dll: mod_auth.o mod_auth.def
+ $(mkdll)
+
+auth_ano.dll: mod_auth_anon.o mod_auth_anon.def
+ $(mkdll)
+
+auth_db.dll: mod_auth_db.o mod_auth_db.def
+ $(mkdll)
+
+auth_dbm.dll: mod_auth_dbm.o mod_auth_dbm.def
+ $(mkdll)
+
+autoinde.dll: mod_autoindex.o mod_autoindex.def
+ $(mkdll)
+
+cern_met.dll: mod_cern_meta.o mod_cern_meta.def
+ $(mkdll)
+
+cgi.dll: mod_cgi.o mod_cgi.def
+ $(mkdll)
+
+digest.dll: mod_digest.o mod_digest.def
+ $(mkdll)
+
+dir.dll: mod_dir.o mod_dir.def
+ $(mkdll)
+
+env.dll: mod_env.o mod_env.def
+ $(mkdll)
+
+expires.dll: mod_expires.o mod_expires.def
+ $(mkdll)
+
+headers.dll: mod_headers.o mod_headers.def
+ $(mkdll)
+
+imap.dll: mod_imap.o mod_imap.def
+ $(mkdll)
+
+include.dll: mod_include.o mod_include.def
+ $(mkdll)
+
+info.dll: mod_info.o mod_info.def
+ $(mkdll)
+
+log_agen.dll: mod_log_agent.o mod_log_agent.def
+ $(mkdll)
+
+log_conf.dll: mod_log_config.o mod_log_config.def
+ $(mkdll)
+
+log_refe.dll: mod_log_referer.o mod_log_referer.def
+ $(mkdll)
+
+mime.dll: mod_mime.o mod_mime.def
+ $(mkdll)
+
+mime_mag.dll: mod_mime_magic.o mod_mime_magic.def
+ $(mkdll)
+
+negotiat.dll: mod_negotiation.o mod_negotiation.def
+ $(mkdll)
+
+rewrite.dll: mod_rewrite.o mod_rewrite.def
+ $(mkdll)
+
+setenvif.dll: mod_setenvif.o mod_setenvif.def
+ $(mkdll)
+
+so.dll: mod_so.o mod_so.def
+ $(mkdll)
+
+speling.dll: mod_speling.o mod_speling.def
+ $(mkdll)
+
+status.dll: mod_status.o mod_status.def
+ $(mkdll)
+
+unique_i.dll: mod_unique_id.o mod_unique_id.def
+ $(mkdll)
+
+userdir.dll: mod_userdir.o mod_userdir.def
+ $(mkdll)
+
+usertrac.dll: mod_usertrack.o mod_usertrack.def
+ $(mkdll)
+
+vhost_al.dll: mod_vhost_alias.o mod_vhost_alias.def
+ $(mkdll)
diff --git a/usr.sbin/httpd/src/modules/standard/mod_access.c b/usr.sbin/httpd/src/modules/standard/mod_access.c
index f681e95501f..6179510451c 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_access.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_access.c
@@ -202,7 +202,7 @@ static const char *allow_cmd(cmd_parms *cmd, void *dv, char *from, char *where)
mask = htonl(mask);
}
a->x.ip.mask = mask;
-
+ a->x.ip.net = (a->x.ip.net & mask); /* pjr - This fixes PR 4770 */
}
else if (ap_isdigit(*where) && is_ip(where)) {
/* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
diff --git a/usr.sbin/httpd/src/modules/standard/mod_alias.c b/usr.sbin/httpd/src/modules/standard/mod_alias.c
index b7f5ba3d96c..f92d982d233 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_alias.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_alias.c
@@ -300,7 +300,7 @@ static char *try_alias_list(request_rec *r, array_header *aliases, int doesc, in
int l;
if (p->regexp) {
- if (!regexec(p->regexp, r->uri, p->regexp->re_nsub + 1, regm, 0)) {
+ if (!ap_regexec(p->regexp, r->uri, p->regexp->re_nsub + 1, regm, 0)) {
if (p->real) {
found = ap_pregsub(r->pool, p->real, r->uri,
p->regexp->re_nsub + 1, regm);
diff --git a/usr.sbin/httpd/src/modules/standard/mod_auth.c b/usr.sbin/httpd/src/modules/standard/mod_auth.c
index 11df5645926..e07dc453733 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_auth.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_auth.c
@@ -74,9 +74,6 @@
#include "http_core.h"
#include "http_log.h"
#include "http_protocol.h"
-#if defined(HAVE_CRYPT_H)
-#include <crypt.h>
-#endif
typedef struct auth_config_struct {
char *auth_pwfile;
@@ -203,6 +200,7 @@ static int authenticate_basic_user(request_rec *r)
conn_rec *c = r->connection;
const char *sent_pw;
char *real_pw;
+ char *invalid_pw;
int res;
if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
@@ -219,10 +217,11 @@ static int authenticate_basic_user(request_rec *r)
ap_note_basic_auth_failure(r);
return AUTH_REQUIRED;
}
- /* anyone know where the prototype for crypt is? */
- if (strcmp(real_pw, (char *) crypt(sent_pw, real_pw))) {
+ invalid_pw = ap_validate_password(sent_pw, real_pw);
+ if (invalid_pw != NULL) {
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
- "user %s: password mismatch: %s", c->user, r->uri);
+ "user %s: authentication failure for \"%s\": %s",
+ c->user, r->uri, invalid_pw);
ap_note_basic_auth_failure(r);
return AUTH_REQUIRED;
}
diff --git a/usr.sbin/httpd/src/modules/standard/mod_auth_db.c b/usr.sbin/httpd/src/modules/standard/mod_auth_db.c
index 5571f7b51c8..e09e8eb6c4b 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_auth_db.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_auth_db.c
@@ -226,6 +226,7 @@ static int db_authenticate_basic_user(request_rec *r)
conn_rec *c = r->connection;
const char *sent_pw;
char *real_pw, *colon_pw;
+ char *invalid_pw;
int res;
if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
@@ -244,12 +245,14 @@ static int db_authenticate_basic_user(request_rec *r)
}
/* Password is up to first : if exists */
colon_pw = strchr(real_pw, ':');
- if (colon_pw)
+ if (colon_pw) {
*colon_pw = '\0';
- /* anyone know where the prototype for crypt is? */
- if (strcmp(real_pw, (char *) crypt(sent_pw, real_pw))) {
+ }
+ invalid_pw = ap_validate_password(sent_pw, real_pw);
+ if (invalid_pw != NULL) {
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
- "DB user %s: password mismatch: %s", c->user, r->uri);
+ "DB user %s: authentication failure for \"%s\": %s",
+ c->user, r->uri, invalid_pw);
ap_note_basic_auth_failure(r);
return AUTH_REQUIRED;
}
diff --git a/usr.sbin/httpd/src/modules/standard/mod_auth_dbm.c b/usr.sbin/httpd/src/modules/standard/mod_auth_dbm.c
index a91838b4c2b..bb32361a6d9 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_auth_dbm.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_auth_dbm.c
@@ -74,7 +74,12 @@
#include "http_core.h"
#include "http_log.h"
#include "http_protocol.h"
+#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) \
+ && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
+#include <db1/ndbm.h>
+#else
#include <ndbm.h>
+#endif
/*
* Module definition information - the part between the -START and -END
@@ -208,6 +213,7 @@ static int dbm_authenticate_basic_user(request_rec *r)
conn_rec *c = r->connection;
const char *sent_pw;
char *real_pw, *colon_pw;
+ char *invalid_pw;
int res;
if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
@@ -226,12 +232,14 @@ static int dbm_authenticate_basic_user(request_rec *r)
}
/* Password is up to first : if exists */
colon_pw = strchr(real_pw, ':');
- if (colon_pw)
+ if (colon_pw) {
*colon_pw = '\0';
- /* anyone know where the prototype for crypt is? */
- if (strcmp(real_pw, (char *) crypt(sent_pw, real_pw))) {
+ }
+ invalid_pw = ap_validate_password(sent_pw, real_pw);
+ if (invalid_pw != NULL) {
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
- "user %s: password mismatch: %s", c->user, r->uri);
+ "DBM user %s: authentication failure for \"%s\": %s",
+ c->user, r->uri, invalid_pw);
ap_note_basic_auth_failure(r);
return AUTH_REQUIRED;
}
diff --git a/usr.sbin/httpd/src/modules/standard/mod_autoindex.c b/usr.sbin/httpd/src/modules/standard/mod_autoindex.c
index 10436261aff..9c28dc40864 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_autoindex.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_autoindex.c
@@ -72,6 +72,7 @@
#include "http_log.h"
#include "http_main.h"
#include "util_script.h"
+#include "fnmatch.h"
module MODULE_VAR_EXPORT autoindex_module;
@@ -131,6 +132,13 @@ struct item {
char *data;
};
+typedef struct ai_desc_t {
+ char *pattern;
+ char *description;
+ int full_path;
+ int wildcards;
+} ai_desc_t;
+
typedef struct autoindex_config_struct {
char *default_icon;
@@ -143,8 +151,12 @@ typedef struct autoindex_config_struct {
int icon_height;
char *default_order;
- array_header *icon_list, *alt_list, *desc_list, *ign_list;
- array_header *hdr_list, *rdme_list;
+ array_header *icon_list;
+ array_header *alt_list;
+ array_header *desc_list;
+ array_header *ign_list;
+ array_header *hdr_list;
+ array_header *rdme_list;
} autoindex_config_rec;
@@ -180,7 +192,7 @@ static ap_inline int is_parent(const char *name)
*/
static void emit_preamble(request_rec *r, char *title)
{
- ap_rvputs(r, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n",
+ ap_rvputs(r, DOCTYPE_HTML_3_2,
"<HTML>\n <HEAD>\n <TITLE>Index of ", title,
"</TITLE>\n </HEAD>\n <BODY>\n", NULL);
}
@@ -257,10 +269,48 @@ static const char *add_icon(cmd_parms *cmd, void *d, char *icon, char *to)
return NULL;
}
+/*
+ * Add description text for a filename pattern. If the pattern has
+ * wildcards already (or we need to add them), add leading and
+ * trailing wildcards to it to ensure substring processing. If the
+ * pattern contains a '/' anywhere, force wildcard matching mode,
+ * add a slash to the prefix so that "bar/bletch" won't be matched
+ * by "foobar/bletch", and make a note that there's a delimiter;
+ * the matching routine simplifies to just the actual filename
+ * whenever it can. This allows definitions in parent directories
+ * to be made for files in subordinate ones using relative paths.
+ */
+
+/*
+ * Absent a strcasestr() function, we have to force wildcards on
+ * systems for which "AAA" and "aaa" mean the same file.
+ */
+#ifdef CASE_BLIND_FILESYSTEM
+#define WILDCARDS_REQUIRED 1
+#else
+#define WILDCARDS_REQUIRED 0
+#endif
+
static const char *add_desc(cmd_parms *cmd, void *d, char *desc, char *to)
{
- push_item(((autoindex_config_rec *) d)->desc_list, cmd->info, to,
- cmd->path, desc);
+ autoindex_config_rec *dcfg = (autoindex_config_rec *) d;
+ ai_desc_t *desc_entry;
+ char *prefix = "";
+
+ desc_entry = (ai_desc_t *) ap_push_array(dcfg->desc_list);
+ desc_entry->full_path = (strchr(to, '/') == NULL) ? 0 : 1;
+ desc_entry->wildcards = (WILDCARDS_REQUIRED
+ || desc_entry->full_path
+ || ap_is_fnmatch(to));
+ if (desc_entry->wildcards) {
+ prefix = desc_entry->full_path ? "*/" : "*";
+ desc_entry->pattern = ap_pstrcat(dcfg->desc_list->pool,
+ prefix, to, "*", NULL);
+ }
+ else {
+ desc_entry->pattern = ap_pstrdup(dcfg->desc_list->pool, to);
+ }
+ desc_entry->description = ap_pstrdup(dcfg->desc_list->pool, desc);
return NULL;
}
@@ -272,9 +322,6 @@ static const char *add_ignore(cmd_parms *cmd, void *d, char *ext)
static const char *add_header(cmd_parms *cmd, void *d, char *name)
{
- if (strchr(name, '/')) {
- return "HeaderName cannot contain a /";
- }
push_item(((autoindex_config_rec *) d)->hdr_list, 0, NULL, cmd->path,
name);
return NULL;
@@ -282,9 +329,6 @@ static const char *add_header(cmd_parms *cmd, void *d, char *name)
static const char *add_readme(cmd_parms *cmd, void *d, char *name)
{
- if (strchr(name, '/')) {
- return "ReadmeName cannot contain a /";
- }
push_item(((autoindex_config_rec *) d)->rdme_list, 0, NULL, cmd->path,
name);
return NULL;
@@ -410,8 +454,8 @@ static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr)
else {
int width = atoi(&w[10]);
- if (width < 1) {
- return "NameWidth value must be greater than 1";
+ if (width < 5) {
+ return "NameWidth value must be greater than 5";
}
d_cfg->name_width = width;
d_cfg->name_adjust = K_NOADJUST;
@@ -530,7 +574,7 @@ static void *create_autoindex_config(pool *p, char *dummy)
new->name_adjust = K_UNSET;
new->icon_list = ap_make_array(p, 4, sizeof(struct item));
new->alt_list = ap_make_array(p, 4, sizeof(struct item));
- new->desc_list = ap_make_array(p, 4, sizeof(struct item));
+ new->desc_list = ap_make_array(p, 4, sizeof(ai_desc_t));
new->ign_list = ap_make_array(p, 4, sizeof(struct item));
new->hdr_list = ap_make_array(p, 4, sizeof(struct item));
new->rdme_list = ap_make_array(p, 4, sizeof(struct item));
@@ -688,7 +732,6 @@ static char *find_item(request_rec *r, array_header *list, int path_only)
#define find_icon(d,p,t) find_item(p,d->icon_list,t)
#define find_alt(d,p,t) find_item(p,d->alt_list,t)
-#define find_desc(d,p) find_item(p,d->desc_list,0)
#define find_header(d,p) find_item(p,d->hdr_list,0)
#define find_readme(d,p) find_item(p,d->rdme_list,0)
@@ -707,6 +750,63 @@ static char *find_default_icon(autoindex_config_rec *d, char *bogus_name)
return find_item(&r, d->icon_list, 1);
}
+/*
+ * Look through the list of pattern/description pairs and return the first one
+ * if any) that matches the filename in the request. If multiple patterns
+ * match, only the first one is used; since the order in the array is the
+ * same as the order in which directives were processed, earlier matching
+ * directives will dominate.
+ */
+
+#ifdef CASE_BLIND_FILESYSTEM
+#define MATCH_FLAGS FNM_CASE_BLIND
+#else
+#define MATCH_FLAGS 0
+#endif
+
+static char *find_desc(autoindex_config_rec *dcfg, request_rec *r)
+{
+ int i;
+ ai_desc_t *list = (ai_desc_t *) dcfg->desc_list->elts;
+ const char *filename_full = r->filename;
+ const char *filename_only;
+ const char *filename;
+
+ /*
+ * If the filename includes a path, extract just the name itself
+ * for the simple matches.
+ */
+ if ((filename_only = strrchr(filename_full, '/')) == NULL) {
+ filename_only = filename_full;
+ }
+ else {
+ filename_only++;
+ }
+ for (i = 0; i < dcfg->desc_list->nelts; ++i) {
+ ai_desc_t *tuple = &list[i];
+ int found;
+
+ /*
+ * Only use the full-path filename if the pattern contains '/'s.
+ */
+ filename = (tuple->full_path) ? filename_full : filename_only;
+ /*
+ * Make the comparison using the cheapest method; only do
+ * wildcard checking if we must.
+ */
+ if (tuple->wildcards) {
+ found = (ap_fnmatch(tuple->pattern, filename, MATCH_FLAGS) == 0);
+ }
+ else {
+ found = (strstr(filename, tuple->pattern) != NULL);
+ }
+ if (found) {
+ return tuple->description;
+ }
+ }
+ return NULL;
+}
+
static int ignore_entry(autoindex_config_rec *d, char *path)
{
array_header *list = d->ign_list;
@@ -758,99 +858,217 @@ static int ignore_entry(autoindex_config_rec *d, char *path)
*/
/*
- * Look for the specified file, and pump it into the response stream if we
- * find it.
+ * Elements of the emitted document:
+ * Preamble
+ * Emitted unless SUPPRESS_PREAMBLE is set AND ap_run_sub_req
+ * succeeds for the (content_type == text/html) header file.
+ * Header file
+ * Emitted if found (and able).
+ * H1 tag line
+ * Emitted if a header file is NOT emitted.
+ * Directory stuff
+ * Always emitted.
+ * HR
+ * Emitted if FANCY_INDEXING is set.
+ * Readme file
+ * Emitted if found (and able).
+ * ServerSig
+ * Emitted if ServerSignature is not Off AND a readme file
+ * is NOT emitted.
+ * Postamble
+ * Emitted unless SUPPRESS_PREAMBLE is set AND ap_run_sub_req
+ * succeeds for the (content_type == text/html) readme file.
*/
-static int insert_readme(char *name, char *readme_fname, char *title,
- int hrule, int whichend, request_rec *r)
+
+
+/*
+ * emit a plain text file
+ */
+static void do_emit_plain(request_rec *r, FILE *f)
{
- char *fn;
- FILE *f;
- struct stat finfo;
- int plaintext = 0;
- request_rec *rr;
- autoindex_config_rec *cfg;
- int autoindex_opts;
-
- cfg = (autoindex_config_rec *) ap_get_module_config(r->per_dir_config,
- &autoindex_module);
- autoindex_opts = cfg->opts;
- /* XXX: this is a load of crap, it needs to do a full sub_req_lookup_uri */
- fn = ap_make_full_path(r->pool, name, readme_fname);
- fn = ap_pstrcat(r->pool, fn, ".html", NULL);
- if (stat(fn, &finfo) == -1) {
- /* A brief fake multiviews search for README.html */
- fn[strlen(fn) - 5] = '\0';
- if (stat(fn, &finfo) == -1) {
- return 0;
+ char buf[IOBUFSIZE + 1];
+ int i, n, c, ch;
+
+ ap_rputs("<PRE>\n", r);
+ while (!feof(f)) {
+ do {
+ n = fread(buf, sizeof(char), IOBUFSIZE, f);
}
- plaintext = 1;
- if (hrule) {
- ap_rputs("<HR>\n", r);
+ while (n == -1 && ferror(f) && errno == EINTR);
+ if (n == -1 || n == 0) {
+ break;
+ }
+ buf[n] = '\0';
+ c = 0;
+ while (c < n) {
+ for (i = c; i < n; i++) {
+ if (buf[i] == '<' || buf[i] == '>' || buf[i] == '&') {
+ break;
+ }
+ }
+ ch = buf[i];
+ buf[i] = '\0';
+ ap_rputs(&buf[c], r);
+ if (ch == '<') {
+ ap_rputs("&lt;", r);
+ }
+ else if (ch == '>') {
+ ap_rputs("&gt;", r);
+ }
+ else if (ch == '&') {
+ ap_rputs("&amp;", r);
+ }
+ c = i + 1;
}
}
- else if (hrule) {
- ap_rputs("<HR>\n", r);
- }
- /* XXX: when the above is rewritten properly, this necessary security
- * check will be redundant. -djg */
- rr = ap_sub_req_lookup_file(fn, r);
- if (rr->status != HTTP_OK) {
- ap_destroy_sub_req(rr);
- return 0;
- }
- ap_destroy_sub_req(rr);
- if (!(f = ap_pfopen(r->pool, fn, "r"))) {
- return 0;
+ ap_rputs("</PRE>\n", r);
+}
+
+/*
+ * Handle the preamble through the H1 tag line, inclusive. Locate
+ * the file with a subrequests. Process text/html documents by actually
+ * running the subrequest; text/xxx documents get copied verbatim,
+ * and any other content type is ignored. This means that a non-text
+ * document (such as HEADER.gif) might get multiviewed as the result
+ * instead of a text document, meaning nothing will be displayed, but
+ * oh well.
+ */
+static void emit_head(request_rec *r, char *header_fname, int suppress_amble,
+ char *title)
+{
+ FILE *f;
+ request_rec *rr = NULL;
+ int emit_amble = 1;
+ int emit_H1 = 1;
+
+ /*
+ * If there's a header file, send a subrequest to look for it. If it's
+ * found and a text file, handle it -- otherwise fall through and
+ * pretend there's nothing there.
+ */
+ if ((header_fname != NULL)
+ && (rr = ap_sub_req_lookup_uri(header_fname, r))
+ && (rr->status == HTTP_OK)
+ && (rr->filename != NULL)
+ && S_ISREG(rr->finfo.st_mode)) {
+ /*
+ * Check for the two specific cases we allow: text/html and
+ * text/anything-else. The former is allowed to be processed for
+ * SSIs.
+ */
+ if (rr->content_type != NULL) {
+ if (!strcasecmp(ap_field_noparam(r->pool, rr->content_type),
+ "text/html")) {
+ /* Hope everything will work... */
+ emit_amble = 0;
+ emit_H1 = 0;
+
+ if (! suppress_amble) {
+ emit_preamble(r, title);
+ }
+ /*
+ * If there's a problem running the subrequest, display the
+ * preamble if we didn't do it before -- the header file
+ * didn't get displayed.
+ */
+ if (ap_run_sub_req(rr) != OK) {
+ /* It didn't work */
+ emit_amble = suppress_amble;
+ emit_H1 = 1;
+ }
+ }
+ else if (!strncasecmp("text/", rr->content_type, 5)) {
+ /*
+ * If we can open the file, prefix it with the preamble
+ * regardless; since we'll be sending a <PRE> block around
+ * the file's contents, any HTML header it had won't end up
+ * where it belongs.
+ */
+ if ((f = ap_pfopen(r->pool, rr->filename, "r")) != 0) {
+ emit_preamble(r, title);
+ emit_amble = 0;
+ do_emit_plain(r, f);
+ ap_pfclose(r->pool, f);
+ emit_H1 = 0;
+ }
+ }
+ }
}
- if ((whichend == FRONT_MATTER)
- && (!(autoindex_opts & SUPPRESS_PREAMBLE))) {
+
+ if (emit_amble) {
emit_preamble(r, title);
}
- if (!plaintext) {
- ap_send_fd(f, r);
+ if (emit_H1) {
+ ap_rvputs(r, "<H1>Index of ", title, "</H1>\n", NULL);
}
- else {
- char buf[IOBUFSIZE + 1];
- int i, n, c, ch;
- ap_rputs("<PRE>\n", r);
- while (!feof(f)) {
- do {
- n = fread(buf, sizeof(char), IOBUFSIZE, f);
- }
- while (n == -1 && ferror(f) && errno == EINTR);
- if (n == -1 || n == 0) {
- break;
- }
- buf[n] = '\0';
- c = 0;
- while (c < n) {
- for (i = c; i < n; i++) {
- if (buf[i] == '<' || buf[i] == '>' || buf[i] == '&') {
- break;
- }
- }
- ch = buf[i];
- buf[i] = '\0';
- ap_rputs(&buf[c], r);
- if (ch == '<') {
- ap_rputs("&lt;", r);
- }
- else if (ch == '>') {
- ap_rputs("&gt;", r);
+ if (rr != NULL) {
+ ap_destroy_sub_req(rr);
+ }
+}
+
+
+/*
+ * Handle the Readme file through the postamble, inclusive. Locate
+ * the file with a subrequests. Process text/html documents by actually
+ * running the subrequest; text/xxx documents get copied verbatim,
+ * and any other content type is ignored. This means that a non-text
+ * document (such as FOOTER.gif) might get multiviewed as the result
+ * instead of a text document, meaning nothing will be displayed, but
+ * oh well.
+ */
+static void emit_tail(request_rec *r, char *readme_fname, int suppress_amble)
+{
+ FILE *f;
+ request_rec *rr = NULL;
+ int suppress_post = 0;
+ int suppress_sig = 0;
+
+ /*
+ * If there's a readme file, send a subrequest to look for it. If it's
+ * found and a text file, handle it -- otherwise fall through and
+ * pretend there's nothing there.
+ */
+ if ((readme_fname != NULL)
+ && (rr = ap_sub_req_lookup_uri(readme_fname, r))
+ && (rr->status == HTTP_OK)
+ && (rr->filename != NULL)
+ && S_ISREG(rr->finfo.st_mode)) {
+ /*
+ * Check for the two specific cases we allow: text/html and
+ * text/anything-else. The former is allowed to be processed for
+ * SSIs.
+ */
+ if (rr->content_type != NULL) {
+ if (!strcasecmp(ap_field_noparam(r->pool, rr->content_type),
+ "text/html")) {
+ if (ap_run_sub_req(rr) == OK) {
+ /* worked... */
+ suppress_sig = 1;
+ suppress_post = suppress_amble;
}
- else if (ch == '&') {
- ap_rputs("&amp;", r);
+ }
+ else if (!strncasecmp("text/", rr->content_type, 5)) {
+ /*
+ * If we can open the file, suppress the signature.
+ */
+ if ((f = ap_pfopen(r->pool, rr->filename, "r")) != 0) {
+ do_emit_plain(r, f);
+ ap_pfclose(r->pool, f);
+ suppress_sig = 1;
}
- c = i + 1;
}
}
}
- ap_pfclose(r->pool, f);
- if (plaintext) {
- ap_rputs("</PRE>\n", r);
+
+ if (!suppress_sig) {
+ ap_rputs(ap_psignature("", r), r);
+ }
+ if (!suppress_post) {
+ ap_rputs("</BODY></HTML>\n", r);
+ }
+ if (rr != NULL) {
+ ap_destroy_sub_req(rr);
}
- return 1;
}
@@ -863,8 +1081,9 @@ static char *find_title(request_rec *r)
if (r->status != HTTP_OK) {
return NULL;
}
- if (r->content_type
- && (!strcmp(r->content_type, "text/html")
+ if ((r->content_type != NULL)
+ && (!strcasecmp(ap_field_noparam(r->pool, r->content_type),
+ "text/html")
|| !strcmp(r->content_type, INCLUDES_MAGIC_TYPE))
&& !r->content_encoding) {
if (!(thefile = ap_pfopen(r->pool, r->filename, "r"))) {
@@ -1042,41 +1261,6 @@ static void emit_link(request_rec *r, char *anchor, char fname, char curkey,
}
}
-/*
- * Fit a string into a specified buffer width, marking any
- * truncation. The size argument is the actual buffer size, including
- * the \0 termination byte. The buffer will be prefilled with blanks.
- * If the pad argument is false, any extra spaces at the end of the
- * buffer are omitted. (Used when constructing anchors.)
- */
-static ap_inline char *widthify(const char *s, char *buff, int size, int pad)
-{
- int s_len;
-
- memset(buff, ' ', size);
- buff[size - 1] = '\0';
- s_len = strlen(s);
- if (s_len > (size - 1)) {
- ap_cpystrn(buff, s, size);
- if (size > 1) {
- buff[size - 2] = '>';
- }
- if (size > 2) {
- buff[size - 3] = '.';
- }
- if (size > 3) {
- buff[size - 4] = '.';
- }
- }
- else {
- ap_cpystrn(buff, s, s_len + 1);
- if (pad) {
- buff[s_len] = ' ';
- }
- }
- return buff;
-}
-
static void output_directories(struct ent **ar, int n,
autoindex_config_rec *d, request_rec *r,
int autoindex_opts, char keyid, char direction)
@@ -1088,6 +1272,7 @@ static void output_directories(struct ent **ar, int n,
pool *scratch = ap_make_sub_pool(r->pool);
int name_width;
char *name_scratch;
+ char *pad_scratch;
if (name[0] == '\0') {
name = "/";
@@ -1102,10 +1287,10 @@ static void output_directories(struct ent **ar, int n,
}
}
}
- ++name_width;
name_scratch = ap_palloc(r->pool, name_width + 1);
- memset(name_scratch, ' ', name_width);
- name_scratch[name_width] = '\0';
+ pad_scratch = ap_palloc(r->pool, name_width + 1);
+ memset(pad_scratch, ' ', name_width);
+ pad_scratch[name_width] = '\0';
if (autoindex_opts & FANCY_INDEXING) {
ap_rputs("<PRE>", r);
@@ -1123,14 +1308,8 @@ static void output_directories(struct ent **ar, int n,
}
ap_rputs("> ", r);
}
- emit_link(r, widthify("Name", name_scratch,
- (name_width > 5) ? 5 : name_width, K_NOPAD),
- K_NAME, keyid, direction, static_columns);
- if (name_width > 5) {
- memset(name_scratch, ' ', name_width);
- name_scratch[name_width] = '\0';
- ap_rputs(&name_scratch[5], r);
- }
+ emit_link(r, "Name", K_NAME, keyid, direction, static_columns);
+ ap_rputs(pad_scratch + 4, r);
/*
* Emit the guaranteed-at-least-one-space-between-columns byte.
*/
@@ -1156,7 +1335,6 @@ static void output_directories(struct ent **ar, int n,
for (x = 0; x < n; x++) {
char *anchor, *t, *t2;
- char *pad;
int nwidth;
ap_clear_pool(scratch);
@@ -1167,15 +1345,12 @@ static void output_directories(struct ent **ar, int n,
if (t[0] == '\0') {
t = "/";
}
- /* 1234567890123456 */
t2 = "Parent Directory";
- pad = name_scratch + 16;
anchor = ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0));
}
else {
t = ar[x]->name;
- pad = name_scratch + strlen(t);
- t2 = ap_escape_html(scratch, t);
+ t2 = t;
anchor = ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0));
}
@@ -1200,18 +1375,19 @@ static void output_directories(struct ent **ar, int n,
ap_rputs("</A>", r);
}
- ap_rvputs(r, " <A HREF=\"", anchor, "\">",
- widthify(t2, name_scratch, name_width, K_NOPAD),
- "</A>", NULL);
- /*
- * We know that widthify() prefilled the buffer with spaces
- * before doing its thing, so use them.
- */
nwidth = strlen(t2);
- if (nwidth < (name_width - 1)) {
- name_scratch[nwidth] = ' ';
- ap_rputs(&name_scratch[nwidth], r);
+ if (nwidth > name_width) {
+ memcpy(name_scratch, t2, name_width - 3);
+ name_scratch[name_width - 3] = '.';
+ name_scratch[name_width - 2] = '.';
+ name_scratch[name_width - 1] = '>';
+ name_scratch[name_width] = 0;
+ t2 = name_scratch;
+ nwidth = name_width;
}
+ ap_rvputs(r, " <A HREF=\"", anchor, "\">",
+ ap_escape_html(scratch, t2), "</A>", pad_scratch + nwidth,
+ NULL);
/*
* The blank before the storm.. er, before the next field.
*/
@@ -1241,7 +1417,7 @@ static void output_directories(struct ent **ar, int n,
}
else {
ap_rvputs(r, "<LI><A HREF=\"", anchor, "\"> ", t2,
- "</A>", pad, NULL);
+ "</A>", NULL);
}
ap_rputc('\n', r);
}
@@ -1326,7 +1502,6 @@ static int index_directory(request_rec *r,
int num_ent = 0, x;
struct ent *head, *p;
struct ent **ar = NULL;
- char *tmp;
const char *qstring;
int autoindex_opts = autoindex_conf->opts;
char keyid;
@@ -1356,12 +1531,8 @@ static int index_directory(request_rec *r,
*title_endp-- = '\0';
}
- if ((!(tmp = find_header(autoindex_conf, r)))
- || (!(insert_readme(name, tmp, title_name, NO_HRULE, FRONT_MATTER, r)))
- ) {
- emit_preamble(r, title_name);
- ap_rvputs(r, "<H1>Index of ", title_name, "</H1>\n", NULL);
- }
+ emit_head(r, find_header(autoindex_conf, r),
+ autoindex_opts & SUPPRESS_PREAMBLE, title_name);
/*
* Figure out what sort of indexing (if any) we're supposed to use.
@@ -1426,15 +1597,11 @@ static int index_directory(request_rec *r,
direction);
ap_pclosedir(r->pool, d);
- if ((tmp = find_readme(autoindex_conf, r))) {
- if (!insert_readme(name, tmp, "",
- ((autoindex_opts & FANCY_INDEXING) ? HRULE
- : NO_HRULE),
- END_MATTER, r)) {
- ap_rputs(ap_psignature("<HR>\n", r), r);
- }
+ if (autoindex_opts & FANCY_INDEXING) {
+ ap_rputs("<HR>\n", r);
}
- ap_rputs("</BODY></HTML>\n", r);
+ emit_tail(r, find_readme(autoindex_conf, r),
+ autoindex_opts & SUPPRESS_PREAMBLE);
ap_kill_timeout(r);
return 0;
diff --git a/usr.sbin/httpd/src/modules/standard/mod_cgi.c b/usr.sbin/httpd/src/modules/standard/mod_cgi.c
index 9091d0d9be0..392fb5a1f13 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_cgi.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_cgi.c
@@ -210,8 +210,19 @@ static int log_script(request_rec *r, cgi_server_conf * conf, int ret,
/* Soak up script output */
while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0)
continue;
+#ifdef WIN32
+ /* Soak up stderr and redirect it to the error log.
+ * Script output to stderr is already directed to the error log
+ * on Unix, thanks to the magic of fork().
+ */
+ while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r,
+ "%s", argsbuffer);
+ }
+#else
while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0)
continue;
+#endif
return ret;
}
@@ -275,6 +286,9 @@ static int log_script(request_rec *r, cgi_server_conf * conf, int ret,
struct cgi_child_stuff {
+#ifdef TPF
+ TPF_FORK_CHILD t;
+#endif
request_rec *r;
int nph;
int debug;
@@ -325,10 +339,13 @@ static int cgi_child(void *child_stuff, child_info *pinfo)
* NB only ISINDEX scripts get decoded arguments.
*/
+#ifdef TPF
+ return (0);
+#else
ap_cleanup_for_exec();
child_pid = ap_call_exec(r, pinfo, argv0, env, 0);
-#ifdef WIN32
+#if defined(WIN32) || defined(OS2)
return (child_pid);
#else
@@ -346,6 +363,7 @@ static int cgi_child(void *child_stuff, child_info *pinfo)
/* NOT REACHED */
return (0);
#endif
+#endif /* TPF */
}
static int cgi_handler(request_rec *r)
@@ -419,6 +437,11 @@ static int cgi_handler(request_rec *r)
cld.r = r;
cld.nph = nph;
cld.debug = conf->logname ? 1 : 0;
+#ifdef TPF
+ cld.t.filename = r->filename;
+ cld.t.subprocess_env = r->subprocess_env;
+ cld.t.prog_type = FORK_FILE;
+#endif /* TPF */
#ifdef CHARSET_EBCDIC
/* XXX:@@@ Is the generated/included output ALWAYS in text/ebcdic format? */
@@ -440,16 +463,10 @@ static int cgi_handler(request_rec *r)
}
/* Transfer any put/post args, CERN style...
- * Note that if a buggy script fails to read everything we throw
- * at it, or a buggy client sends too much, we get a SIGPIPE, so
- * we have to ignore SIGPIPE while doing this. CERN does the same
- * (and in fact, they pretty nearly guarantee themselves a SIGPIPE
- * on every invocation by chasing the real client data with a
- * spurious newline).
+ * Note that we already ignore SIGPIPE in the core server.
*/
if (ap_should_client_block(r)) {
- void (*handler) (int);
int dbsize, len_read;
if (conf->logname) {
@@ -458,9 +475,6 @@ static int cgi_handler(request_rec *r)
}
ap_hard_timeout("copy script args", r);
-#ifdef SIGPIPE
- handler = signal(SIGPIPE, SIG_IGN);
-#endif
while ((len_read =
ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN)) > 0) {
@@ -485,7 +499,6 @@ static int cgi_handler(request_rec *r)
}
ap_bflush(script_out);
- signal(SIGPIPE, handler);
ap_kill_timeout(r);
}
diff --git a/usr.sbin/httpd/src/modules/standard/mod_dir.c b/usr.sbin/httpd/src/modules/standard/mod_dir.c
index 04fbd1458c3..a32b390a88b 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_dir.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_dir.c
@@ -161,7 +161,7 @@ static int handle_dir(request_rec *r)
char *name_ptr = *names_ptr;
request_rec *rr = ap_sub_req_lookup_uri(name_ptr, r);
- if (rr->status == HTTP_OK && rr->finfo.st_mode != 0) {
+ if (rr->status == HTTP_OK && S_ISREG(rr->finfo.st_mode)) {
char *new_uri = ap_escape_uri(r->pool, rr->uri);
if (rr->args != NULL)
@@ -179,13 +179,13 @@ static int handle_dir(request_rec *r)
if (ap_is_HTTP_REDIRECT(rr->status) ||
(rr->status == HTTP_NOT_ACCEPTABLE && num_names == 1)) {
+ ap_pool_join(r->pool, rr->pool);
error_notfound = rr->status;
r->notes = ap_overlay_tables(r->pool, r->notes, rr->notes);
r->headers_out = ap_overlay_tables(r->pool, r->headers_out,
rr->headers_out);
r->err_headers_out = ap_overlay_tables(r->pool, r->err_headers_out,
rr->err_headers_out);
- ap_destroy_sub_req(rr);
return error_notfound;
}
diff --git a/usr.sbin/httpd/src/modules/standard/mod_env.c b/usr.sbin/httpd/src/modules/standard/mod_env.c
index e2bf3603a01..351a48712b0 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_env.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_env.c
@@ -105,26 +105,26 @@ typedef struct {
table *vars;
char *unsetenv;
int vars_present;
-} env_server_config_rec;
+} env_dir_config_rec;
module MODULE_VAR_EXPORT env_module;
-static void *create_env_server_config(pool *p, server_rec *dummy)
+static void *create_env_dir_config(pool *p, char *dummy)
{
- env_server_config_rec *new =
- (env_server_config_rec *) ap_palloc(p, sizeof(env_server_config_rec));
+ env_dir_config_rec *new =
+ (env_dir_config_rec *) ap_palloc(p, sizeof(env_dir_config_rec));
new->vars = ap_make_table(p, 50);
new->unsetenv = "";
new->vars_present = 0;
return (void *) new;
}
-static void *merge_env_server_configs(pool *p, void *basev, void *addv)
+static void *merge_env_dir_configs(pool *p, void *basev, void *addv)
{
- env_server_config_rec *base = (env_server_config_rec *) basev;
- env_server_config_rec *add = (env_server_config_rec *) addv;
- env_server_config_rec *new =
- (env_server_config_rec *) ap_palloc(p, sizeof(env_server_config_rec));
+ env_dir_config_rec *base = (env_dir_config_rec *) basev;
+ env_dir_config_rec *add = (env_dir_config_rec *) addv;
+ env_dir_config_rec *new =
+ (env_dir_config_rec *) ap_palloc(p, sizeof(env_dir_config_rec));
table *new_table;
table_entry *elts;
@@ -166,11 +166,10 @@ static void *merge_env_server_configs(pool *p, void *basev, void *addv)
return new;
}
-static const char *add_env_module_vars_passed(cmd_parms *cmd, char *struct_ptr,
+static const char *add_env_module_vars_passed(cmd_parms *cmd,
+ env_dir_config_rec *sconf,
const char *arg)
{
- env_server_config_rec *sconf =
- ap_get_module_config(cmd->server->module_config, &env_module);
table *vars = sconf->vars;
char *env_var;
char *name_ptr;
@@ -186,11 +185,10 @@ static const char *add_env_module_vars_passed(cmd_parms *cmd, char *struct_ptr,
return NULL;
}
-static const char *add_env_module_vars_set(cmd_parms *cmd, char *struct_ptr,
+static const char *add_env_module_vars_set(cmd_parms *cmd,
+ env_dir_config_rec *sconf,
const char *arg)
{
- env_server_config_rec *sconf =
- ap_get_module_config(cmd->server->module_config, &env_module);
table *vars = sconf->vars;
char *name, *value;
@@ -212,11 +210,10 @@ static const char *add_env_module_vars_set(cmd_parms *cmd, char *struct_ptr,
return NULL;
}
-static const char *add_env_module_vars_unset(cmd_parms *cmd, char *struct_ptr,
+static const char *add_env_module_vars_unset(cmd_parms *cmd,
+ env_dir_config_rec *sconf,
char *arg)
{
- env_server_config_rec *sconf =
- ap_get_module_config(cmd->server->module_config, &env_module);
sconf->unsetenv = sconf->unsetenv ?
ap_pstrcat(cmd->pool, sconf->unsetenv, " ", arg, NULL) :
arg;
@@ -226,19 +223,18 @@ static const char *add_env_module_vars_unset(cmd_parms *cmd, char *struct_ptr,
static const command_rec env_module_cmds[] =
{
{"PassEnv", add_env_module_vars_passed, NULL,
- RSRC_CONF, RAW_ARGS, "a list of environment variables to pass to CGI."},
+ OR_FILEINFO, RAW_ARGS, "a list of environment variables to pass to CGI."},
{"SetEnv", add_env_module_vars_set, NULL,
- RSRC_CONF, RAW_ARGS, "an environment variable name and a value to pass to CGI."},
+ OR_FILEINFO, RAW_ARGS, "an environment variable name and a value to pass to CGI."},
{"UnsetEnv", add_env_module_vars_unset, NULL,
- RSRC_CONF, RAW_ARGS, "a list of variables to remove from the CGI environment."},
+ OR_FILEINFO, RAW_ARGS, "a list of variables to remove from the CGI environment."},
{NULL},
};
static int fixup_env_module(request_rec *r)
{
table *e = r->subprocess_env;
- server_rec *s = r->server;
- env_server_config_rec *sconf = ap_get_module_config(s->module_config,
+ env_dir_config_rec *sconf = ap_get_module_config(r->per_dir_config,
&env_module);
table *vars = sconf->vars;
@@ -254,10 +250,10 @@ module MODULE_VAR_EXPORT env_module =
{
STANDARD_MODULE_STUFF,
NULL, /* initializer */
- NULL, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- create_env_server_config, /* server config */
- merge_env_server_configs, /* merge server configs */
+ create_env_dir_config, /* dir config creater */
+ merge_env_dir_configs, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server configs */
env_module_cmds, /* command table */
NULL, /* handlers */
NULL, /* filename translation */
diff --git a/usr.sbin/httpd/src/modules/standard/mod_imap.c b/usr.sbin/httpd/src/modules/standard/mod_imap.c
index dfde31464c4..c5152e71e40 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_imap.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_imap.c
@@ -508,7 +508,7 @@ static void menu_header(request_rec *r, char *menu)
ap_send_http_header(r);
ap_hard_timeout("send menu", r); /* killed in menu_footer */
- ap_rvputs(r, "<html><head>\n<title>Menu for ", r->uri,
+ ap_rvputs(r, DOCTYPE_HTML_3_2, "<html><head>\n<title>Menu for ", r->uri,
"</title>\n</head><body>\n", NULL);
if (!strcasecmp(menu, "formatted")) {
diff --git a/usr.sbin/httpd/src/modules/standard/mod_include.c b/usr.sbin/httpd/src/modules/standard/mod_include.c
index dd36668cda7..3ee96db83b5 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_include.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_include.c
@@ -628,7 +628,7 @@ static int include_cgi(char *s, request_rec *r)
*/
static int is_only_below(const char *path)
{
-#if WIN32
+#ifdef HAVE_DRIVE_LETTERS
if (path[1] == ':')
return 0;
#endif
@@ -765,6 +765,9 @@ static int handle_include(FILE *in, request_rec *r, const char *error, int noexe
}
typedef struct {
+#ifdef TPF
+ TPF_FORK_CHILD t;
+#endif
request_rec *r;
char *s;
} include_cmd_arg;
@@ -818,11 +821,14 @@ static int include_cmd_child(void *arg, child_info *pinfo)
#ifdef DEBUG_INCLUDE_CMD
fprintf(dbg, "Attempting to exec '%s'\n", s);
#endif
+#ifdef TPF
+ return (0);
+#else
ap_cleanup_for_exec();
/* set shellcmd flag to pass arg to SHELL_PATH */
child_pid = ap_call_exec(r, pinfo, s, ap_create_environment(r->pool, env),
1);
-#ifdef WIN32
+#if defined(WIN32) || defined(OS2)
return (child_pid);
#else
/* Oh, drat. We're still here. The log file descriptors are closed,
@@ -840,6 +846,7 @@ static int include_cmd_child(void *arg, child_info *pinfo)
/* NOT REACHED */
return (child_pid);
#endif /* WIN32 */
+#endif /* TPF */
}
static int include_cmd(char *s, request_rec *r)
@@ -849,6 +856,11 @@ static int include_cmd(char *s, request_rec *r)
arg.r = r;
arg.s = s;
+#ifdef TPF
+ arg.t.filename = r->filename;
+ arg.t.subprocess_env = r->subprocess_env;
+ arg.t.prog_type = FORK_FILE;
+#endif
if (!ap_bspawn_child(r->pool, include_cmd_child, &arg,
kill_after_timeout, NULL, &script_in, NULL)) {
@@ -1033,35 +1045,41 @@ static int handle_config(FILE *in, request_rec *r, char *error, char *tf,
static int find_file(request_rec *r, const char *directive, const char *tag,
char *tag_val, struct stat *finfo, const char *error)
{
- char *to_send;
- request_rec *rr;
+ char *to_send = tag_val;
+ request_rec *rr = NULL;
int ret=0;
+ char *error_fmt = NULL;
if (!strcmp(tag, "file")) {
- ap_getparents(tag_val); /* get rid of any nasties */
-
- rr = ap_sub_req_lookup_file(tag_val, r);
-
- if (rr->status == HTTP_OK && rr->finfo.st_mode != 0) {
- to_send = rr->filename;
- if ((ret = stat(to_send, finfo)) == -1) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
- "unable to get information about \"%s\" "
- "in parsed file %s",
- to_send, r->filename);
- ap_rputs(error, r);
- }
+ /* be safe; only files in this directory or below allowed */
+ if (!is_only_below(tag_val)) {
+ error_fmt = "unable to access file \"%s\" "
+ "in parsed file %s";
}
else {
+ ap_getparents(tag_val); /* get rid of any nasties */
+ rr = ap_sub_req_lookup_file(tag_val, r);
+
+ if (rr->status == HTTP_OK && rr->finfo.st_mode != 0) {
+ to_send = rr->filename;
+ if (stat(to_send, finfo)) {
+ error_fmt = "unable to get information about \"%s\" "
+ "in parsed file %s";
+ }
+ }
+ else {
+ error_fmt = "unable to lookup information about \"%s\" "
+ "in parsed file %s";
+ }
+ }
+
+ if (error_fmt) {
ret = -1;
- ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
- "unable to lookup information about \"%s\" "
- "in parsed file %s",
- tag_val, r->filename);
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r, error_fmt, to_send, r->filename);
ap_rputs(error, r);
}
-
- ap_destroy_sub_req(rr);
+
+ if (rr) ap_destroy_sub_req(rr);
return ret;
}
@@ -1116,9 +1134,8 @@ static int handle_fsize(FILE *in, request_rec *r, const char *error, int sizefmt
}
else {
int l, x;
-#if defined(BSD) && BSD > 199305
- /* ap_snprintf can't handle %qd */
- sprintf(tag, "%qd", finfo.st_size);
+#if defined(AP_OFF_T_IS_QUAD)
+ ap_snprintf(tag, sizeof(tag), "%qd", finfo.st_size);
#else
ap_snprintf(tag, sizeof(tag), "%ld", finfo.st_size);
#endif
@@ -1169,7 +1186,7 @@ static int re_check(request_rec *r, char *string, char *rexp)
"unable to compile pattern \"%s\"", rexp);
return -1;
}
- regex_error = regexec(compiled, string, 0, (regmatch_t *) NULL, 0);
+ regex_error = ap_regexec(compiled, string, 0, (regmatch_t *) NULL, 0);
ap_pregfree(r->pool, compiled);
return (!regex_error);
}
diff --git a/usr.sbin/httpd/src/modules/standard/mod_info.c b/usr.sbin/httpd/src/modules/standard/mod_info.c
index ce0edefc9e2..27995855780 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_info.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_info.c
@@ -378,7 +378,8 @@ static int display_info(request_rec *r)
}
ap_hard_timeout("send server info", r);
- ap_rputs("<html><head><title>Server Information</title></head>\n", r);
+ ap_rputs(DOCTYPE_HTML_3_2
+ "<html><head><title>Server Information</title></head>\n", r);
ap_rputs("<body><h1 align=center>Apache Server Information</h1>\n", r);
if (!r->args || strcasecmp(r->args, "list")) {
cfname = ap_server_root_relative(r->pool, ap_server_confname);
diff --git a/usr.sbin/httpd/src/modules/standard/mod_log_config.c b/usr.sbin/httpd/src/modules/standard/mod_log_config.c
index 21ed1973f99..def4069b961 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_log_config.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_log_config.c
@@ -106,8 +106,8 @@
* CustomLog logs/referer "%{referer}i -> %U"
* CustomLog logs/agent "%{user-agent}i"
*
- * Except: no RefererIgnore functionality
- * logs '-' if no Referer or User-Agent instead of nothing
+ * RefererIgnore functionality can be obtained with conditional
+ * logging (SetEnvIf and CustomLog ... env=!VAR).
*
* But using this method allows much easier modification of the
* log format, e.g. to log hosts along with UA:
@@ -122,6 +122,7 @@
* %...f: filename
* %...h: remote host
* %...a: remote IP-address
+ * %...A: local IP-address
* %...{Foobar}i: The contents of Foobar: header line(s) in the request
* sent to the client.
* %...l: remote logname (from identd, if supplied)
@@ -138,7 +139,8 @@
* %...T: the time taken to serve the request, in seconds.
* %...u: remote user (from auth; may be bogus if return status (%s) is 401)
* %...U: the URL path requested.
- * %...v: the name of the server (i.e. which virtual host?)
+ * %...v: the configured name of the server (i.e. which virtual host?)
+ * %...V: the server name according to the UseCanonicalName setting
*
* The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can
* indicate conditions for inclusion of the item (which will cause it
@@ -235,6 +237,7 @@ typedef struct {
char *format_string;
array_header *format;
int log_fd;
+ char *condition_var;
#ifdef BUFFERED_LOGS
int outcnt;
char outbuf[LOG_BUFSIZE];
@@ -290,6 +293,11 @@ static const char *log_remote_address(request_rec *r, char *a)
return r->connection->remote_ip;
}
+static const char *log_local_address(request_rec *r, char *a)
+{
+ return r->connection->local_ip;
+}
+
static const char *log_remote_logname(request_rec *r, char *a)
{
return ap_get_remote_logname(r);
@@ -385,16 +393,14 @@ static const char *log_request_time(request_rec *r, char *a)
}
else { /* CLF format */
char sign = (timz < 0 ? '-' : '+');
- size_t l;
if (timz < 0) {
timz = -timz;
}
-
- strftime(tstr, MAX_STRING_LEN, "[%d/%b/%Y:%H:%M:%S ", t);
- l = strlen(tstr);
- ap_snprintf(tstr + l, sizeof(tstr) - l,
- "%c%.2d%.2d]", sign, timz / 60, timz % 60);
+ ap_snprintf(tstr, sizeof(tstr), "[%02d/%s/%d:%02d:%02d:%02d %c%.2d%.2d]",
+ t->tm_mday, ap_month_snames[t->tm_mon], t->tm_year+1900,
+ t->tm_hour, t->tm_min, t->tm_sec,
+ sign, timz / 60, timz % 60);
}
return ap_pstrdup(r->pool, tstr);
@@ -419,6 +425,14 @@ static const char *log_server_port(request_rec *r, char *a)
r->server->port ? r->server->port : ap_default_port(r));
}
+/* This respects the setting of UseCanonicalName so that
+ * the dynamic mass virtual hosting trick works better.
+ */
+static const char *log_server_name(request_rec *r, char *a)
+{
+ return ap_get_server_name(r);
+}
+
static const char *log_child_pid(request_rec *r, char *a)
{
return ap_psprintf(r->pool, "%ld", (long) getpid());
@@ -441,6 +455,9 @@ static struct log_item_list {
{
'a', log_remote_address, 0
},
+ {
+ 'A', log_local_address, 0
+ },
{
'l', log_remote_logname, 0
},
@@ -481,6 +498,9 @@ static struct log_item_list {
'e', log_env_var, 0
},
{
+ 'V', log_server_name, 0
+ },
+ {
'v', log_virtual_host, 0
},
{
@@ -527,30 +547,61 @@ static struct log_item_list *find_log_func(char k)
return NULL;
}
-static char *log_format_substring(pool *p, const char *start,
- const char *end)
-{
- char *res = ap_palloc(p, end - start + 1);
-
- strncpy(res, start, end - start);
- res[end - start] = '\0';
- return res;
-}
-
static char *parse_log_misc_string(pool *p, log_format_item *it,
const char **sa)
{
- const char *s = *sa;
+ const char *s;
+ char *d;
it->func = constant_item;
it->conditions = NULL;
+ s = *sa;
while (*s && *s != '%') {
- ++s;
+ s++;
}
- it->arg = log_format_substring(p, *sa, s);
- *sa = s;
+ /*
+ * This might allocate a few chars extra if there's a backslash
+ * escape in the format string.
+ */
+ it->arg = ap_palloc(p, s - *sa + 1);
+
+ d = it->arg;
+ s = *sa;
+ while (*s && *s != '%') {
+ if (*s != '\\') {
+ *d++ = *s++;
+ }
+ else {
+ s++;
+ switch (*s) {
+ case '\\':
+ *d++ = '\\';
+ s++;
+ break;
+ case 'n':
+ *d++ = '\n';
+ s++;
+ break;
+ case 't':
+ *d++ = '\t';
+ s++;
+ break;
+ default:
+ /* copy verbatim */
+ *d++ = '\\';
+ /*
+ * Allow the loop to deal with this *s in the normal
+ * fashion so that it handles end of string etc.
+ * properly.
+ */
+ break;
+ }
+ }
+ }
+ *d = '\0';
+ *sa = s;
return NULL;
}
@@ -729,11 +780,30 @@ static int config_log_transaction(request_rec *r, config_log_state *cls,
int i;
int len = 0;
array_header *format;
+ char *envar;
if (cls->fname == NULL) {
return DECLINED;
}
+ /*
+ * See if we've got any conditional envariable-controlled logging decisions
+ * to make.
+ */
+ if (cls->condition_var != NULL) {
+ envar = cls->condition_var;
+ if (*envar != '!') {
+ if (ap_table_get(r->subprocess_env, envar) == NULL) {
+ return DECLINED;
+ }
+ }
+ else {
+ if (ap_table_get(r->subprocess_env, &envar[1]) != NULL) {
+ return DECLINED;
+ }
+ }
+ }
+
format = cls->format ? cls->format : default_format;
strs = ap_palloc(r->pool, sizeof(char *) * (format->nelts));
@@ -792,10 +862,13 @@ static int config_log_transaction(request_rec *r, config_log_state *cls,
static int multi_log_transaction(request_rec *r)
{
multi_log_state *mls = ap_get_module_config(r->server->module_config,
- &config_log_module);
+ &config_log_module);
config_log_state *clsarray;
int i;
+ /*
+ * Log this transaction..
+ */
if (mls->config_logs->nelts) {
clsarray = (config_log_state *) mls->config_logs->elts;
for (i = 0; i < mls->config_logs->nelts; ++i) {
@@ -823,8 +896,9 @@ static int multi_log_transaction(request_rec *r)
static void *make_config_log_state(pool *p, server_rec *s)
{
- multi_log_state *mls = (multi_log_state *) ap_palloc(p, sizeof(multi_log_state));
+ multi_log_state *mls;
+ mls = (multi_log_state *) ap_palloc(p, sizeof(multi_log_state));
mls->config_logs = ap_make_array(p, 1, sizeof(config_log_state));
mls->default_format_string = NULL;
mls->default_format = NULL;
@@ -864,7 +938,7 @@ static const char *log_format(cmd_parms *cmd, void *dummy, char *fmt,
{
const char *err_string = NULL;
multi_log_state *mls = ap_get_module_config(cmd->server->module_config,
- &config_log_module);
+ &config_log_module);
/*
* If we were given two arguments, the second is a name to be given to the
@@ -884,18 +958,31 @@ static const char *log_format(cmd_parms *cmd, void *dummy, char *fmt,
return err_string;
}
+
static const char *add_custom_log(cmd_parms *cmd, void *dummy, char *fn,
- char *fmt)
+ char *fmt, char *envclause)
{
const char *err_string = NULL;
multi_log_state *mls = ap_get_module_config(cmd->server->module_config,
- &config_log_module);
+ &config_log_module);
config_log_state *cls;
cls = (config_log_state *) ap_push_array(mls->config_logs);
+ cls->condition_var = NULL;
+ if (envclause != NULL) {
+ if (strncasecmp(envclause, "env=", 4) != 0) {
+ return "error in condition clause";
+ }
+ if ((envclause[4] == '\0')
+ || ((envclause[4] == '!') && (envclause[5] == '\0'))) {
+ return "missing environment variable name";
+ }
+ cls->condition_var = ap_pstrdup(cmd->pool, &envclause[4]);
+ }
+
cls->fname = fn;
cls->format_string = fmt;
- if (!fmt) {
+ if (fmt == NULL) {
cls->format = NULL;
}
else {
@@ -908,18 +995,19 @@ static const char *add_custom_log(cmd_parms *cmd, void *dummy, char *fn,
static const char *set_transfer_log(cmd_parms *cmd, void *dummy, char *fn)
{
- return add_custom_log(cmd, dummy, fn, NULL);
+ return add_custom_log(cmd, dummy, fn, NULL, NULL);
}
static const char *set_cookie_log(cmd_parms *cmd, void *dummy, char *fn)
{
- return add_custom_log(cmd, dummy, fn, "%{Cookie}n \"%r\" %t");
+ return add_custom_log(cmd, dummy, fn, "%{Cookie}n \"%r\" %t", NULL);
}
static const command_rec config_log_cmds[] =
{
- {"CustomLog", add_custom_log, NULL, RSRC_CONF, TAKE2,
- "a file name and a custom log format string or format name"},
+ {"CustomLog", add_custom_log, NULL, RSRC_CONF, TAKE23,
+ "a file name, a custom log format string or format name, "
+ "and an optional \"env=\" clause (see docs)"},
{"TransferLog", set_transfer_log, NULL, RSRC_CONF, TAKE1,
"the filename of the access log"},
{"LogFormat", log_format, NULL, RSRC_CONF, TAKE12,
diff --git a/usr.sbin/httpd/src/modules/standard/mod_mime.c b/usr.sbin/httpd/src/modules/standard/mod_mime.c
index 80ec7ee3c82..f27356bfdd3 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_mime.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_mime.c
@@ -233,13 +233,8 @@ static const command_rec mime_cmds[] =
* get private versions through AddType...
*/
-/* MIME_HASHSIZE used to be 27 (26 chars and one "non-alpha" slot), but
- * with character sets like EBCDIC, this is insufficient because the
- * range 'a'...'z' is not contigous. Defining it as ('z'-'a'+2) is
- * equivalent to 27 in ASCII, and makes it work in EBCDIC.
- */
-#define MIME_HASHSIZE ('z'-'a'+2)
-#define hash(i) (ap_isalpha(i) ? (ap_tolower(i)) - 'a' : (MIME_HASHSIZE-1))
+#define MIME_HASHSIZE (32)
+#define hash(i) (ap_tolower(i) % MIME_HASHSIZE)
static table *hash_buckets[MIME_HASHSIZE];
diff --git a/usr.sbin/httpd/src/modules/standard/mod_mime_magic.c b/usr.sbin/httpd/src/modules/standard/mod_mime_magic.c
index e57eea537f8..7f4d6ba6e30 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_mime_magic.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_mime_magic.c
@@ -242,7 +242,7 @@ union record {
static int ascmagic(request_rec *, unsigned char *, int);
static int is_tar(unsigned char *, int);
static int softmagic(request_rec *, unsigned char *, int);
-static void tryit(request_rec *, unsigned char *, int);
+static void tryit(request_rec *, unsigned char *, int, int);
static int zmagic(request_rec *, unsigned char *, int);
static int getvalue(server_rec *, struct magic *, char **);
@@ -256,7 +256,7 @@ static int mget(request_rec *, union VALUETYPE *, unsigned char *,
static int mcheck(request_rec *, union VALUETYPE *, struct magic *);
static void mprint(request_rec *, union VALUETYPE *, struct magic *);
-static int uncompress(request_rec *, int, const unsigned char *,
+static int uncompress(request_rec *, int,
unsigned char **, int);
static long from_oct(int, char *);
static int fsmagic(request_rec *r, const char *fn);
@@ -887,7 +887,7 @@ static int magic_process(request_rec *r)
magic_rsl_puts(r, MIME_TEXT_UNKNOWN);
else {
buf[nbytes++] = '\0'; /* null-terminate it */
- tryit(r, buf, nbytes);
+ tryit(r, buf, nbytes, 1);
}
(void) ap_pclosef(r->pool, fd);
@@ -897,13 +897,15 @@ static int magic_process(request_rec *r)
}
-static void tryit(request_rec *r, unsigned char *buf, int nb)
+static void tryit(request_rec *r, unsigned char *buf, int nb, int checkzmagic)
{
/*
* Try compression stuff
*/
- if (zmagic(r, buf, nb) == 1)
- return;
+ if (checkzmagic == 1) {
+ if (zmagic(r, buf, nb) == 1)
+ return;
+ }
/*
* try tests in /etc/magic (or surrogate magic file)
@@ -2082,9 +2084,13 @@ static struct {
char *encoding; /* MUST be lowercase */
} compr[] = {
+ /* we use gzip here rather than uncompress because we have to pass
+ * it a full filename -- and uncompress only considers filenames
+ * ending with .Z
+ */
{
"\037\235", 2, {
- "uncompress", "-c", NULL
+ "gzip", "-dcq", NULL
}, 0, "x-compress"
},
{
@@ -2121,8 +2127,8 @@ static int zmagic(request_rec *r, unsigned char *buf, int nbytes)
if (i == ncompr)
return 0;
- if ((newsize = uncompress(r, i, buf, &newbuf, nbytes)) > 0) {
- tryit(r, newbuf, newsize);
+ if ((newsize = uncompress(r, i, &newbuf, nbytes)) > 0) {
+ tryit(r, newbuf, newsize, 0);
/* set encoding type in the request record */
r->content_encoding = compr[i].encoding;
@@ -2139,6 +2145,13 @@ struct uncompress_parms {
static int uncompress_child(void *data, child_info *pinfo)
{
struct uncompress_parms *parm = data;
+ char *new_argv[4];
+
+ new_argv[0] = compr[parm->method].argv[0];
+ new_argv[1] = compr[parm->method].argv[1];
+ new_argv[2] = parm->r->filename;
+ new_argv[3] = NULL;
+
#if defined(WIN32)
int child_pid;
#endif
@@ -2149,10 +2162,10 @@ static int uncompress_child(void *data, child_info *pinfo)
#if defined(WIN32)
child_pid = spawnvp(compr[parm->method].argv[0],
- compr[parm->method].argv);
+ new_argv);
return (child_pid);
#else
- execvp(compr[parm->method].argv[0], compr[parm->method].argv);
+ execvp(compr[parm->method].argv[0], new_argv);
ap_log_rerror(APLOG_MARK, APLOG_ERR, parm->r,
MODNAME ": could not execute `%s'.",
compr[parm->method].argv[0]);
@@ -2161,11 +2174,11 @@ static int uncompress_child(void *data, child_info *pinfo)
}
-static int uncompress(request_rec *r, int method, const unsigned char *old,
+static int uncompress(request_rec *r, int method,
unsigned char **newch, int n)
{
struct uncompress_parms parm;
- BUFF *bin, *bout;
+ BUFF *bout;
pool *sub_pool;
parm.r = r;
@@ -2178,19 +2191,12 @@ static int uncompress(request_rec *r, int method, const unsigned char *old,
sub_pool = ap_make_sub_pool(r->pool);
if (!ap_bspawn_child(sub_pool, uncompress_child, &parm, kill_always,
- &bin, &bout, NULL)) {
+ NULL, &bout, NULL)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
MODNAME ": couldn't spawn uncompress process: %s", r->uri);
return -1;
}
- if (ap_bwrite(bin, old, n) != n) {
- ap_destroy_pool(sub_pool);
- ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
- MODNAME ": write failed.");
- return -1;
- }
- ap_bclose(bin);
*newch = (unsigned char *) ap_palloc(r->pool, n);
if ((n = ap_bread(bout, *newch, n)) <= 0) {
ap_destroy_pool(sub_pool);
diff --git a/usr.sbin/httpd/src/modules/standard/mod_negotiation.c b/usr.sbin/httpd/src/modules/standard/mod_negotiation.c
index b2fcf93ef74..5f7411260c2 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_negotiation.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_negotiation.c
@@ -140,7 +140,6 @@ static const command_rec negotiation_cmds[] =
typedef struct accept_rec {
char *name; /* MUST be lowercase */
float quality;
- float max_bytes;
float level;
char *charset; /* for content-type only */
} accept_rec;
@@ -315,7 +314,6 @@ static const char *get_entry(pool *p, accept_rec *result,
const char *accept_line)
{
result->quality = 1.0f;
- result->max_bytes = 0.0f;
result->level = 0.0f;
result->charset = "";
@@ -392,10 +390,6 @@ static const char *get_entry(pool *p, accept_rec *result,
&& (parm[1] == '\0' || (parm[1] == 's' && parm[2] == '\0'))) {
result->quality = atof(cp);
}
- else if (parm[0] == 'm' && parm[1] == 'x' &&
- parm[2] == 'b' && parm[3] == '\0') {
- result->max_bytes = atof(cp);
- }
else if (parm[0] == 'l' && !strcmp(&parm[1], "evel")) {
result->level = atof(cp);
}
@@ -511,81 +505,81 @@ static negotiation_state *parse_accept_headers(request_rec *r)
static void parse_negotiate_header(request_rec *r, negotiation_state *neg)
{
const char *negotiate = ap_table_get(r->headers_in, "Negotiate");
+ char *tok;
- if (negotiate) {
- /* Negotiate: header tells us UA does transparent negotiation */
+ /* First, default to no TCN, no Alternates, and the original Apache
+ * negotiation algorithm with fiddles for broken browser configs.
+ *
+ * To save network bandwidth, we do not configure to send an
+ * Alternates header to the user agent by default. User
+ * agents that want an Alternates header for agent-driven
+ * negotiation will have to request it by sending an
+ * appropriate Negotiate header.
+ */
+ neg->ua_supports_trans = 0;
+ neg->send_alternates = 0;
+ neg->may_choose = 1;
+ neg->use_rvsa = 0;
+ neg->dont_fiddle_headers = 0;
+
+ if (!negotiate)
+ return;
- /* sending Alternates on non-transparent resources is allowed,
- * and may even be useful, but we don't for now, also
- * because it could clash with an Alternates header set by
- * a sub- or super- request on a transparent resource.
+ if (strcmp(negotiate, "trans") == 0) {
+ /* Lynx 2.7 and 2.8 send 'negotiate: trans' even though they
+ * do not support transparent content negotiation, so for Lynx we
+ * ignore the negotiate header when its contents are exactly "trans".
+ * If future versions of Lynx ever need to say 'negotiate: trans',
+ * they can send the equivalent 'negotiate: trans, trans' instead
+ * to avoid triggering the workaround below.
*/
+ const char *ua = ap_table_get(r->headers_in, "User-Agent");
- while (*negotiate) {
- char *tok = ap_get_token(neg->pool, &negotiate, 1);
- char *cp;
+ if (ua && (strncmp(ua, "Lynx", 4) == 0))
+ return;
+ }
- for (cp = tok; (*cp && !ap_isspace(*cp) && *cp != '='); ++cp) {
- *cp = ap_tolower(*cp);
- }
- *cp = 0;
-
- if (strcmp(tok, "trans") == 0 ||
- strcmp(tok, "vlist") == 0 ||
- strcmp(tok, "guess-small") == 0 ||
- ap_isdigit(tok[0]) ||
- strcmp(tok, "*") == 0) {
-
- /* The user agent supports transparent negotiation */
- neg->ua_supports_trans = 1;
-
- /* Send-alternates could be configurable, but note
- * that it must be 1 if we have 'vlist' in the
- * negotiate header.
- */
- neg->send_alternates = 1;
+ neg->may_choose = 0; /* An empty Negotiate would require 300 response */
- if (strcmp(tok, "1.0") == 0) {
- /* we may use the RVSA/1.0 algorithm, configure for it */
- neg->may_choose = 1;
- neg->use_rvsa = 1;
- neg->dont_fiddle_headers = 1;
- }
- else if (strcmp(tok, "*") == 0) {
- /* we may use any variant selection algorithm, configure
- * to use the Apache algorithm
- */
- neg->may_choose = 1;
-
- /* We disable header fiddles on the assumption that a
- * client sending Negotiate knows how to send correct
- * headers which don't need fiddling.
- */
- neg->dont_fiddle_headers = 1;
- }
- }
+ while ((tok = ap_get_list_item(neg->pool, &negotiate)) != NULL) {
- if (*negotiate)
- negotiate++; /* skip over , */
- }
- }
+ if (strcmp(tok, "trans") == 0 ||
+ strcmp(tok, "vlist") == 0 ||
+ strcmp(tok, "guess-small") == 0 ||
+ ap_isdigit(tok[0]) ||
+ strcmp(tok, "*") == 0) {
- if (!neg->ua_supports_trans) {
- /* User agent does not support transparent negotiation,
- * configure to do server-driven negotiation with the Apache
- * algorithm.
- */
- neg->may_choose = 1;
+ /* The user agent supports transparent negotiation */
+ neg->ua_supports_trans = 1;
- /* To save network bandwidth, we do not configure to send an
- * Alternates header to the user agent in this case. User
- * agents which want an Alternates header for agent-driven
- * negotiation will have to request it by sending an
- * appropriate Negotiate header.
- */
+ /* Send-alternates could be configurable, but note
+ * that it must be 1 if we have 'vlist' in the
+ * negotiate header.
+ */
+ neg->send_alternates = 1;
+
+ if (strcmp(tok, "1.0") == 0) {
+ /* we may use the RVSA/1.0 algorithm, configure for it */
+ neg->may_choose = 1;
+ neg->use_rvsa = 1;
+ neg->dont_fiddle_headers = 1;
+ }
+ else if (tok[0] == '*') {
+ /* we may use any variant selection algorithm, configure
+ * to use the Apache algorithm
+ */
+ neg->may_choose = 1;
+
+ /* We disable header fiddles on the assumption that a
+ * client sending Negotiate knows how to send correct
+ * headers which don't need fiddling.
+ */
+ neg->dont_fiddle_headers = 1;
+ }
+ }
}
-#if NEG_DEBUG
+#ifdef NEG_DEBUG
fprintf(stderr, "dont_fiddle_headers=%d use_rvsa=%d ua_supports_trans=%d "
"send_alternates=%d, may_choose=%d\n",
neg->dont_fiddle_headers, neg->use_rvsa,
@@ -613,7 +607,6 @@ static void maybe_add_default_accepts(negotiation_state *neg,
new_accept->name = "*/*";
new_accept->quality = 1.0f;
new_accept->level = 0.0f;
- new_accept->max_bytes = 0.0f;
}
new_accept = (accept_rec *) ap_push_array(neg->accepts);
@@ -626,7 +619,6 @@ static void maybe_add_default_accepts(negotiation_state *neg,
new_accept->quality = prefer_scripts ? 2.0f : 0.001f;
}
new_accept->level = 0.0f;
- new_accept->max_bytes = 0.0f;
}
/*****************************************************************
@@ -837,9 +829,6 @@ static int read_type_map(negotiation_state *neg, request_rec *rr)
has_content = 1;
}
else if (!strncmp(buffer, "description:", 12)) {
- /* XXX: The possibility to set a description is
- * currently not documented.
- */
char *desc = ap_pstrdup(neg->pool, body);
char *cp;
@@ -1523,13 +1512,6 @@ static void set_accept_quality(negotiation_state *neg, var_rec *variant)
}
}
- /* Check maxbytes -- not in HTTP/1.1 or TCN */
-
- if (type->max_bytes > 0
- && (find_content_length(neg, variant) > type->max_bytes)) {
- continue;
- }
-
/* If we are allowed to mess with the q-values
* and have no explicit q= parameters in the accept header,
* make wildcards very low, so we have a low chance
@@ -1556,7 +1538,7 @@ static void set_accept_quality(negotiation_state *neg, var_rec *variant)
}
/* For a given variant, find the 'q' value of the charset given
- * on the Accept-Charset line. If not charsets are listed,
+ * on the Accept-Charset line. If no charsets are listed,
* assume value of '1'.
*/
static void set_charset_quality(negotiation_state *neg, var_rec *variant)
@@ -1763,20 +1745,21 @@ static int is_variant_better_rvsa(negotiation_state *neg, var_rec *variant,
variant->charset_quality *
variant->lang_quality;
- /* Make sure that variants with a very low nonzero q value
- * do not get rounded down to 0
+ /* RFC 2296 calls for the result to be rounded to 5 decimal places,
+ * but we don't do that because it serves no useful purpose other
+ * than to ensure that a remote algorithm operates on the same
+ * precision as ours. That is silly, since what we obviously want
+ * is for the algorithm to operate on the best available precision
+ * regardless of who runs it. Since the above calculation may
+ * result in significant variance at 1e-12, rounding would be bogus.
*/
- if (q <= 0.0f)
- q = 0.0f;
- else if (q < 0.00001f)
- q = 0.00001f;
#ifdef NEG_DEBUG
fprintf(stderr, "Variant: file=%s type=%s lang=%s sourceq=%1.3f "
"mimeq=%1.3f langq=%1.3f charq=%1.3f encq=%1.3f "
"q=%1.5f definite=%d\n",
(variant->file_name ? variant->file_name : ""),
- (variant->mime_name ? variant->mime_name : ""),
+ (variant->mime_type ? variant->mime_type : ""),
(variant->content_languages
? ap_array_pstrcat(neg->pool, variant->content_languages, ',')
: ""),
@@ -1784,11 +1767,12 @@ static int is_variant_better_rvsa(negotiation_state *neg, var_rec *variant,
variant->mime_type_quality,
variant->lang_quality,
variant->charset_quality,
- variant->encoding_qual q,
+ variant->encoding_quality,
+ q,
variant->definite);
#endif
- if (q == 0.0f) {
+ if (q <= 0.0f) {
return 0;
}
if (q > bestq) {
@@ -1803,19 +1787,6 @@ static int is_variant_better_rvsa(negotiation_state *neg, var_rec *variant,
*p_bestq = q;
return 1;
}
- /* If the best variant's charset is ISO-8859-1 and this variant has
- * the same charset quality, then we prefer this variant
- */
- if (variant->charset_quality == best->charset_quality &&
- (variant->content_charset != NULL &&
- *variant->content_charset != '\0' &&
- strcmp(variant->content_charset, "iso-8859-1") != 0) &&
- (best->content_charset == NULL ||
- *best->content_charset == '\0' ||
- strcmp(best->content_charset, "iso-8859-1") == 0)) {
- *p_bestq = q;
- return 1;
- }
}
return 0;
}
@@ -1833,7 +1804,7 @@ static int is_variant_better(negotiation_state *neg, var_rec *variant,
/* For non-transparent negotiation, server can choose how
* to handle the negotiation. We'll use the following in
* order: content-type, language, content-type level, charset,
- * content length.
+ * content encoding, content length.
*
* For each check, we have three possible outcomes:
* This variant is worse than current best: return 0
@@ -1853,6 +1824,22 @@ static int is_variant_better(negotiation_state *neg, var_rec *variant,
* acceptable by type, charset, encoding or language.
*/
+#ifdef NEG_DEBUG
+ fprintf(stderr, "Variant: file=%s type=%s lang=%s sourceq=%1.3f "
+ "mimeq=%1.3f langq=%1.3f langidx=%d charq=%1.3f encq=%1.3f \n",
+ (variant->file_name ? variant->file_name : ""),
+ (variant->mime_type ? variant->mime_type : ""),
+ (variant->content_languages
+ ? ap_array_pstrcat(neg->pool, variant->content_languages, ',')
+ : ""),
+ variant->source_quality,
+ variant->mime_type_quality,
+ variant->lang_quality,
+ variant->lang_index,
+ variant->charset_quality,
+ variant->encoding_quality);
+#endif
+
if (variant->encoding_quality == 0.0f ||
variant->lang_quality == 0.0f ||
variant->source_quality == 0.0f ||
@@ -1879,17 +1866,13 @@ static int is_variant_better(negotiation_state *neg, var_rec *variant,
return 1;
}
- /* if language qualities were equal, try the LanguagePriority
- * stuff
- */
- /* XXX: TODO: there is a slight discrepancy between how this
- * behaves and how it described in the documentation
- */
- if (best->lang_index != -1 && variant->lang_index > best->lang_index) {
+ /* if language qualities were equal, try the LanguagePriority stuff */
+ if (best->lang_index != -1 &&
+ (variant->lang_index == -1 || variant->lang_index > best->lang_index)) {
return 0;
}
if (variant->lang_index != -1 &&
- (variant->lang_index < best->lang_index || best->lang_index == -1)) {
+ (best->lang_index == -1 || variant->lang_index < best->lang_index)) {
*p_bestq = q;
return 1;
}
@@ -1913,9 +1896,6 @@ static int is_variant_better(negotiation_state *neg, var_rec *variant,
/* If the best variant's charset is ISO-8859-1 and this variant has
* the same charset quality, then we prefer this variant
*/
- /* XXX: TODO: this specific tie-breaker is not described in the
- * documentation
- */
if (variant->charset_quality > best->charset_quality ||
((variant->content_charset != NULL &&
@@ -2211,14 +2191,6 @@ static void set_neg_headers(request_rec *r, negotiation_state *neg,
ap_array_pstrcat(r->pool, arr, '\0'));
}
- /* Theoretically the negotiation result _always_ has a dependence on
- * the contents of the Accept header because we do 'mxb='
- * processing in set_accept_quality(). However, variations in mxb
- * only affect the relative quality of several acceptable variants,
- * so there is no reason to worry about an unacceptable variant
- * being mistakenly prioritized. We therefore ignore mxb in deciding
- * whether or not to include Accept in the Vary field value.
- */
if (neg->is_transparent || vary_by_type || vary_by_language ||
vary_by_language || vary_by_charset || vary_by_encoding) {
@@ -2437,7 +2409,6 @@ static int do_negotiation(request_rec *r, negotiation_state *neg,
int alg_result; /* result of variant selection algorithm */
int res;
int j;
- int unencoded_variants = 0;
/* Decide if resource is transparently negotiable */
@@ -2465,20 +2436,7 @@ static int do_negotiation(request_rec *r, negotiation_state *neg,
*/
if (strchr(variant->file_name, '/'))
neg->is_transparent = 0;
-
- if (!variant->content_encoding)
- unencoded_variants++;
}
-
- /* If there are less than 2 unencoded variants, we always
- * switch to server-driven negotiation, regardless of whether
- * we are contacted by a client capable of transparent
- * negotiation. We do this because our current TCN
- * implementation does not deal well with the case of having 0
- * or 1 unencoded variants.
- */
- if (unencoded_variants < 2)
- neg->is_transparent = 0;
}
if (neg->is_transparent) {
diff --git a/usr.sbin/httpd/src/modules/standard/mod_rewrite.c b/usr.sbin/httpd/src/modules/standard/mod_rewrite.c
index 9898103006f..fa16d2d1916 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_rewrite.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_rewrite.c
@@ -91,6 +91,10 @@
#include "mod_rewrite.h"
+#ifndef NO_WRITEV
+#include <sys/types.h>
+#include <sys/uio.h>
+#endif
/*
** +-------------------------------------------------------+
@@ -158,9 +162,9 @@ static const command_rec command_table[] = {
{ "RewriteBase", cmd_rewritebase, NULL, OR_FILEINFO, TAKE1,
"the base URL of the per-directory context" },
{ "RewriteCond", cmd_rewritecond, NULL, OR_FILEINFO, RAW_ARGS,
- "a input string and a to be applied regexp-pattern" },
+ "an input string and a to be applied regexp-pattern" },
{ "RewriteRule", cmd_rewriterule, NULL, OR_FILEINFO, RAW_ARGS,
- "a URL-applied regexp-pattern and a substitution URL" },
+ "an URL-applied regexp-pattern and a substitution URL" },
{ "RewriteMap", cmd_rewritemap, NULL, RSRC_CONF, TAKE2,
"a mapname and a filename" },
{ "RewriteLock", cmd_rewritelock, NULL, RSRC_CONF, TAKE1,
@@ -208,10 +212,8 @@ static cache *cachep;
/* whether proxy module is available or not */
static int proxy_available;
- /* the txt mapfile parsing stuff */
-static regex_t *lookup_map_txtfile_regexp = NULL;
-static regmatch_t lookup_map_txtfile_regmatch[MAX_NMATCH];
-
+static char *lockname;
+static int lockfd = -1;
/*
** +-------------------------------------------------------+
@@ -238,8 +240,6 @@ static void *config_server_create(pool *p, server_rec *s)
a->rewritelogfile = NULL;
a->rewritelogfp = -1;
a->rewriteloglevel = 0;
- a->rewritelockfile = NULL;
- a->rewritelockfp = -1;
a->rewritemaps = ap_make_array(p, 2, sizeof(rewritemap_entry));
a->rewriteconds = ap_make_array(p, 2, sizeof(rewritecond_entry));
a->rewriterules = ap_make_array(p, 2, sizeof(rewriterule_entry));
@@ -274,12 +274,6 @@ static void *config_server_merge(pool *p, void *basev, void *overridesv)
a->rewritelogfp = overrides->rewritelogfp != -1
? overrides->rewritelogfp
: base->rewritelogfp;
- a->rewritelockfile = overrides->rewritelockfile != NULL
- ? overrides->rewritelockfile
- : base->rewritelockfile;
- a->rewritelockfp = overrides->rewritelockfp != -1
- ? overrides->rewritelockfp
- : base->rewritelockfp;
a->rewritemaps = ap_append_arrays(p, overrides->rewritemaps,
base->rewritemaps);
a->rewriteconds = ap_append_arrays(p, overrides->rewriteconds,
@@ -295,8 +289,6 @@ static void *config_server_merge(pool *p, void *basev, void *overridesv)
a->rewriteloglevel = overrides->rewriteloglevel;
a->rewritelogfile = overrides->rewritelogfile;
a->rewritelogfp = overrides->rewritelogfp;
- a->rewritelockfile = overrides->rewritelockfile;
- a->rewritelockfp = overrides->rewritelockfp;
a->rewritemaps = overrides->rewritemaps;
a->rewriteconds = overrides->rewriteconds;
a->rewriterules = overrides->rewriterules;
@@ -532,12 +524,12 @@ static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, char *a1,
static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, char *a1)
{
- rewrite_server_conf *sconf;
+ const char *error;
- sconf = (rewrite_server_conf *)
- ap_get_module_config(cmd->server->module_config, &rewrite_module);
+ if ((error = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
+ return error;
- sconf->rewritelockfile = a1;
+ lockname = a1;
return NULL;
}
@@ -952,10 +944,6 @@ static void init_module(server_rec *s, pool *p)
/* check if proxy module is available */
proxy_available = (ap_find_linked_module("mod_proxy.c") != NULL);
- /* precompile a static pattern
- for the txt mapfile parsing */
- lookup_map_txtfile_regexp = ap_pregcomp(p, MAPFILE_PATTERN, REG_EXTENDED);
-
/* create the rewriting lockfile in the parent */
rewritelock_create(s, p);
ap_register_cleanup(p, (void *)s, rewritelock_remove, ap_null_cleanup);
@@ -1804,7 +1792,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
rewritelog(r, 3, "[per-dir %s] applying pattern '%s' to uri '%s'",
perdir, p->pattern, uri);
}
- rc = (regexec(regexp, uri, regexp->re_nsub+1, regmatch, 0) == 0);
+ rc = (ap_regexec(regexp, uri, regexp->re_nsub+1, regmatch, 0) == 0);
if (! (( rc && !(p->flags & RULEFLAG_NOTMATCH)) ||
(!rc && (p->flags & RULEFLAG_NOTMATCH)) ) ) {
return 0;
@@ -2180,7 +2168,7 @@ static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
}
}
}
- else if (strcmp(p->pattern, "-s ") == 0) {
+ else if (strcmp(p->pattern, "-s") == 0) {
if (stat(input, &sb) == 0) {
if (S_ISREG(sb.st_mode) && sb.st_size > 0) {
rc = 1;
@@ -2273,8 +2261,8 @@ static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
}
else {
/* it is really a regexp pattern, so apply it */
- rc = (regexec(p->regexp, input,
- p->regexp->re_nsub+1, regmatch,0) == 0);
+ rc = (ap_regexec(p->regexp, input,
+ p->regexp->re_nsub+1, regmatch,0) == 0);
/* if it isn't a negated pattern and really matched
we update the passed-through regex subst info structure */
@@ -2729,13 +2717,15 @@ static char *lookup_map(request_rec *r, char *name, char *key)
else {
rewritelog(r, 5, "map lookup FAILED: map=%s[txt] "
"key=%s", s->name, key);
+ set_cache_string(cachep, s->name, CACHEMODE_TS,
+ st.st_mtime, key, "");
return NULL;
}
}
else {
rewritelog(r, 5, "cache lookup OK: map=%s[txt] key=%s "
"-> val=%s", s->name, key, value);
- return value;
+ return value[0] != '\0' ? value : NULL;
}
}
else if (s->type == MAPTYPE_DBM) {
@@ -2764,13 +2754,15 @@ static char *lookup_map(request_rec *r, char *name, char *key)
else {
rewritelog(r, 5, "map lookup FAILED: map=%s[dbm] "
"key=%s", s->name, key);
+ set_cache_string(cachep, s->name, CACHEMODE_TS,
+ st.st_mtime, key, "");
return NULL;
}
}
else {
rewritelog(r, 5, "cache lookup OK: map=%s[dbm] key=%s "
"-> val=%s", s->name, key, value);
- return value;
+ return value[0] != '\0' ? value : NULL;
}
#else
return NULL;
@@ -2823,6 +2815,8 @@ static char *lookup_map(request_rec *r, char *name, char *key)
else {
rewritelog(r, 5, "map lookup FAILED: map=%s[txt] "
"key=%s", s->name, key);
+ set_cache_string(cachep, s->name, CACHEMODE_TS,
+ st.st_mtime, key, "");
return NULL;
}
}
@@ -2830,8 +2824,13 @@ static char *lookup_map(request_rec *r, char *name, char *key)
rewritelog(r, 5, "cache lookup OK: map=%s[txt] key=%s "
"-> val=%s", s->name, key, value);
}
- value = select_random_value_part(r, value);
- rewritelog(r, 5, "randomly choosen the subvalue `%s'", value);
+ if (value[0] != '\0') {
+ value = select_random_value_part(r, value);
+ rewritelog(r, 5, "randomly choosen the subvalue `%s'", value);
+ }
+ else {
+ value = NULL;
+ }
return value;
}
}
@@ -2839,44 +2838,45 @@ static char *lookup_map(request_rec *r, char *name, char *key)
return NULL;
}
-
static char *lookup_map_txtfile(request_rec *r, char *file, char *key)
{
FILE *fp = NULL;
char line[1024];
- char output[1024];
- char result[1024];
char *value = NULL;
char *cpT;
+ size_t skip;
char *curkey;
char *curval;
if ((fp = ap_pfopen(r->pool, file, "r")) == NULL) {
- return NULL;
+ return NULL;
}
- ap_cpystrn(output, MAPFILE_OUTPUT, sizeof(output));
while (fgets(line, sizeof(line), fp) != NULL) {
- if (line[strlen(line)-1] == '\n') {
- line[strlen(line)-1] = '\0';
- }
- if (regexec(lookup_map_txtfile_regexp, line,
- lookup_map_txtfile_regexp->re_nsub+1,
- lookup_map_txtfile_regmatch, 0) == 0) {
- ap_cpystrn(result, ap_pregsub(r->pool, output, line,
- lookup_map_txtfile_regexp->re_nsub+1,
- lookup_map_txtfile_regmatch),
- sizeof(result)); /* substitute in output */
- cpT = strchr(result, ',');
- *cpT = '\0';
- curkey = result;
- curval = cpT+1;
-
- if (strcmp(curkey, key) == 0) {
- value = ap_pstrdup(r->pool, curval);
- break;
- }
- }
+ if (line[0] == '#')
+ continue; /* ignore comments */
+ cpT = line;
+ curkey = cpT;
+ skip = strcspn(cpT," \t\r\n");
+ if (skip == 0)
+ continue; /* ignore lines that start with a space, tab, CR, or LF */
+ cpT += skip;
+ *cpT = '\0';
+ if (strcmp(curkey, key) != 0)
+ continue; /* key does not match... */
+
+ /* found a matching key; now extract and return the value */
+ ++cpT;
+ skip = strspn(cpT, " \t\r\n");
+ cpT += skip;
+ curval = cpT;
+ skip = strcspn(cpT, " \t\r\n");
+ if (skip == 0)
+ continue; /* no value... */
+ cpT += skip;
+ *cpT = '\0';
+ value = ap_pstrdup(r->pool, curval);
+ break;
}
ap_pfclose(r->pool, fp);
return value;
@@ -2913,6 +2913,9 @@ static char *lookup_map_program(request_rec *r, int fpin, int fpout, char *key)
char buf[LONG_STRING_LEN];
char c;
int i;
+#ifndef NO_WRITEV
+ struct iovec iov[2];
+#endif
/* when `RewriteEngine off' was used in the per-server
* context then the rewritemap-programs were not spawned.
@@ -2927,8 +2930,16 @@ static char *lookup_map_program(request_rec *r, int fpin, int fpout, char *key)
rewritelock_alloc(r);
/* write out the request key */
+#ifdef NO_WRITEV
write(fpin, key, strlen(key));
write(fpin, "\n", 1);
+#else
+ iov[0].iov_base = key;
+ iov[0].iov_len = strlen(key);
+ iov[1].iov_base = "\n";
+ iov[1].iov_len = 1;
+ writev(fpin, iov, 2);
+#endif
/* read in the response value */
i = 0;
@@ -3247,28 +3258,26 @@ static void rewritelock_create(server_rec *s, pool *p)
conf = ap_get_module_config(s->module_config, &rewrite_module);
/* only operate if a lockfile is used */
- if (conf->rewritelockfile == NULL
- || *(conf->rewritelockfile) == '\0') {
+ if (lockname == NULL || *(lockname) == '\0') {
return;
}
/* fixup the path, especially for rewritelock_remove() */
- conf->rewritelockfile = ap_server_root_relative(p, conf->rewritelockfile);
+ lockname = ap_server_root_relative(p, lockname);
/* create the lockfile */
- unlink(conf->rewritelockfile);
- if ((conf->rewritelockfp = ap_popenf(p, conf->rewritelockfile,
- O_WRONLY|O_CREAT,
+ unlink(lockname);
+ if ((lockfd = ap_popenf(p, lockname, O_WRONLY|O_CREAT,
REWRITELOCK_MODE)) < 0) {
ap_log_error(APLOG_MARK, APLOG_ERR, s,
"mod_rewrite: Parent could not create RewriteLock "
- "file %s", conf->rewritelockfile);
+ "file %s", lockname);
exit(1);
}
#if !defined(OS2) && !defined(WIN32)
/* make sure the childs have access to this file */
if (geteuid() == 0 /* is superuser */)
- chown(conf->rewritelockfile, ap_user_id, -1 /* no gid change */);
+ chown(lockname, ap_user_id, -1 /* no gid change */);
#endif
return;
@@ -3281,18 +3290,16 @@ static void rewritelock_open(server_rec *s, pool *p)
conf = ap_get_module_config(s->module_config, &rewrite_module);
/* only operate if a lockfile is used */
- if (conf->rewritelockfile == NULL
- || *(conf->rewritelockfile) == '\0') {
+ if (lockname == NULL || *(lockname) == '\0') {
return;
}
/* open the lockfile (once per child) to get a unique fd */
- if ((conf->rewritelockfp = ap_popenf(p, conf->rewritelockfile,
- O_WRONLY,
+ if ((lockfd = ap_popenf(p, lockname, O_WRONLY,
REWRITELOCK_MODE)) < 0) {
ap_log_error(APLOG_MARK, APLOG_ERR, s,
"mod_rewrite: Child could not open RewriteLock "
- "file %s", conf->rewritelockfile);
+ "file %s", lockname);
exit(1);
}
return;
@@ -3300,43 +3307,29 @@ static void rewritelock_open(server_rec *s, pool *p)
static void rewritelock_remove(void *data)
{
- server_rec *s;
- rewrite_server_conf *conf;
-
- /* the data is really the server_rec */
- s = (server_rec *)data;
- conf = ap_get_module_config(s->module_config, &rewrite_module);
-
/* only operate if a lockfile is used */
- if (conf->rewritelockfile == NULL
- || *(conf->rewritelockfile) == '\0') {
+ if (lockname == NULL || *(lockname) == '\0') {
return;
}
/* remove the lockfile */
- unlink(conf->rewritelockfile);
+ unlink(lockname);
+ lockname = NULL;
+ lockfd = -1;
}
static void rewritelock_alloc(request_rec *r)
{
- rewrite_server_conf *conf;
-
- conf = ap_get_module_config(r->server->module_config, &rewrite_module);
-
- if (conf->rewritelockfp != -1) {
- fd_lock(r, conf->rewritelockfp);
+ if (lockfd != -1) {
+ fd_lock(r, lockfd);
}
return;
}
static void rewritelock_free(request_rec *r)
{
- rewrite_server_conf *conf;
-
- conf = ap_get_module_config(r->server->module_config, &rewrite_module);
-
- if (conf->rewritelockfp != -1) {
- fd_unlock(r, conf->rewritelockfp);
+ if (lockfd != -1) {
+ fd_unlock(r, lockfd);
}
return;
}
@@ -3607,6 +3600,9 @@ static char *lookup_variable(request_rec *r, char *var)
else if (strcasecmp(var, "SERVER_NAME") == 0) {
result = ap_get_server_name(r);
}
+ else if (strcasecmp(var, "SERVER_ADDR") == 0) { /* non-standard */
+ result = r->connection->local_ip;
+ }
else if (strcasecmp(var, "SERVER_PORT") == 0) {
ap_snprintf(resultbuf, sizeof(resultbuf), "%u", ap_get_server_port(r));
result = resultbuf;
@@ -3843,12 +3839,57 @@ static char *get_cache_string(cache *c, char *res, int mode,
return ap_pstrdup(c->pool, ce->value);
}
+static int cache_tlb_hash(char *key)
+{
+ unsigned long n;
+ char *p;
+
+ n = 0;
+ for (p=key; *p != '\0'; ++p) {
+ n = n * 53711 + 134561 + (unsigned)(*p & 0xff);
+ }
+
+ return n % CACHE_TLB_ROWS;
+}
+
+static cacheentry *cache_tlb_lookup(cachetlbentry *tlb, cacheentry *elt,
+ char *key)
+{
+ int ix = cache_tlb_hash(key);
+ int i;
+ int j;
+
+ for (i=0; i < CACHE_TLB_COLS; ++i) {
+ j = tlb[ix].t[i];
+ if (j < 0)
+ return NULL;
+ if (strcmp(elt[j].key, key) == 0)
+ return &elt[j];
+ }
+ return NULL;
+}
+
+static void cache_tlb_replace(cachetlbentry *tlb, cacheentry *elt,
+ cacheentry *e)
+{
+ int ix = cache_tlb_hash(e->key);
+ int i;
+
+ tlb = &tlb[ix];
+
+ for (i=1; i < CACHE_TLB_COLS; ++i)
+ tlb->t[i] = tlb->t[i-1];
+
+ tlb->t[0] = e - elt;
+}
+
static void store_cache_string(cache *c, char *res, cacheentry *ce)
{
int i;
int j;
cachelist *l;
cacheentry *e;
+ cachetlbentry *t;
int found_list;
found_list = 0;
@@ -3857,11 +3898,22 @@ static void store_cache_string(cache *c, char *res, cacheentry *ce)
l = &(((cachelist *)c->lists->elts)[i]);
if (strcmp(l->resource, res) == 0) {
found_list = 1;
+
+ e = cache_tlb_lookup((cachetlbentry *)l->tlb->elts,
+ (cacheentry *)l->entries->elts, ce->key);
+ if (e != NULL) {
+ e->time = ce->time;
+ e->value = ap_pstrdup(c->pool, ce->value);
+ return;
+ }
+
for (j = 0; j < l->entries->nelts; j++) {
e = &(((cacheentry *)l->entries->elts)[j]);
if (strcmp(e->key, ce->key) == 0) {
e->time = ce->time;
e->value = ap_pstrdup(c->pool, ce->value);
+ cache_tlb_replace((cachetlbentry *)l->tlb->elts,
+ (cacheentry *)l->entries->elts, e);
return;
}
}
@@ -3873,6 +3925,13 @@ static void store_cache_string(cache *c, char *res, cacheentry *ce)
l = ap_push_array(c->lists);
l->resource = ap_pstrdup(c->pool, res);
l->entries = ap_make_array(c->pool, 2, sizeof(cacheentry));
+ l->tlb = ap_make_array(c->pool, CACHE_TLB_ROWS,
+ sizeof(cachetlbentry));
+ for (i=0; i<CACHE_TLB_ROWS; ++i) {
+ t = &((cachetlbentry *)l->tlb->elts)[i];
+ for (j=0; j<CACHE_TLB_COLS; ++j)
+ t->t[j] = -1;
+ }
}
/* create the new entry */
@@ -3883,6 +3942,8 @@ static void store_cache_string(cache *c, char *res, cacheentry *ce)
e->time = ce->time;
e->key = ap_pstrdup(c->pool, ce->key);
e->value = ap_pstrdup(c->pool, ce->value);
+ cache_tlb_replace((cachetlbentry *)l->tlb->elts,
+ (cacheentry *)l->entries->elts, e);
return;
}
}
@@ -3901,6 +3962,12 @@ static cacheentry *retrieve_cache_string(cache *c, char *res, char *key)
for (i = 0; i < c->lists->nelts; i++) {
l = &(((cachelist *)c->lists->elts)[i]);
if (strcmp(l->resource, res) == 0) {
+
+ e = cache_tlb_lookup((cachetlbentry *)l->tlb->elts,
+ (cacheentry *)l->entries->elts, key);
+ if (e != NULL)
+ return e;
+
for (j = 0; j < l->entries->nelts; j++) {
e = &(((cacheentry *)l->entries->elts)[j]);
if (strcmp(e->key, key) == 0) {
diff --git a/usr.sbin/httpd/src/modules/standard/mod_rewrite.h b/usr.sbin/httpd/src/modules/standard/mod_rewrite.h
index 323f0af2974..22ff3375589 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_rewrite.h
+++ b/usr.sbin/httpd/src/modules/standard/mod_rewrite.h
@@ -105,6 +105,7 @@
#include <sys/stat.h>
/* Include from the Apache server ... */
+#define CORE_PRIVATE
#include "httpd.h"
#include "http_config.h"
#include "http_conf_globals.h"
@@ -126,8 +127,15 @@
* so we also need to know the file extension
*/
#ifndef NO_DBM_REWRITEMAP
+#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) \
+ && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
+#include <db1/ndbm.h>
+#else
#include <ndbm.h>
-#if (__FreeBSD__)
+#endif
+#if defined(DBM_SUFFIX)
+#define NDBM_FILE_SUFFIX DBM_SUFFIX
+#elif defined(__FreeBSD__) || (defined(DB_LOCK) && defined(DB_SHMEM))
#define NDBM_FILE_SUFFIX ".db"
#else
#define NDBM_FILE_SUFFIX ".pag"
@@ -149,7 +157,7 @@
#endif
#if !defined(USE_FCNTL) && !defined(USE_FLOCK)
#define USE_FLOCK 1
-#if !defined(MPE) && !defined(WIN32)
+#if !defined(MPE) && !defined(WIN32) && !defined(__TANDEM)
#include <sys/file.h>
#endif
#ifndef LOCK_UN
@@ -219,6 +227,9 @@
#define CACHEMODE_TS 1<<0
#define CACHEMODE_TTL 1<<1
+#define CACHE_TLB_ROWS 1024
+#define CACHE_TLB_COLS 4
+
#ifndef FALSE
#define FALSE 0
#define TRUE !FALSE
@@ -241,10 +252,6 @@
#define MAX_NMATCH 10
-#define MAPFILE_PATTERN "^([^ \t]+)[ \t]+([^ \t]+).*$"
-#define MAPFILE_OUTPUT "$1,$2"
-
-
/*
**
** our private data structures we handle with
@@ -295,8 +302,6 @@ typedef struct {
char *rewritelogfile; /* the RewriteLog filename */
int rewritelogfp; /* the RewriteLog open filepointer */
int rewriteloglevel; /* the RewriteLog level of verbosity */
- char *rewritelockfile; /* the RewriteLock filename */
- int rewritelockfp; /* the RewriteLock open filepointer */
array_header *rewritemaps; /* the RewriteMap entries */
array_header *rewriteconds; /* the RewriteCond entries (temporary) */
array_header *rewriterules; /* the RewriteRule entries */
@@ -317,17 +322,23 @@ typedef struct {
} rewrite_perdir_conf;
- /* the cache structures */
-
+ /* the cache structures,
+ * a 4-way hash table with LRU functionality
+ */
typedef struct cacheentry {
time_t time;
char *key;
char *value;
} cacheentry;
+typedef struct tlbentry {
+ int t[CACHE_TLB_COLS];
+} cachetlbentry;
+
typedef struct cachelist {
char *resource;
array_header *entries;
+ array_header *tlb;
} cachelist;
typedef struct cache {
@@ -335,9 +346,10 @@ typedef struct cache {
array_header *lists;
} cache;
- /* the regex structure for the
- substitution of backreferences */
+ /* the regex structure for the
+ * substitution of backreferences
+ */
typedef struct backrefinfo {
char *source;
int nsub;
diff --git a/usr.sbin/httpd/src/modules/standard/mod_setenvif.c b/usr.sbin/httpd/src/modules/standard/mod_setenvif.c
index 24841852946..27eef0aec94 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_setenvif.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_setenvif.c
@@ -125,7 +125,8 @@ enum special {
SPECIAL_REMOTE_HOST,
SPECIAL_REMOTE_USER,
SPECIAL_REQUEST_URI,
- SPECIAL_REQUEST_METHOD
+ SPECIAL_REQUEST_METHOD,
+ SPECIAL_REQUEST_PROTOCOL
};
typedef struct {
char *name; /* header name */
@@ -241,6 +242,9 @@ static const char *add_setenvif_core(cmd_parms *cmd, void *mconfig,
else if (!strcasecmp(fname, "request_method")) {
new->special_type = SPECIAL_REQUEST_METHOD;
}
+ else if (!strcasecmp(fname, "request_protocol")) {
+ new->special_type = SPECIAL_REQUEST_PROTOCOL;
+ }
else {
new->special_type = SPECIAL_NOT;
}
@@ -355,8 +359,14 @@ static int match_headers(request_rec *r)
case SPECIAL_REQUEST_METHOD:
val = r->method;
break;
+ case SPECIAL_REQUEST_PROTOCOL:
+ val = r->protocol;
+ break;
case SPECIAL_NOT:
val = ap_table_get(r->headers_in, b->name);
+ if (val == NULL) {
+ val = ap_table_get(r->subprocess_env, b->name);
+ }
break;
}
}
@@ -371,7 +381,7 @@ static int match_headers(request_rec *r)
val = "";
}
- if (!regexec(b->preg, val, 0, NULL, 0)) {
+ if (!ap_regexec(b->preg, val, 0, NULL, 0)) {
array_header *arr = ap_table_elts(b->features);
elts = (table_entry *) arr->elts;
diff --git a/usr.sbin/httpd/src/modules/standard/mod_so.c b/usr.sbin/httpd/src/modules/standard/mod_so.c
index ecc81f8f181..c3c89c975f4 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_so.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_so.c
@@ -251,7 +251,7 @@ static const char *load_module(cmd_parms *cmd, void *dummy,
"' in file ", szModuleFile, ": ", ap_os_dso_error(), NULL);
}
modi->modp = modp;
- modp->dynamic_load_handle = modhandle;
+ modp->dynamic_load_handle = (void *)modhandle;
/*
* Make sure the found module structure is really a module structure
@@ -296,7 +296,7 @@ static const char *load_module(cmd_parms *cmd, void *dummy,
static const char *load_file(cmd_parms *cmd, void *dummy, char *filename)
{
- void *handle;
+ ap_os_dso_handle_t handle;
char *file;
file = ap_server_root_relative(cmd->pool, filename);
@@ -312,7 +312,7 @@ static const char *load_file(cmd_parms *cmd, void *dummy, char *filename)
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL,
"loaded file %s", filename);
- ap_register_cleanup(cmd->pool, handle, unload_file, ap_null_cleanup);
+ ap_register_cleanup(cmd->pool, (void *)handle, unload_file, ap_null_cleanup);
return NULL;
}
@@ -356,6 +356,7 @@ module MODULE_VAR_EXPORT so_module = {
NULL, /* check auth */
NULL, /* check access */
NULL, /* type_checker */
+ NULL, /* fixer_upper */
NULL, /* logger */
NULL, /* header parser */
NULL, /* child_init */
diff --git a/usr.sbin/httpd/src/modules/standard/mod_speling.c b/usr.sbin/httpd/src/modules/standard/mod_speling.c
index a9f94d7fc16..067fd77c719 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_speling.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_speling.c
@@ -428,9 +428,12 @@ static int check_speling(request_rec *r)
* returned.
*/
else {
- char *t;
pool *p;
table *notes;
+ pool *sub_pool;
+ array_header *t;
+ array_header *v;
+
if (r->main == NULL) {
p = r->pool;
@@ -441,16 +444,22 @@ static int check_speling(request_rec *r)
notes = r->main->notes;
}
+ sub_pool = ap_make_sub_pool(p);
+ t = ap_make_array(sub_pool, candidates->nelts * 8 + 8,
+ sizeof(char *));
+ v = ap_make_array(sub_pool, candidates->nelts * 5,
+ sizeof(char *));
+
/* Generate the response text. */
- /*
- * Since the text is expanded by repeated calls of
- * t = pstrcat(p, t, ".."), we can avoid a little waste
- * of memory by adding the header AFTER building the list.
- * XXX: FIXME: find a way to build a string concatenation
- * without repeatedly requesting new memory
- * XXX: FIXME: Limit the list to a maximum number of entries
- */
- t = "";
+
+ *(const char **)ap_push_array(t) =
+ "The document name you requested (<code>";
+ *(const char **)ap_push_array(t) = r->uri;
+ *(const char **)ap_push_array(t) =
+ "</code>) could not be found on this server.\n"
+ "However, we found documents with names similar "
+ "to the one you requested.<p>"
+ "Available documents:\n<ul>\n";
for (i = 0; i < candidates->nelts; ++i) {
char *vuri;
@@ -458,16 +467,24 @@ static int check_speling(request_rec *r)
reason = sp_reason_str[(int) (variant[i].quality)];
/* The format isn't very neat... */
- vuri = ap_pstrcat(p, url, variant[i].name, r->path_info,
+ vuri = ap_pstrcat(sub_pool, url, variant[i].name, r->path_info,
(r->parsed_uri.query != NULL) ? "?" : "",
(r->parsed_uri.query != NULL)
? r->parsed_uri.query : "",
NULL);
- ap_table_mergen(r->subprocess_env, "VARIANTS",
- ap_pstrcat(p, "\"", vuri, "\";\"",
- reason, "\"", NULL));
- t = ap_pstrcat(p, t, "<li><a href=\"", vuri,
- "\">", vuri, "</a> (", reason, ")\n", NULL);
+ *(const char **)ap_push_array(v) = "\"";
+ *(const char **)ap_push_array(v) = vuri;
+ *(const char **)ap_push_array(v) = "\";\"";
+ *(const char **)ap_push_array(v) = reason;
+ *(const char **)ap_push_array(v) = "\"";
+
+ *(const char **)ap_push_array(t) = "<li><a href=\"";
+ *(const char **)ap_push_array(t) = vuri;
+ *(const char **)ap_push_array(t) = "\">";
+ *(const char **)ap_push_array(t) = vuri;
+ *(const char **)ap_push_array(t) = "</a> (";
+ *(const char **)ap_push_array(t) = reason;
+ *(const char **)ap_push_array(t) = ")\n";
/*
* when we have printed the "close matches" and there are
@@ -479,30 +496,31 @@ static int check_speling(request_rec *r)
if (i > 0 && i < candidates->nelts - 1
&& variant[i].quality != SP_VERYDIFFERENT
&& variant[i + 1].quality == SP_VERYDIFFERENT) {
- t = ap_pstrcat(p, t,
+ *(const char **)ap_push_array(t) =
"</ul>\nFurthermore, the following related "
- "documents were found:\n<ul>\n", NULL);
+ "documents were found:\n<ul>\n";
}
}
- t = ap_pstrcat(p, "The document name you requested (<code>",
- r->uri,
- "</code>) could not be found on this server.\n"
- "However, we found documents with names similar "
- "to the one you requested.<p>"
- "Available documents:\n<ul>\n", t, "</ul>\n", NULL);
+ *(const char **)ap_push_array(t) = "</ul>\n";
/* If we know there was a referring page, add a note: */
if (ref != NULL) {
- t = ap_pstrcat(p, t,
+ *(const char **)ap_push_array(t) =
"Please consider informing the owner of the "
- "<a href=\"", ref,
- "\">referring page</a> "
- "about the broken link.\n",
- NULL);
+ "<a href=\"";
+ *(const char **)ap_push_array(t) = ref;
+ *(const char **)ap_push_array(t) = "\">referring page</a> "
+ "about the broken link.\n";
}
+
/* Pass our table to http_protocol.c (see mod_negotiation): */
- ap_table_setn(notes, "variant-list", t);
+ ap_table_setn(notes, "variant-list", ap_array_pstrcat(p, t, 0));
+
+ ap_table_mergen(r->subprocess_env, "VARIANTS",
+ ap_array_pstrcat(p, v, ','));
+
+ ap_destroy_pool(sub_pool);
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_INFO, r,
ref ? "Spelling fix: %s: %d candidates from %s"
diff --git a/usr.sbin/httpd/src/modules/standard/mod_status.c b/usr.sbin/httpd/src/modules/standard/mod_status.c
index bba554526c0..ad09467f4ab 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_status.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_status.c
@@ -341,7 +341,9 @@ static int status_handler(request_rec *r)
ap_hard_timeout("send status info", r);
if (!short_report) {
- ap_rputs("<HTML><HEAD>\n<TITLE>Apache Status</TITLE>\n</HEAD><BODY>\n", r);
+ ap_rputs(DOCTYPE_HTML_3_2
+ "<HTML><HEAD>\n<TITLE>Apache Status</TITLE>\n</HEAD><BODY>\n",
+ r);
ap_rputs("<H1>Apache Server Status for ", r);
ap_rvputs(r, ap_get_server_name(r), "</H1>\n\n", NULL);
ap_rvputs(r, "Server Version: ",
@@ -353,6 +355,7 @@ static int status_handler(request_rec *r)
ap_rvputs(r, "Restart Time: ",
ap_ht_time(r->pool, ap_restart_time, DEFAULT_TIME_FORMAT, 0),
"<br>\n", NULL);
+ ap_rprintf(r, "Parent Server Generation: %d <br>\n", (int) ap_my_generation);
ap_rputs("Server uptime: ", r);
show_time(r, up_time);
ap_rputs("<br>\n", r);
@@ -477,12 +480,33 @@ static int status_handler(request_rec *r)
if (no_table_report)
ap_rputs("<p><hr><h2>Server Details</h2>\n\n", r);
else
+#ifndef NO_PRETTYPRINT
+ ap_rputs("<p>\n\n<table bgcolor=\"#ffffff\" border=\"0\">"
+ "<tr bgcolor=000000>"
+ "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Srv</b></font></td>"
+ "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>PID</b></font></td>"
+ "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Acc</b></font></td>"
+ "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>M</b></font></td>"
+#ifndef NO_TIMES
+ "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>CPU</b></font></td>"
+#endif
+ "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>SS</b></font></td>"
+ "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Req</b></font></td>"
+ "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Conn</b></font></td>"
+ "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Child</b></font></td>"
+ "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Slot</b></font></td>"
+ "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Host</b></font></td>"
+ "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>VHost</b></font></td>"
+ "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Request</b></td>"
+ "</tr>\n", r);
+#else /* NO_PRETTYPRINT */
#ifdef NO_TIMES
/* Allow for OS/2 not having CPU stats */
ap_rputs("<p>\n\n<table border=0><tr><th>Srv<th>PID<th>Acc<th>M\n<th>SS<th>Req<th>Conn<th>Child<th>Slot<th>Client<th>VHost<th>Request</tr>\n\n", r);
#else
ap_rputs("<p>\n\n<table border=0><tr><th>Srv<th>PID<th>Acc<th>M<th>CPU\n<th>SS<th>Req<th>Conn<th>Child<th>Slot<th>Client<th>VHost<th>Request</tr>\n\n", r);
#endif
+#endif /* NO_PRETTYPRINT */
}
for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
@@ -527,11 +551,16 @@ static int status_handler(request_rec *r)
if (!short_report) {
if (no_table_report) {
if (score_record.status == SERVER_DEAD)
- ap_rprintf(r, "<b>Server %d</b> (-): %d|%lu|%lu [",
- i, (int) conn_lres, my_lres, lres);
+ ap_rprintf(r,
+ "<b>Server %d-%d</b> (-): %d|%lu|%lu [",
+ i, (int) ps_record.generation, (int) conn_lres,
+ my_lres, lres);
else
- ap_rprintf(r, "<b>Server %d</b> (%d): %d|%lu|%lu [",
- i, (int) ps_record.pid, (int) conn_lres, my_lres, lres);
+ ap_rprintf(r,
+ "<b>Server %d-%d</b> (%d): %d|%lu|%lu [",
+ i, (int) ps_record.generation,
+ (int) ps_record.pid,
+ (int) conn_lres, my_lres, lres);
switch (score_record.status) {
case SERVER_READY:
@@ -588,17 +617,28 @@ static int status_handler(request_rec *r)
ap_rputs("|", r);
format_byte_out(r, bytes);
ap_rputs(")\n", r);
- ap_rprintf(r, " <i>%s {%s}</i><br>\n\n",
- score_record.client,
- ap_escape_html(r->pool, score_record.request));
+ ap_rprintf(r, " <i>%s {%s}</i> <b>[%s]</b><br>\n\n",
+ score_record.client,
+ ap_escape_html(r->pool, score_record.request),
+ vhost ? vhost->server_hostname : "(unavailable)");
}
else { /* !no_table_report */
+#ifndef NO_PRETTYPRINT
+ ap_rprintf(r,"<tr bgcolor=\"#ffffff\">");
+#else
+ ap_rprintf(r,"<tr>");
+#endif
if (score_record.status == SERVER_DEAD)
- ap_rprintf(r, "<tr><td><b>%d</b><td>-<td>%d/%lu/%lu",
- i, (int) conn_lres, my_lres, lres);
+ ap_rprintf(r,
+ "<td><b>%d-%d</b><td>-<td>%d/%lu/%lu",
+ i, (int) ps_record.generation,
+ (int) conn_lres, my_lres, lres);
else
- ap_rprintf(r, "<tr><td><b>%d</b><td>%d<td>%d/%lu/%lu",
- i, (int) ps_record.pid, (int) conn_lres, my_lres, lres);
+ ap_rprintf(r,
+ "<td><b>%d-%d</b><td>%d<td>%d/%lu/%lu",
+ i, (int) ps_record.generation,
+ (int) ps_record.pid, (int) conn_lres,
+ my_lres, lres);
switch (score_record.status) {
case SERVER_READY:
@@ -655,11 +695,22 @@ static int status_handler(request_rec *r)
ap_rprintf(r,
"<td>?<td nowrap>?<td nowrap>..reading.. </tr>\n\n");
else
+#ifndef NO_PRETTYPRINT
+ ap_rprintf(r,
+ "<td nowrap><font face=\"Arial,Helvetica\" size=\"-1\">%s</font>"
+ "<td nowrap><font face=\"Arial,Helvetica\" size=\"-1\">%s</font>"
+ "<td nowrap><font face=\"Arial,Helvetica\" size=\"-1\">%s</font>"
+ "</tr>\n\n",
+ score_record.client,
+ vhost ? vhost->server_hostname : "(unavailable)",
+ ap_escape_html(r->pool, score_record.request));
+#else
ap_rprintf(r,
"<td>%s<td nowrap>%s<td nowrap>%s</tr>\n\n",
score_record.client,
vhost ? vhost->server_hostname : "(unavailable)",
ap_escape_html(r->pool, score_record.request));
+#endif
} /* no_table_report */
} /* !short_report */
} /* if (<active child>) */
@@ -670,7 +721,7 @@ static int status_handler(request_rec *r)
ap_rputs("</table>\n \
<hr> \
<table>\n \
-<tr><th>Srv<td>Server number\n \
+<tr><th>Srv<td>Child Server number - generation\n \
<tr><th>PID<td>OS process ID\n \
<tr><th>Acc<td>Number of accesses this connection / this child / this slot\n \
<tr><th>M<td>Mode of operation\n \
@@ -684,7 +735,7 @@ static int status_handler(request_rec *r)
ap_rputs("</table>\n \
<hr> \
<table>\n \
-<tr><th>Srv<td>Server number\n \
+<tr><th>Srv<td>Child Server number - generation\n \
<tr><th>PID<td>OS process ID\n \
<tr><th>Acc<td>Number of accesses this connection / this child / this slot\n \
<tr><th>M<td>Mode of operation\n \
@@ -698,6 +749,12 @@ static int status_handler(request_rec *r)
#endif
}
+#ifdef EAPI
+ ap_hook_use("ap::mod_status::display",
+ AP_HOOK_SIG4(void,ptr,int,int), AP_HOOK_ALL,
+ r, no_table_report, short_report);
+#endif
+
} else {
ap_rputs("<hr>To obtain a full report with current status information ", r);
diff --git a/usr.sbin/httpd/src/modules/standard/mod_unique_id.c b/usr.sbin/httpd/src/modules/standard/mod_unique_id.c
index 6e103942bd3..63474ed1feb 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_unique_id.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_unique_id.c
@@ -104,7 +104,7 @@ typedef struct {
* saving cpu cycles. The counter is never reset, and is used to permit up to
* 64k requests in a single second by a single child.
*
- * The 112-bits of unique_id_rec are uuencoded using the alphabet
+ * The 112-bits of unique_id_rec are encoded using the alphabet
* [A-Za-z0-9@-], resulting in 19 bytes of printable characters. That is then
* stuffed into the environment variable UNIQUE_ID so that it is available to
* other modules. The alphabet choice differs from normal base64 encoding
@@ -181,7 +181,7 @@ static void unique_id_global_init(server_rec *s, pool *p)
unique_id_rec_size[2] + unique_id_rec_size[3];
/*
- * Calculate the size of the structure when uuencoded.
+ * Calculate the size of the structure when encoded.
*/
unique_id_rec_size_uu = (unique_id_rec_total_size*8+5)/6;
@@ -296,7 +296,7 @@ static void unique_id_child_init(server_rec *s, pool *p)
cur_unique_id.counter = htons(cur_unique_id.counter);
}
-/* NOTE: This is *NOT* the same encoding used by uuencode ... the last two
+/* NOTE: This is *NOT* the same encoding used by base64encode ... the last two
* characters should be + and /. But those two characters have very special
* meanings in URLs, and we want to make it easy to use identifiers in
* URLs. So we replace them with @ and -.
diff --git a/usr.sbin/httpd/src/modules/standard/mod_userdir.c b/usr.sbin/httpd/src/modules/standard/mod_userdir.c
index 9aea9ce9dd2..5c0e26d2753 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_userdir.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_userdir.c
@@ -262,7 +262,7 @@ static int translate_userdir(request_rec *r)
if (userdir[0] == '\0' || ap_os_is_path_absolute(userdir)) {
if (x) {
-#ifdef WIN32
+#ifdef HAVE_DRIVE_LETTERS
/*
* Crummy hack. Need to figure out whether we have been
* redirected to a URL or to a file on some drive. Since I
diff --git a/usr.sbin/httpd/src/modules/standard/mod_usertrack.c b/usr.sbin/httpd/src/modules/standard/mod_usertrack.c
index fbf800b4dab..1b50e159967 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_usertrack.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_usertrack.c
@@ -111,7 +111,12 @@ module MODULE_VAR_EXPORT usertrack_module;
typedef struct {
int always;
time_t expires;
-} cookie_log_state;
+} cookie_log_state;
+
+typedef struct {
+ int enabled;
+ char *cookie_name;
+} cookie_dir_rec;
/* Define this to allow post-2000 cookies. Cookies use two-digit dates,
* so it might be dicey. (Netscape does it correctly, but others may not)
@@ -121,12 +126,12 @@ typedef struct {
/* Make Cookie: Now we have to generate something that is going to be
* pretty unique. We can base it on the pid, time, hostip */
-#define COOKIE_NAME "Apache="
+#define COOKIE_NAME "Apache"
static void make_cookie(request_rec *r)
{
cookie_log_state *cls = ap_get_module_config(r->server->module_config,
- &usertrack_module);
+ &usertrack_module);
#if defined(NO_GETTIMEOFDAY) && !defined(NO_TIMES)
clock_t mpe_times;
struct tms mpe_tms;
@@ -138,7 +143,10 @@ static void make_cookie(request_rec *r)
char cookiebuf[1024];
char *new_cookie;
const char *rname = ap_get_remote_host(r->connection, r->per_dir_config,
- REMOTE_NAME);
+ REMOTE_NAME);
+ cookie_dir_rec *dcfg;
+
+ dcfg = ap_get_module_config(r->per_dir_config, &usertrack_module);
#if defined(NO_GETTIMEOFDAY) && !defined(NO_TIMES)
/* We lack gettimeofday(), so we must use time() to obtain the epoch
@@ -147,7 +155,8 @@ static void make_cookie(request_rec *r)
mpe_times = times(&mpe_tms);
- ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%d%ld%ld", rname, (int) getpid(),
+ ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%d%ld%ld", rname,
+ (int) getpid(),
(long) r->request_time, (long) mpe_tms.tms_utime);
#elif defined(WIN32)
/*
@@ -156,13 +165,15 @@ static void make_cookie(request_rec *r)
* was started. It should be relatively unique.
*/
- ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%d%ld%ld", rname, (int) getpid(),
+ ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%d%ld%ld", rname,
+ (int) getpid(),
(long) r->request_time, (long) GetTickCount());
#else
gettimeofday(&tv, &tz);
- ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%d%ld%d", rname, (int) getpid(),
+ ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%d%ld%d", rname,
+ (int) getpid(),
(long) tv.tv_sec, (int) tv.tv_usec / 1000);
#endif
@@ -184,14 +195,16 @@ static void make_cookie(request_rec *r)
/* Cookie with date; as strftime '%a, %d-%h-%y %H:%M:%S GMT' */
new_cookie = ap_psprintf(r->pool,
- "%s%s; path=/; expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT",
- COOKIE_NAME, cookiebuf, ap_day_snames[tms->tm_wday],
+ "%s=%s; path=/; expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT",
+ dcfg->cookie_name, cookiebuf, ap_day_snames[tms->tm_wday],
tms->tm_mday, ap_month_snames[tms->tm_mon],
tms->tm_year % 100,
tms->tm_hour, tms->tm_min, tms->tm_sec);
}
- else
- new_cookie = ap_psprintf(r->pool, "%s%s; path=/", COOKIE_NAME, cookiebuf);
+ else {
+ new_cookie = ap_psprintf(r->pool, "%s=%s; path=/",
+ dcfg->cookie_name, cookiebuf);
+ }
ap_table_setn(r->headers_out, "Set-Cookie", new_cookie);
ap_table_setn(r->notes, "cookie", ap_pstrdup(r->pool, cookiebuf)); /* log first time */
@@ -200,19 +213,20 @@ static void make_cookie(request_rec *r)
static int spot_cookie(request_rec *r)
{
- int *enable = (int *) ap_get_module_config(r->per_dir_config,
- &usertrack_module);
+ cookie_dir_rec *dcfg = ap_get_module_config(r->per_dir_config,
+ &usertrack_module);
const char *cookie;
char *value;
- if (!*enable)
+ if (!dcfg->enabled) {
return DECLINED;
+ }
if ((cookie = ap_table_get(r->headers_in, "Cookie")))
- if ((value = strstr(cookie, COOKIE_NAME))) {
+ if ((value = strstr(cookie, dcfg->cookie_name))) {
char *cookiebuf, *cookieend;
- value += strlen(COOKIE_NAME);
+ value += strlen(dcfg->cookie_name) + 1; /* Skip over the '=' */
cookiebuf = ap_pstrdup(r->pool, value);
cookieend = strchr(cookiebuf, ';');
if (cookieend)
@@ -221,7 +235,7 @@ static int spot_cookie(request_rec *r)
/* Set the cookie in a note, for logging */
ap_table_setn(r->notes, "cookie", cookiebuf);
- return DECLINED; /* Theres already a cookie, no new one */
+ return DECLINED; /* There's already a cookie, no new one */
}
make_cookie(r);
return OK; /* We set our cookie */
@@ -239,12 +253,19 @@ static void *make_cookie_log_state(pool *p, server_rec *s)
static void *make_cookie_dir(pool *p, char *d)
{
- return (void *) ap_pcalloc(p, sizeof(int));
+ cookie_dir_rec *dcfg;
+
+ dcfg = (cookie_dir_rec *) ap_pcalloc(p, sizeof(cookie_dir_rec));
+ dcfg->cookie_name = COOKIE_NAME;
+ dcfg->enabled = 0;
+ return dcfg;
}
-static const char *set_cookie_enable(cmd_parms *cmd, int *c, int arg)
+static const char *set_cookie_enable(cmd_parms *cmd, void *mconfig, int arg)
{
- *c = arg;
+ cookie_dir_rec *dcfg = mconfig;
+
+ dcfg->enabled = arg;
return NULL;
}
@@ -315,11 +336,21 @@ static const char *set_cookie_exp(cmd_parms *parms, void *dummy, const char *arg
return NULL;
}
+static const char *set_cookie_name(cmd_parms *cmd, void *mconfig, char *name)
+{
+ cookie_dir_rec *dcfg = (cookie_dir_rec *) mconfig;
+
+ dcfg->cookie_name = ap_pstrdup(cmd->pool, name);
+ return NULL;
+}
+
static const command_rec cookie_log_cmds[] = {
{"CookieExpires", set_cookie_exp, NULL, RSRC_CONF, TAKE1,
- "an expiry date code"},
+ "an expiry date code"},
{"CookieTracking", set_cookie_enable, NULL, OR_FILEINFO, FLAG,
- "whether or not to enable cookies"},
+ "whether or not to enable cookies"},
+ {"CookieName", set_cookie_name, NULL, OR_FILEINFO, TAKE1,
+ "name of the tracking cookie"},
{NULL}
};
diff --git a/usr.sbin/httpd/src/modules/standard/mod_vhost_alias.c b/usr.sbin/httpd/src/modules/standard/mod_vhost_alias.c
new file mode 100644
index 00000000000..65cc5a2ef41
--- /dev/null
+++ b/usr.sbin/httpd/src/modules/standard/mod_vhost_alias.c
@@ -0,0 +1,482 @@
+/* ====================================================================
+ * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+
+/*
+ * mod_vhost_alias.c: support for dynamically configured mass virtual hosting
+ *
+ * Copyright (c) 1998-1999 Demon Internet Ltd.
+ *
+ * This software was submitted by Demon Internet to the Apache Group
+ * in May 1999. Future revisions and derivatives of this source code
+ * must acknowledge Demon Internet as the original contributor of
+ * this module. All other licensing and usage conditions are those
+ * of the Apache Group.
+ *
+ * Originally written by Tony Finch <fanf@demon.net> <dot@dotat.at>.
+ *
+ * Implementation ideas were taken from mod_alias.c. The overall
+ * concept is derived from the OVERRIDE_DOC_ROOT/OVERRIDE_CGIDIR
+ * patch to Apache 1.3b3 and a similar feature in Demon's thttpd,
+ * both written by James Grinter <jrg@blodwen.demon.co.uk>.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+
+
+module MODULE_VAR_EXPORT vhost_alias_module;
+
+
+/*
+ * basic configuration things
+ * we abbreviate "mod_vhost_alias" to "mva" for shorter names
+ */
+
+typedef enum {
+ VHOST_ALIAS_UNSET, VHOST_ALIAS_NONE, VHOST_ALIAS_NAME, VHOST_ALIAS_IP
+} mva_mode_e;
+
+/*
+ * Per-server module config record.
+ */
+typedef struct mva_sconf_t {
+ char *doc_root;
+ char *cgi_root;
+ mva_mode_e doc_root_mode;
+ mva_mode_e cgi_root_mode;
+} mva_sconf_t;
+
+static void *mva_create_server_config(pool *p, server_rec *s)
+{
+ mva_sconf_t *conf;
+
+ conf = (mva_sconf_t *) ap_pcalloc(p, sizeof(mva_sconf_t));
+ conf->doc_root = NULL;
+ conf->cgi_root = NULL;
+ conf->doc_root_mode = VHOST_ALIAS_UNSET;
+ conf->cgi_root_mode = VHOST_ALIAS_UNSET;
+ return conf;
+}
+
+static void *mva_merge_server_config(pool *p, void *parentv, void *childv)
+{
+ mva_sconf_t *parent = (mva_sconf_t *) parentv;
+ mva_sconf_t *child = (mva_sconf_t *) childv;
+ mva_sconf_t *conf;
+
+ conf = (mva_sconf_t *) ap_pcalloc(p, sizeof(*conf));
+ if (child->doc_root_mode == VHOST_ALIAS_UNSET) {
+ conf->doc_root_mode = parent->doc_root_mode;
+ conf->doc_root = parent->doc_root;
+ }
+ else {
+ conf->doc_root_mode = child->doc_root_mode;
+ conf->doc_root = child->doc_root;
+ }
+ if (child->cgi_root_mode == VHOST_ALIAS_UNSET) {
+ conf->cgi_root_mode = parent->cgi_root_mode;
+ conf->cgi_root = parent->cgi_root;
+ }
+ else {
+ conf->cgi_root_mode = child->cgi_root_mode;
+ conf->cgi_root = child->cgi_root;
+ }
+ return conf;
+}
+
+
+/*
+ * These are just here to tell us what vhost_alias_set should do.
+ * We don't put anything into them; we just use the cell addresses.
+ */
+static int vhost_alias_set_doc_root_ip,
+ vhost_alias_set_cgi_root_ip,
+ vhost_alias_set_doc_root_name,
+ vhost_alias_set_cgi_root_name;
+
+static const char *vhost_alias_set(cmd_parms *cmd, void *dummy, char *map)
+{
+ mva_sconf_t *conf;
+ mva_mode_e mode, *pmode;
+ char **pmap;
+ char *p;
+
+ conf = (mva_sconf_t *) ap_get_module_config(cmd->server->module_config,
+ &vhost_alias_module);
+ /* there ought to be a better way of doing this */
+ if (&vhost_alias_set_doc_root_ip == cmd->info) {
+ mode = VHOST_ALIAS_IP;
+ pmap = &conf->doc_root;
+ pmode = &conf->doc_root_mode;
+ }
+ else if (&vhost_alias_set_cgi_root_ip == cmd->info) {
+ mode = VHOST_ALIAS_IP;
+ pmap = &conf->cgi_root;
+ pmode = &conf->cgi_root_mode;
+ }
+ else if (&vhost_alias_set_doc_root_name == cmd->info) {
+ mode = VHOST_ALIAS_NAME;
+ pmap = &conf->doc_root;
+ pmode = &conf->doc_root_mode;
+ }
+ else if (&vhost_alias_set_cgi_root_name == cmd->info) {
+ mode = VHOST_ALIAS_NAME;
+ pmap = &conf->cgi_root;
+ pmode = &conf->cgi_root_mode;
+ }
+ else {
+ return "INTERNAL ERROR: unknown command info";
+ }
+
+ if (*map != '/') {
+ if (strcasecmp(map, "none")) {
+ return "format string must start with '/' or be 'none'";
+ }
+ *pmap = NULL;
+ *pmode = VHOST_ALIAS_NONE;
+ return NULL;
+ }
+
+ /* sanity check */
+ p = map;
+ while (*p != '\0') {
+ if (*p++ != '%') {
+ continue;
+ }
+ /* we just found a '%' */
+ if (*p == 'p' || *p == '%') {
+ ++p;
+ continue;
+ }
+ /* optional dash */
+ if (*p == '-') {
+ ++p;
+ }
+ /* digit N */
+ if (ap_isdigit(*p)) {
+ ++p;
+ }
+ else {
+ return "syntax error in format string";
+ }
+ /* optional plus */
+ if (*p == '+') {
+ ++p;
+ }
+ /* do we end here? */
+ if (*p != '.') {
+ continue;
+ }
+ ++p;
+ /* optional dash */
+ if (*p == '-') {
+ ++p;
+ }
+ /* digit M */
+ if (ap_isdigit(*p)) {
+ ++p;
+ }
+ else {
+ return "syntax error in format string";
+ }
+ /* optional plus */
+ if (*p == '+') {
+ ++p;
+ }
+ }
+ *pmap = map;
+ *pmode = mode;
+ return NULL;
+}
+
+static const command_rec mva_commands[] =
+{
+ {"VirtualScriptAlias", vhost_alias_set, &vhost_alias_set_cgi_root_name,
+ RSRC_CONF, TAKE1, "how to create a ScriptAlias based on the host"},
+ {"VirtualDocumentRoot", vhost_alias_set, &vhost_alias_set_doc_root_name,
+ RSRC_CONF, TAKE1, "how to create the DocumentRoot based on the host"},
+ {"VirtualScriptAliasIP", vhost_alias_set, &vhost_alias_set_cgi_root_ip,
+ RSRC_CONF, TAKE1, "how to create a ScriptAlias based on the host"},
+ {"VirtualDocumentRootIP", vhost_alias_set, &vhost_alias_set_doc_root_ip,
+ RSRC_CONF, TAKE1, "how to create the DocumentRoot based on the host"},
+ { NULL }
+};
+
+
+/*
+ * This really wants to be a nested function
+ * but C is too feeble to support them.
+ */
+static ap_inline void vhost_alias_checkspace(request_rec *r, char *buf,
+ char **pdest, int size)
+{
+ /* XXX: what if size > HUGE_STRING_LEN? */
+ if (*pdest + size > buf + HUGE_STRING_LEN) {
+ **pdest = '\0';
+ if (r->filename) {
+ r->filename = ap_pstrcat(r->pool, r->filename, buf, NULL);
+ }
+ else {
+ r->filename = ap_pstrdup(r->pool, buf);
+ }
+ *pdest = buf;
+ }
+}
+
+static void vhost_alias_interpolate(request_rec *r, const char *name,
+ const char *map, const char *uri)
+{
+ /* 0..9 9..0 */
+ enum { MAXDOTS = 19 };
+ const char *dots[MAXDOTS+1];
+ int ndots;
+
+ char buf[HUGE_STRING_LEN];
+ char *dest, last;
+
+ int N, M, Np, Mp, Nd, Md;
+ const char *start, *end;
+
+ const char *p;
+
+ ndots = 0;
+ dots[ndots++] = name-1; /* slightly naughty */
+ for (p = name; *p; ++p){
+ if (*p == '.' && ndots < MAXDOTS) {
+ dots[ndots++] = p;
+ }
+ }
+ dots[ndots] = p;
+
+ r->filename = NULL;
+
+ dest = buf;
+ last = '\0';
+ while (*map) {
+ if (*map != '%') {
+ /* normal characters */
+ vhost_alias_checkspace(r, buf, &dest, 1);
+ last = *dest++ = *map++;
+ continue;
+ }
+ /* we are in a format specifier */
+ ++map;
+ /* can't be a slash */
+ last = '\0';
+ /* %% -> % */
+ if (*map == '%') {
+ ++map;
+ vhost_alias_checkspace(r, buf, &dest, 1);
+ *dest++ = '%';
+ continue;
+ }
+ /* port number */
+ if (*map == 'p') {
+ ++map;
+ /* no. of decimal digits in a short plus one */
+ vhost_alias_checkspace(r, buf, &dest, 7);
+ dest += ap_snprintf(dest, 7, "%d", ap_get_server_port(r));
+ continue;
+ }
+ /* deal with %-N+.-M+ -- syntax is already checked */
+ N = M = 0; /* value */
+ Np = Mp = 0; /* is there a plus? */
+ Nd = Md = 0; /* is there a dash? */
+ if (*map == '-') ++map, Nd = 1;
+ N = *map++ - '0';
+ if (*map == '+') ++map, Np = 1;
+ if (*map == '.') {
+ ++map;
+ if (*map == '-') {
+ ++map, Md = 1;
+ }
+ M = *map++ - '0';
+ if (*map == '+') {
+ ++map, Mp = 1;
+ }
+ }
+ /* note that N and M are one-based indices, not zero-based */
+ start = dots[0]+1; /* ptr to the first character */
+ end = dots[ndots]; /* ptr to the character after the last one */
+ if (N != 0) {
+ if (N > ndots) {
+ start = "_";
+ end = start+1;
+ }
+ else if (!Nd) {
+ start = dots[N-1]+1;
+ if (!Np) {
+ end = dots[N];
+ }
+ }
+ else {
+ if (!Np) {
+ start = dots[ndots-N]+1;
+ }
+ end = dots[ndots-N+1];
+ }
+ }
+ if (M != 0) {
+ if (M > end - start) {
+ start = "_";
+ end = start+1;
+ }
+ else if (!Md) {
+ start = start+M-1;
+ if (!Mp) {
+ end = start+1;
+ }
+ }
+ else {
+ if (!Mp) {
+ start = end-M;
+ }
+ end = end-M+1;
+ }
+ }
+ vhost_alias_checkspace(r, buf, &dest, end - start);
+ for (p = start; p < end; ++p) {
+ *dest++ = ap_tolower(*p);
+ }
+ }
+ *dest = '\0';
+ /* no double slashes */
+ if (last == '/') {
+ ++uri;
+ }
+ if (r->filename) {
+ r->filename = ap_pstrcat(r->pool, r->filename, buf, uri, NULL);
+ }
+ else {
+ r->filename = ap_pstrcat(r->pool, buf, uri, NULL);
+ }
+}
+
+static int mva_translate(request_rec *r)
+{
+ mva_sconf_t *conf;
+ const char *name, *map, *uri;
+ mva_mode_e mode;
+ int cgi;
+
+ conf = (mva_sconf_t *) ap_get_module_config(r->server->module_config,
+ &vhost_alias_module);
+ if (!strncmp(r->uri, "/cgi-bin/", 9)) {
+ mode = conf->cgi_root_mode;
+ map = conf->cgi_root;
+ uri = r->uri + 8;
+ /*
+ * can't force cgi immediately because we might not handle this
+ * call if the mode is wrong
+ */
+ cgi = 1;
+ }
+ else if (r->uri[0] == '/') {
+ mode = conf->doc_root_mode;
+ map = conf->doc_root;
+ uri = r->uri;
+ cgi = 0;
+ }
+ else {
+ return DECLINED;
+ }
+
+ if (mode == VHOST_ALIAS_NAME) {
+ name = ap_get_server_name(r);
+ }
+ else if (mode == VHOST_ALIAS_IP) {
+ name = r->connection->local_ip;
+ }
+ else {
+ return DECLINED;
+ }
+
+ vhost_alias_interpolate(r, name, map, uri);
+
+ if (cgi) {
+ /* see is_scriptaliased() in mod_cgi */
+ r->handler = "cgi-script";
+ ap_table_setn(r->notes, "alias-forced-type", r->handler);
+ }
+
+ return OK;
+}
+
+
+module MODULE_VAR_EXPORT vhost_alias_module =
+{
+ STANDARD_MODULE_STUFF,
+ NULL, /* initializer */
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ mva_create_server_config, /* server config */
+ mva_merge_server_config, /* merge server configs */
+ mva_commands, /* command table */
+ NULL, /* handlers */
+ mva_translate, /* filename translation */
+ NULL, /* check_user_id */
+ NULL, /* check auth */
+ NULL, /* check access */
+ NULL, /* type_checker */
+ NULL, /* fixups */
+ NULL, /* logger */
+ NULL, /* header parser */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ NULL /* post read-request */
+};
diff --git a/usr.sbin/httpd/src/os/bs2000/Makefile.tmpl b/usr.sbin/httpd/src/os/bs2000/Makefile.tmpl
index 962b6d624f0..e56c1b618ca 100644
--- a/usr.sbin/httpd/src/os/bs2000/Makefile.tmpl
+++ b/usr.sbin/httpd/src/os/bs2000/Makefile.tmpl
@@ -36,7 +36,49 @@ depend:
&& rm Makefile.new
$(OBJS): Makefile
-os.o: os.c os-inline.c
-ebcdic.o: ebcdic.c
+
# DO NOT REMOVE
-os.o: os.c
+bs2login.o: bs2login.c
+bs2login.o: $(INCDIR)/httpd.h
+bs2login.o: $(INCDIR)/ap_config.h
+bs2login.o: $(INCDIR)/ap_mmn.h
+bs2login.o: $(INCDIR)/ap_config_auto.h
+bs2login.o: os.h
+bs2login.o: $(INCDIR)/ap_ctype.h
+bs2login.o: $(INCDIR)/hsregex.h
+bs2login.o: $(INCDIR)/alloc.h
+bs2login.o: $(INCDIR)/buff.h
+bs2login.o: $(INCDIR)/ap.h
+bs2login.o: ebcdic.h
+bs2login.o: $(INCDIR)/util_uri.h
+bs2login.o: $(INCDIR)/http_config.h
+bs2login.o: $(INCDIR)/http_log.h
+ebcdic.o: ebcdic.c
+ebcdic.o: $(INCDIR)/ap_config.h
+ebcdic.o: $(INCDIR)/ap_mmn.h
+ebcdic.o: $(INCDIR)/ap_config_auto.h
+ebcdic.o: os.h
+ebcdic.o: $(INCDIR)/ap_ctype.h
+ebcdic.o: $(INCDIR)/hsregex.h
+ebcdic.o: ebcdic.h
+os-inline.o: os-inline.c
+os-inline.o: $(INCDIR)/ap_config.h
+os-inline.o: $(INCDIR)/ap_mmn.h
+os-inline.o: $(INCDIR)/ap_config_auto.h
+os-inline.o: os.h
+os-inline.o: $(INCDIR)/ap_ctype.h
+os-inline.o: $(INCDIR)/hsregex.h
+os.o: os.c
+os.o: $(INCDIR)/httpd.h
+os.o: $(INCDIR)/ap_config.h
+os.o: $(INCDIR)/ap_mmn.h
+os.o: $(INCDIR)/ap_config_auto.h
+os.o: os.h
+os.o: $(INCDIR)/ap_ctype.h
+os.o: $(INCDIR)/hsregex.h
+os.o: $(INCDIR)/alloc.h
+os.o: $(INCDIR)/buff.h
+os.o: $(INCDIR)/ap.h
+os.o: ebcdic.h
+os.o: $(INCDIR)/util_uri.h
+os.o: $(INCDIR)/http_core.h
diff --git a/usr.sbin/httpd/src/os/bs2000/bs2login.c b/usr.sbin/httpd/src/os/bs2000/bs2login.c
index f76c536221e..32eb1aecb00 100644
--- a/usr.sbin/httpd/src/os/bs2000/bs2login.c
+++ b/usr.sbin/httpd/src/os/bs2000/bs2login.c
@@ -66,6 +66,17 @@
#define USER_LEN 8
static const char *bs2000_account = NULL;
+typedef enum
+{
+ bs2_unknown, /* not initialized yet. */
+ bs2_noFORK, /* no fork() because -X flag was specified */
+ bs2_FORK, /* only fork() because uid != 0 */
+ bs2_FORK_RINI, /* prior to A17, regular fork() and _rini() was used. */
+ bs2_RFORK_RINI, /* for A17, use of _rfork() and _rini() was required */
+ bs2_UFORK /* As of A18, the new ufork() is used. */
+} bs2_ForkType;
+
+static bs2_ForkType forktype = bs2_unknown;
static void ap_pad(char *dest, size_t size, char ch)
@@ -86,6 +97,75 @@ static void ap_str_toupper(char *str)
}
}
+/* Determine the method for forking off a child in such a way as to
+ * set both the POSIX and BS2000 user id's to the unprivileged user.
+ */
+static bs2_ForkType os_forktype(void)
+{
+ struct utsname os_version;
+
+ /* have we checked the OS version before? If yes return the previous
+ * result - the OS release isn't going to change suddenly!
+ */
+ if (forktype != bs2_unknown) {
+ return forktype;
+ }
+
+ /* If the user is unprivileged, use the normal fork() only. */
+ if (getuid() != 0) {
+ return forktype = bs2_FORK;
+ }
+
+ if (uname(&os_version) < 0)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ALERT, NULL,
+ "uname() failed - aborting.");
+ exit(APEXIT_CHILDFATAL);
+ }
+
+ /*
+ * Old BS2000/OSD versions (before XPG4 SPEC1170) don't work with Apache.
+ * Anyway, simply return a fork().
+ */
+ if (strcmp(os_version.release, "01.0A") == 0 ||
+ strcmp(os_version.release, "02.0A") == 0 ||
+ strcmp(os_version.release, "02.1A") == 0)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
+ "Error: unsupported OS version. "
+ "You may encounter problems.");
+ forktype = bs2_FORK;
+ }
+
+ /* The following versions are special:
+ * OS versions before A17 needs regular fork() and _rini().
+ * A17 requires _rfork() and _rini(),
+ * and later versions need ufork().
+ */
+ else if (strcmp(os_version.release, "01.1A") == 0 ||
+ strcmp(os_version.release, "03.0A") == 0 ||
+ strcmp(os_version.release, "03.1A") == 0 ||
+ strcmp(os_version.release, "04.0A") == 0)
+ {
+ if (strcmp (os_version.version, "A18") >= 0)
+ forktype = bs2_UFORK;
+
+ else if (strcmp (os_version.version, "A17") < 0)
+ forktype = bs2_FORK_RINI;
+
+ else
+ forktype = bs2_RFORK_RINI;
+ }
+
+ /* All later OS versions will hopefully use ufork() only ;-) */
+ else
+ forktype = bs2_UFORK;
+
+ return forktype;
+}
+
+
+
/* This routine is called by http_core for the BS2000Account directive */
/* It stores the account name for later use */
const char *os_set_account(pool *p, const char *account)
@@ -113,6 +193,7 @@ int os_init_job_environment(server_rec *server, const char *user_name, int one_p
_rini_struct inittask;
char username[USER_LEN+1];
int save_errno;
+ bs2_ForkType type = os_forktype();
/* We can be sure that no change to uid==0 is possible because of
* the checks in http_core.c:set_user()
@@ -121,6 +202,20 @@ int os_init_job_environment(server_rec *server, const char *user_name, int one_p
/* The _rini() function works only after a prior _rfork().
* In the case of one_process, it would fail.
*/
+ if (one_process) {
+
+ type = forktype = bs2_noFORK;
+
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, server,
+ "The debug mode of Apache should only "
+ "be started by an unprivileged user!");
+ return 0;
+ }
+
+ /* If no _rini() is required, then return quickly. */
+ if (type != bs2_RFORK_RINI && type != bs2_FORK_RINI)
+ return 0;
+
/* An Account is required for _rini() */
if (bs2000_account == NULL)
{
@@ -130,16 +225,6 @@ int os_init_job_environment(server_rec *server, const char *user_name, int one_p
exit(APEXIT_CHILDFATAL);
}
- /* The one_process test is placed _behind_ the BS2000Account test
- * because we never want the user to forget configuring an account.
- */
- if (one_process) {
- ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, server,
- "The debug mode of Apache should only "
- "be started by an unprivileged user!");
- return 0;
- }
-
ap_cpystrn(username, user_name, sizeof username);
/* Make user name all upper case */
@@ -153,34 +238,13 @@ int os_init_job_environment(server_rec *server, const char *user_name, int one_p
inittask.processor_name = " ";
/* Switch to the new logon user (setuid() and setgid() are done later) */
- /* Only the super use can switch identities. */
+ /* Only the super user can switch identities. */
if (_rini(&inittask) != 0) {
- save_errno = errno;
ap_log_error(APLOG_MARK, APLOG_ALERT, server,
"_rini: BS2000 auth failed for user \"%s\" acct \"%s\"",
inittask.username, inittask.account);
- if (save_errno == EAGAIN) {
- /* This funny error code does NOT mean that the operation should
- * be retried. Instead it means that authentication failed
- * because of possibly incompatible `JOBCLASS'es between
- * the calling (SYSROOT) and the target non-privileged user id.
- * Help the administrator by logging a hint.
- */
- char *curr_user, curr_uid[L_cuserid];
-
- if ((curr_user = cuserid(curr_uid)) == NULL) {
- /* This *SHOULD* not occur. But if it does, deal with it. */
- ap_snprintf(curr_uid, sizeof curr_uid, "#%u", getuid());
- curr_user = curr_uid;
- }
-
- ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, server,
- "_rini: Hint: Possible reason: JOBCLASS of user %s "
- "not compatible with that of user %s ?",
- curr_user, inittask.username);
- }
exit(APEXIT_CHILDFATAL);
}
@@ -188,51 +252,42 @@ int os_init_job_environment(server_rec *server, const char *user_name, int one_p
}
/* BS2000 requires a "special" version of fork() before a setuid()/_rini() call */
-/* Additionally, there's an OS release dependency here :-((( */
-/* I'm sorry, but there was no other way to make it work. -Martin */
-pid_t os_fork(void)
+pid_t os_fork(const char *user)
{
- struct utsname os_version;
-
- /*
- * When we run as a normal user (and bypass setuid() and _rini()),
- * we use the regular fork().
- */
- if (getuid() != 0) {
- return fork();
- }
-
- if (uname(&os_version) >= 0)
- {
- /*
- * Old versions (before XPG4 SPEC1170) don't work with Apache
- * and they require a fork(), not a _rfork()
- */
- if (strcmp(os_version.release, "01.0A") == 0 ||
- strcmp(os_version.release, "02.0A") == 0 ||
- strcmp(os_version.release, "02.1A") == 0)
- {
- return fork();
+ pid_t pid;
+ char username[USER_LEN+1];
+
+ switch (os_forktype()) {
+ case bs2_FORK:
+ case bs2_FORK_RINI:
+ pid = fork();
+ break;
+
+ case bs2_RFORK_RINI:
+ pid = _rfork();
+ break;
+
+ case bs2_UFORK:
+ ap_cpystrn(username, user, sizeof username);
+
+ /* Make user name all upper case - for some versions of ufork() */
+ ap_str_toupper(username);
+
+ pid = ufork(username);
+ if (pid == -1 && errno == EPERM) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG,
+ NULL, "ufork: Possible mis-configuration "
+ "for user %s - Aborting.", user);
+ exit(1);
}
+ break;
- /* The following versions are special:
- * OS versions before A17 work with regular fork() only,
- * later versions with _rfork() only.
- */
- if (strcmp(os_version.release, "01.1A") == 0 ||
- strcmp(os_version.release, "03.0A") == 0 ||
- strcmp(os_version.release, "03.1A") == 0 ||
- strcmp(os_version.release, "04.0A") == 0)
- {
- return (strcmp (os_version.version, "A17") < 0)
- ? fork() : _rfork();
- }
+ default:
+ pid = 0;
+ break;
}
- /* All later OS versions will require _rfork()
- * to prepare for authorization with _rini()
- */
- return _rfork();
+ return pid;
}
#else /* _OSD_POSIX */
diff --git a/usr.sbin/httpd/src/os/bs2000/os.h b/usr.sbin/httpd/src/os/bs2000/os.h
index 93be8ee3d20..1ede0813f2e 100644
--- a/usr.sbin/httpd/src/os/bs2000/os.h
+++ b/usr.sbin/httpd/src/os/bs2000/os.h
@@ -9,8 +9,6 @@
* and prototypes of OS specific functions defined in os.c or os-inline.c
*/
-#include "ap_config.h"
-
#if !defined(INLINE) && defined(USE_GNU_INLINE)
/* Compiler supports inline, so include the inlineable functions as
* part of the header
@@ -32,11 +30,22 @@ extern int ap_os_is_path_absolute(const char *file);
/* Other ap_os_ routines not used by this platform */
#define ap_os_is_filename_valid(f) (1)
+#define ap_os_kill(pid, sig) kill(pid, sig)
+
+#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE)
+typedef struct {
+ char *username;
+ char *account;
+ char *processor_name;
+} _rini_struct;
+
+extern int _rini(_rini_struct *);
+#endif /* !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) */
/* Sorry if this is ugly, but the include order doesn't allow me
* to use request_rec here... */
struct request_rec;
extern int ap_checkconv(struct request_rec *r);
-extern pid_t os_fork(void);
+extern pid_t os_fork(const char *user);
#endif /*! APACHE_OS_H*/
diff --git a/usr.sbin/httpd/src/os/os2/Makefile.tmpl b/usr.sbin/httpd/src/os/os2/Makefile.tmpl
index 2d182cef79c..98e96aaf844 100644
--- a/usr.sbin/httpd/src/os/os2/Makefile.tmpl
+++ b/usr.sbin/httpd/src/os/os2/Makefile.tmpl
@@ -8,13 +8,7 @@ COPY= os.h os-inline.c
LIB= libos.a
-all: $(LIB) copy
-
-copy:
- for i in $(COPY); do \
- rm -f $(INCDIR)/$$i ;\
- cp `pwd`/$$i $(INCDIR)/$$i ;\
- done
+all: $(LIB)
$(LIB): $(OBJS)
rm -f $@
@@ -33,6 +27,12 @@ distclean: clean
$(OBJS): Makefile
+$(INCDIR)/os.h: os.h
+ cp $< $@
+
+$(INCDIR)/os-inline.c: os-inline.c
+ cp $< $@
+
# We really don't expect end users to use this rule. It works only with
# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after
# using it.
@@ -46,4 +46,12 @@ depend:
&& rm Makefile.new
# DO NOT REMOVE
-os.o: os.c os-inline.c
+os-inline.o: os-inline.c $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(INCDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h
+os.o: os.c os.h os-inline.c
+util_os2.o: util_os2.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(INCDIR)/os.h $(INCDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
+ $(INCDIR)/hsregex.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h $(INCDIR)/http_log.h
diff --git a/usr.sbin/httpd/src/os/os2/os.c b/usr.sbin/httpd/src/os/os2/os.c
index 2b5de32e46e..4a45c1fd26e 100644
--- a/usr.sbin/httpd/src/os/os2/os.c
+++ b/usr.sbin/httpd/src/os/os2/os.c
@@ -4,3 +4,55 @@
*/
#include "os.h"
+#define INCL_DOS
+#include <os2.h>
+#include <stdio.h>
+
+static int rc=0;
+
+void ap_os_dso_init(void)
+{
+}
+
+
+
+ap_os_dso_handle_t ap_os_dso_load(const char *module_name)
+{
+ char errorstr[200];
+ HMODULE handle;
+
+ rc = DosLoadModule(errorstr, sizeof(errorstr), module_name, &handle);
+
+ if (rc == 0)
+ return handle;
+
+ return 0;
+}
+
+
+
+void ap_os_dso_unload(ap_os_dso_handle_t handle)
+{
+ DosFreeModule(handle);
+}
+
+
+
+void *ap_os_dso_sym(ap_os_dso_handle_t handle, const char *funcname)
+{
+ PFN func;
+
+ rc = DosQueryProcAddr( handle, 0, funcname, &func );
+
+ if (rc == 0)
+ return func;
+
+ return NULL;
+}
+
+
+
+const char *ap_os_dso_error(void)
+{
+ return ap_os_error_message(rc);
+}
diff --git a/usr.sbin/httpd/src/os/os2/os.h b/usr.sbin/httpd/src/os/os2/os.h
index 0aa5a6f1fe2..d717f1f8ca4 100644
--- a/usr.sbin/httpd/src/os/os2/os.h
+++ b/usr.sbin/httpd/src/os/os2/os.h
@@ -3,6 +3,7 @@
#define PLATFORM "OS/2"
#define HAVE_CANONICAL_FILENAME
+#define HAVE_DRIVE_LETTERS
/*
* This file in included in all Apache source code. It contains definitions
@@ -31,7 +32,21 @@ extern int ap_os_is_path_absolute(const char *file);
/* FIXME: the following should be implemented on this platform */
#define ap_os_is_filename_valid(f) (1)
+/* Use a specialized kill() function */
+int ap_os_kill(int pid, int sig);
+
+/* Maps an OS error code to an error message */
+char *ap_os_error_message(int err);
+
/* OS/2 doesn't have symlinks so S_ISLNK is always false */
#define S_ISLNK(m) 0
+/* Dynamic loading functions */
+#define ap_os_dso_handle_t unsigned long
+void ap_os_dso_init(void);
+ap_os_dso_handle_t ap_os_dso_load(const char *);
+void ap_os_dso_unload(ap_os_dso_handle_t);
+void * ap_os_dso_sym(ap_os_dso_handle_t, const char *);
+const char *ap_os_dso_error(void);
+
#endif /* ! APACHE_OS_H */
diff --git a/usr.sbin/httpd/src/os/os2/util_os2.c b/usr.sbin/httpd/src/os/os2/util_os2.c
index 91fe4d444b5..820ea618008 100644
--- a/usr.sbin/httpd/src/os/os2/util_os2.c
+++ b/usr.sbin/httpd/src/os/os2/util_os2.c
@@ -1,4 +1,5 @@
-#define INCL_DOSFILEMGR
+#define INCL_DOS
+#define INCL_DOSERRORS
#include <os2.h>
#include "httpd.h"
#include "http_log.h"
@@ -19,7 +20,16 @@ API_EXPORT(char *)ap_os_canonical_filename(pool *pPool, const char *szFile)
buf[--len] = 0;
rc = DosQueryPathInfo(buf, FIL_QUERYFULLNAME, buf2, HUGE_STRING_LEN);
- ap_assert(rc == 0);
+
+ if (rc) {
+ if ( rc != ERROR_INVALID_NAME ) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL, "OS/2 error %d for file %s", rc, szFile);
+ return ap_pstrdup(pPool, "");
+ } else {
+ return ap_pstrdup(pPool, szFile);
+ }
+ }
+
strlwr(buf2);
/* Switch backslashes to forward */
@@ -29,3 +39,58 @@ API_EXPORT(char *)ap_os_canonical_filename(pool *pPool, const char *szFile)
return ap_pstrdup(pPool, buf2);
}
+
+
+
+int ap_os_kill(pid_t pid, int sig)
+{
+/* SIGTERM's don't work too well in OS/2 (only affects other EMX programs).
+ CGIs may not be, esp. REXX scripts, so use a native call instead */
+
+ int rc;
+
+ if ( sig == SIGTERM ) {
+ rc = DosSendSignalException( pid, XCPT_SIGNAL_BREAK );
+
+ if ( rc ) {
+ errno = ESRCH;
+ rc = -1;
+ }
+ } else {
+ rc = kill(pid, sig);
+ }
+
+ return rc;
+}
+
+
+
+char *ap_os_error_message(int err)
+{
+ static char result[200];
+ char message[HUGE_STRING_LEN];
+ ULONG len;
+ char *pos;
+ int c;
+
+ if (DosGetMessage(NULL, 0, message, HUGE_STRING_LEN, err, "OSO001.MSG", &len) == 0) {
+ len--;
+ message[len] = 0;
+ pos = result;
+
+ if (len >= sizeof(result))
+ len = sizeof(result-1);
+
+ for (c=0; c<len; c++) {
+ while (isspace(message[c]) && isspace(message[c+1])) /* skip multiple whitespace */
+ c++;
+ *(pos++) = isspace(message[c]) ? ' ' : message[c];
+ }
+
+ *pos = 0;
+ } else {
+ sprintf(result, "OS/2 error %d", err);
+ }
+
+ return result;
+}
diff --git a/usr.sbin/httpd/src/os/tpf/Makefile.tmpl b/usr.sbin/httpd/src/os/tpf/Makefile.tmpl
index ad54c1b84a4..14aa0899b1f 100644
--- a/usr.sbin/httpd/src/os/tpf/Makefile.tmpl
+++ b/usr.sbin/httpd/src/os/tpf/Makefile.tmpl
@@ -3,7 +3,7 @@ LIBS=$(EXTRA_LIBS) $(LIBS1)
INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
-OBJS= os.o os-inline.o ebcdic.o
+OBJS= os.o os-inline.o ebcdic.o cgetop.o
LIB= libos.a
@@ -35,7 +35,8 @@ depend:
&& rm Makefile.new
$(OBJS): Makefile
-os.o: os.c os-inline.c
+os.o: os.c os-inline.c $(INCDIR)/ap_config.h
ebcdic.o: ebcdic.c
+cgetop.o: cgetop.c
# DO NOT REMOVE
os.o: os.c
diff --git a/usr.sbin/httpd/src/os/tpf/cgetop.c b/usr.sbin/httpd/src/os/tpf/cgetop.c
new file mode 100644
index 00000000000..90ffbce5f45
--- /dev/null
+++ b/usr.sbin/httpd/src/os/tpf/cgetop.c
@@ -0,0 +1,151 @@
+/**********************************************************************/
+/* */
+/* Copyright (c) 1987, 1993, 1994 */
+/* The Regents of the University of California. All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following conditions */
+/* are met: */
+/* */
+/* 1. Redistributions of source code must retain the above copyright */
+/* notice, this list of conditions and the following disclaimer. */
+/* 2. Redistributions in binary form must reproduce the above */
+/* copyright notice, this list of conditions and the following */
+/* disclaimer in the documentation and/or other materials provided */
+/* with the distribution. */
+/* 3. All advertising materials mentioning features or use of this */
+/* software must display the following acknowledgement: */
+/* This product includes software developed by the University of */
+/* California, Berkeley and its contributors. */
+/* 4. Neither the name of the University nor the names of its */
+/* contributors may be used to endorse or promote products derived */
+/* from this software without specific prior written permission. */
+/* */
+/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''*/
+/* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */
+/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A */
+/* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS */
+/* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
+/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
+/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF */
+/* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND*/
+/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */
+/* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT */
+/* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF */
+/* SUCH DAMAGE. */
+/* */
+/**********************************************************************/
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getopt.c 8.2 (Berkeley) 4/2/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef __CGETOP_
+extern char *optarg;
+extern int opterr, optind, optopt;
+int getopt (int, char * const *, const char *);
+char *group_from_gid (unsigned long, int);
+char *user_from_uid (unsigned long, int);
+extern int optreset;
+#endif
+
+int opterr = 1, /* if error message should be */
+ /* printed */
+ optind = 1, /* index into parent argv vector */
+ optopt, /* character checked for validity */
+ optreset; /* reset getopt */
+char *optarg; /* argument associated with */
+ /* option */
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+/**********************************************************************/
+/* */
+/* getopt -- */
+/* Parse argc/argv argument vector. */
+/* */
+/**********************************************************************/
+int
+getopt(nargc, nargv, ostr)
+ int nargc;
+ char * const *nargv;
+ const char *ostr;
+{
+ /* removed -- BSD2TPF -- crt0 does not create __progname on TPF */
+ /* extern char *__progname; */
+ /* end of removed -- BSD2TPF */
+
+ static char *place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+
+ /* added -- BSD2TPF -- emulate BSD crt0 function to set __progname */
+ char empty = '\0';
+ char *__progname = &empty;
+ if (nargv[0]) {
+ if ((__progname = strrchr(nargv[0], '/')) == NULL) {
+ __progname = nargv[0];
+ }
+ else {
+ ++__progname;
+ }
+ }
+ /* end of added -- BSD2TPF */
+
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc || *(place = nargv[optind]) != '-') {
+ place = EMSG;
+ return (EOF);
+ }
+ if (place[1] && *++place == '-') {
+ /* found "--" */
+ ++optind;
+ place = EMSG;
+ return (EOF);
+ }
+ } /* option letter okay? */
+ if ((optopt = (int)*place++) == (int)':' ||
+ !(oli = strchr(ostr, optopt))) {
+ /* if the user didn't */
+ /* specify '-' as an option, */
+ /* assume it means EOF. */
+ if (optopt == (int)'-')
+ return (EOF);
+ if (!*place)
+ ++optind;
+ if (opterr && *ostr != ':')
+ (void)fprintf(stderr,
+ "%s: illegal option -- %c\n", __progname, optopt);
+ return (BADCH);
+ }
+ if (*++oli != ':') { /* don't need argument */
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ }
+ else { /* need an argument */
+ if (*place) /* no white space */
+ optarg = place;
+ else if (nargc <= ++optind) { /* no arg */
+ place = EMSG;
+ if (*ostr == ':')
+ return (BADARG);
+ if (opterr)
+ (void)fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ __progname, optopt);
+ return (BADCH);
+ }
+ else /* white space */
+ optarg = nargv[optind];
+ place = EMSG;
+ ++optind;
+ }
+ return (optopt); /* dump back option letter */
+} \ No newline at end of file
diff --git a/usr.sbin/httpd/src/os/tpf/os.c b/usr.sbin/httpd/src/os/tpf/os.c
index aea4d961f4e..e4682324cd1 100644
--- a/usr.sbin/httpd/src/os/tpf/os.c
+++ b/usr.sbin/httpd/src/os/tpf/os.c
@@ -63,6 +63,11 @@
#include "httpd.h"
#include "http_core.h"
#include "os.h"
+#include "scoreboard.h"
+#include "http_log.h"
+#include "http_conf_globals.h"
+
+static FILE *sock_fp;
/* Check the Content-Type to decide if conversion is needed */
int ap_checkconv(struct request_rec *r)
@@ -87,14 +92,22 @@ int ap_checkconv(struct request_rec *r)
if (type && (strncasecmp(type, "text/", 5) == 0 ||
strncasecmp(type, "message/", 8) == 0)) {
if (strncasecmp(type, ASCIITEXT_MAGIC_TYPE_PREFIX,
- sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1) == 0)
+ sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1) == 0){
r->content_type = ap_pstrcat(r->pool, "text/",
- type+sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1,
- NULL);
+ type+sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1, NULL);
+ if (r->method_number == M_PUT)
+ ap_bsetflag(r->connection->client, B_ASCII2EBCDIC, 0);
+ }
+
else
/* translate EBCDIC to ASCII */
convert_to_ascii = 1;
}
+ else{
+ if (r->method_number == M_PUT)
+ ap_bsetflag(r->connection->client, B_ASCII2EBCDIC, 0);
+ /* don't translate non-text files to EBCDIC */
+ }
/* Enable conversion if it's a text document */
ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, convert_to_ascii);
@@ -103,51 +116,65 @@ int ap_checkconv(struct request_rec *r)
int tpf_select(int maxfds, fd_set *reads, fd_set *writes, fd_set *excepts, struct timeval *tv)
{
- int sockets[24];
+/* We're going to force our way through select. We're only interested reads and TPF allows
+ 2billion+ socket descriptors for we don't want an fd_set that big. Just assume that maxfds-1
+ contains the socket descriptor we're interested in. If it's 0, leave it alone. */
+
+ int sockets[1];
int no_reads = 0;
int no_writes = 0;
int no_excepts = 0;
int timeout = 0;
- int counter = 0;
- int i;
- fd_set *temp;
+ int rv;
if(maxfds) {
- if(reads)
- temp = reads;
- else if(writes)
- temp = writes;
- else if(excepts)
- temp = excepts;
+ if(tv)
+ timeout = tv->tv_sec * 1000 + tv->tv_usec;
+ sockets[0] = maxfds-1;
+ no_reads++;
+ }
else
- temp = NULL;
+ sockets[0] = 0;
- for(i=0; i<maxfds; i++) {
- if(FD_ISSET(i,temp)) {
- sockets[counter] = i;
- counter++;
- }
- }
+ ap_check_signals();
+ rv = select(sockets, no_reads, no_writes, no_excepts, timeout);
+ ap_check_signals();
- if(tv)
- timeout = tv->tv_sec * 1000 + tv->tv_usec;
+ return rv;
+
+}
- if(reads)
- no_reads = counter;
- else if(writes)
- no_writes = counter;
- else if(excepts)
- no_excepts = counter;
+int tpf_accept(int sockfd, struct sockaddr *peer, int *paddrlen)
+{
+ int socks[1];
+ int rv;
+
+ ap_check_signals();
+ socks[0] = sockfd;
+ rv = select(socks, 1, 0, 0, 1000);
+ errno = sock_errno();
+ if(rv>0) {
+ ap_check_signals();
+ rv = accept(sockfd, peer, paddrlen);
+ errno = sock_errno();
}
- return select(sockets, no_reads, no_writes, no_excepts, timeout);
+ return rv;
}
-/* pipe is not yet available on TPF */
+/* the getpass function is not usable on TPF */
+char *getpass(const char* prompt)
+{
+ errno = EIO;
+ return((char *)NULL);
+}
+
+#ifndef __PIPE_
int pipe(int fildes[2])
{
errno = ENOSYS;
return(-1);
}
+#endif
/* fork and exec functions are not defined on
TPF due to the implementation of tpf_fork() */
@@ -175,3 +202,213 @@ int execve(const char *path, char *const argv[], char *const envp[])
errno = ENOSYS;
return(-1);
}
+
+int execvp(const char *file, char *const argv[])
+{
+ errno = ENOSYS;
+ return(-1);
+}
+
+
+
+int ap_tpf_spawn_child(pool *p, int (*func) (void *, child_info *),
+ void *data, enum kill_conditions kill_how,
+ int *pipe_in, int *pipe_out, int *pipe_err,
+ int out_fds[], int in_fds[], int err_fds[])
+
+{
+
+ int i, temp_out, temp_in, temp_err, save_errno, pid, result=0;
+ int fd_flags_out, fd_flags_in, fd_flags_err;
+ struct tpf_fork_input fork_input;
+ TPF_FORK_CHILD *cld = (TPF_FORK_CHILD *) data;
+ array_header *env_arr = ap_table_elts ((array_header *) cld->subprocess_env);
+ table_entry *elts = (table_entry *) env_arr->elts;
+
+
+
+ if (func) {
+ if (result=func(data, NULL)) {
+ return 0; /* error from child function */
+ }
+ }
+
+ if (pipe_out) {
+ fd_flags_out = fcntl(out_fds[0], F_GETFD);
+ fcntl(out_fds[0], F_SETFD, FD_CLOEXEC);
+ temp_out = dup(STDOUT_FILENO);
+ fcntl(temp_out, F_SETFD, FD_CLOEXEC);
+ dup2(out_fds[1], STDOUT_FILENO);
+ }
+
+
+ if (pipe_in) {
+ fd_flags_in = fcntl(in_fds[1], F_GETFD);
+ fcntl(in_fds[1], F_SETFD, FD_CLOEXEC);
+ temp_in = dup(STDIN_FILENO);
+ fcntl(temp_in, F_SETFD, FD_CLOEXEC);
+ dup2(in_fds[0], STDIN_FILENO);
+ }
+
+ if (pipe_err) {
+ fd_flags_err = fcntl(err_fds[0], F_GETFD);
+ fcntl(err_fds[0], F_SETFD, FD_CLOEXEC);
+ temp_err = dup(STDERR_FILENO);
+ fcntl(temp_err, F_SETFD, FD_CLOEXEC);
+ dup2(err_fds[1], STDERR_FILENO);
+ }
+
+ if (cld->subprocess_env) {
+ for (i = 0; i < env_arr->nelts; ++i) {
+ if (!elts[i].key)
+ continue;
+ setenv (elts[i].key, elts[i].val, 1);
+ }
+ }
+
+ fork_input.program = (const char*) cld->filename;
+ fork_input.prog_type = cld->prog_type;
+ fork_input.istream = TPF_FORK_IS_BALANCE;
+ fork_input.ebw_data_length = 0;
+ fork_input.ebw_data = NULL;
+ fork_input.parm_data = NULL;
+
+
+ if ((pid = tpf_fork(&fork_input)) < 0) {
+ save_errno = errno;
+ if (pipe_out) {
+ close(out_fds[0]);
+ }
+ if (pipe_in) {
+ close(in_fds[1]);
+ }
+ if (pipe_err) {
+ close(err_fds[0]);
+ }
+ errno = save_errno;
+ pid = 0;
+ }
+
+ if (cld->subprocess_env) {
+ for (i = 0; i < env_arr->nelts; ++i) {
+ if (!elts[i].key)
+ continue;
+ unsetenv (elts[i].key);
+ }
+ }
+
+ if (pipe_out) {
+ close(out_fds[1]);
+ dup2(temp_out, STDOUT_FILENO);
+ close(temp_out);
+ fcntl(out_fds[0], F_SETFD, fd_flags_out);
+ }
+
+ if (pipe_in) {
+ close(in_fds[0]);
+ dup2(temp_in, STDIN_FILENO);
+ close(temp_in);
+ fcntl(in_fds[1], F_SETFD, fd_flags_in);
+ }
+
+
+ if (pipe_err) {
+ close(err_fds[1]);
+ dup2(temp_err, STDERR_FILENO);
+ close(temp_err);
+ fcntl(err_fds[0], F_SETFD, fd_flags_err);
+ }
+
+
+ if (pid) {
+
+ ap_note_subprocess(p, pid, kill_how);
+
+ if (pipe_out) {
+ *pipe_out = out_fds[0];
+ }
+ if (pipe_in) {
+ *pipe_in = in_fds[1];
+ }
+ if (pipe_err) {
+ *pipe_err = err_fds[0];
+ }
+ }
+
+ return pid;
+
+}
+
+pid_t os_fork(server_rec *s, int slot)
+{
+ struct tpf_fork_input fork_input;
+ APACHE_TPF_INPUT input_parms;
+ int count;
+ listen_rec *lr;
+
+ fflush(stdin);
+ if (dup2(fileno(sock_fp), STDIN_FILENO) == -1)
+ ap_log_error(APLOG_MARK, APLOG_CRIT, s,
+ "unable to replace stdin with sock device driver");
+ fflush(stdout);
+ if (dup2(fileno(sock_fp), STDOUT_FILENO) == -1)
+ ap_log_error(APLOG_MARK, APLOG_CRIT, s,
+ "unable to replace stdout with sock device driver");
+ input_parms.generation = ap_my_generation;
+#ifdef SCOREBOARD_FILE
+ input_parms.scoreboard_fd = scoreboard_fd;
+#else /* must be USE_TPF_SCOREBOARD or USE_SHMGET_SCOREBOARD */
+ input_parms.scoreboard_heap = ap_scoreboard_image;
+#endif
+
+ lr = ap_listeners;
+ count = 0;
+ do {
+ input_parms.listeners[count] = lr->fd;
+ lr = lr->next;
+ count++;
+ } while(lr != ap_listeners);
+
+ input_parms.slot = slot;
+ input_parms.restart_time = ap_restart_time;
+ fork_input.ebw_data = &input_parms;
+ fork_input.program = ap_server_argv0;
+ fork_input.prog_type = TPF_FORK_NAME;
+ fork_input.istream = TPF_FORK_IS_BALANCE;
+ fork_input.ebw_data_length = sizeof(input_parms);
+ fork_input.parm_data = "-x";
+ return tpf_fork(&fork_input);
+}
+
+int os_check_server(char *server) {
+ #ifndef USE_TPF_DAEMON
+ int rv;
+ int *current_acn;
+ if((rv = inetd_getServerStatus(server)) == INETD_SERVER_STATUS_INACTIVE)
+ return 1;
+ else {
+ current_acn = (int *)cinfc_fast(CINFC_CMMACNUM);
+ if(ecbp2()->ce2acn != *current_acn)
+ return 1;
+ }
+ #endif
+ return 0;
+}
+
+void os_note_additional_cleanups(pool *p, int sd) {
+ char sockfilename[50];
+ /* write the socket to file so that TPF socket device driver will close socket in case
+ we happen to abend. */
+ sprintf(sockfilename, "/dev/tpf.socket.file/%.8X", sd);
+ sock_fp = fopen(sockfilename, "r+");
+ ap_note_cleanups_for_file(p, sock_fp); /* arrange to close on exec or restart */
+ fcntl(sd,F_SETFD,FD_CLOEXEC);
+}
+
+void os_tpf_child(APACHE_TPF_INPUT *input_parms) {
+ tpf_child = 1;
+ ap_my_generation = input_parms->generation;
+ ap_restart_time = input_parms->restart_time;
+}
+
+
diff --git a/usr.sbin/httpd/src/os/tpf/os.h b/usr.sbin/httpd/src/os/tpf/os.h
index 9a94bcc96c2..ff653229029 100644
--- a/usr.sbin/httpd/src/os/tpf/os.h
+++ b/usr.sbin/httpd/src/os/tpf/os.h
@@ -20,9 +20,6 @@
* part of the header
*/
#define INLINE extern ap_inline
-
-INLINE int ap_os_is_path_absolute(const char *file);
-
#include "os-inline.c"
#endif
@@ -30,82 +27,82 @@ INLINE int ap_os_is_path_absolute(const char *file);
/* Compiler does not support inline, so prototype the inlineable functions
* as normal
*/
-extern int ap_os_is_path_absolute(const char *file);
+extern int ap_os_is_path_absolute(const char *f);
#endif
/* Other ap_os_ routines not used by this platform */
#define ap_os_is_filename_valid(f) (1)
+#define ap_os_kill(pid, sig) kill(pid, sig)
/* Sorry if this is ugly, but the include order doesn't allow me
* to use request_rec here... */
struct request_rec;
extern int ap_checkconv(struct request_rec *r);
-#ifdef FD_SETSIZE
-#undef FD_SETSIZE
-#endif
+#include <strings.h>
+#ifndef __strings_h
#define FD_SETSIZE 2048
-#ifdef __FD_MASK
-#undef __FD_MASK
-#endif
-
-typedef long __FD_MASK;
-
-#ifdef __NBBY
-#undef __NBBY
-#endif
-
-#define __NBBY 8 /* number of bits in a byte */
-
-#ifdef __NFDBITS
-#undef __NFDBITS
-#endif
+typedef long fd_mask;
-#define __NFDBITS (sizeof(__FD_MASK) * __NBBY)
+#define NBBY 8 /* number of bits in a byte */
+#define NFDBITS (sizeof(fd_mask) * NBBY)
+#define howmany(x, y) (((x)+((y)-1))/(y))
-#ifndef __howmany
-#define __howmany(x, y) (((x)+((y)-1))/(y))
-#endif
-
typedef struct fd_set {
- __FD_MASK fds_bits [__howmany(FD_SETSIZE, __NFDBITS)];
+ fd_mask fds_bits [howmany(FD_SETSIZE, NFDBITS)];
} fd_set;
-#define FD_SET(n, p)((p)->fds_bits[(n)/__NFDBITS] |= (1 <<((n) % __NFDBITS)))
-
-#define FD_CLR(n, p)((p)->fds_bits[(n)/__NFDBITS] &= ~(1 << ((n) % __NFDBITS)))
-
-#define FD_ISSET(n, p)((p)->fds_bits[(n)/__NFDBITS] & (1 <<((n) % __NFDBITS)))
-
+#define FD_CLR(n, p)((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define FD_ISSET(n, p)((p)->fds_bits[(n)/NFDBITS] & (1 <<((n) % NFDBITS)))
#define FD_ZERO(p) memset((char *)(p), 0, sizeof(*(p)))
+#endif
+#ifdef FD_SET
+#undef FD_SET
+#define FD_SET(n, p) (0)
+#endif
-#define SIGPIPE 13
-#define SIGQUIT 24
-#define SO_KEEPALIVE 0x0008
+#define RESOURCE_KEY ((void*) 0xC1C2C1C3)
/* TPF doesn't have, or need, tzset (it is used in mod_expires.c) */
#define tzset()
-#include <stdarg.h>
-#undef va_list
-#undef va_start
-#undef va_arg
-#undef va_end
-
-typedef char *va_list;
-
-#define __va_promote(type) (((sizeof(type) + sizeof(int) - 1) \
- / sizeof(int)) * sizeof(int))
-
-#define va_start(ap, last) (ap = ((char *)&(last) + __va_promote(last)))
-
-#define va_arg(ap, type) ((type *)(ap += sizeof(type) < sizeof(int) ? \
- (abort(), 0) : sizeof(type)))[-1]
-
-#define va_end(ap)
-
+#include <i$netd.h>
+struct apache_input {
+ INETD_SERVER_INPUT inetd_server;
+ void *scoreboard_heap; /* scoreboard system heap address */
+ int scoreboard_fd; /* scoreboard file descriptor */
+ int slot; /* child number */
+ int generation; /* server generation number */
+ int listeners[10];
+ time_t restart_time;
+};
+
+typedef struct apache_input APACHE_TPF_INPUT;
+
+typedef struct tpf_fork_child {
+ char *filename;
+ enum { FORK_NAME = 1, FORK_FILE = 2 } prog_type;
+ void *subprocess_env;
+}TPF_FORK_CHILD;
+
+int tpf_accept(int sockfd, struct sockaddr *peer, int *paddrlen);
+extern int tpf_child;
+
+struct server_rec;
+pid_t os_fork(struct server_rec *s, int slot);
+int os_check_server(char *server);
+char *getpass(const char *prompt);
+extern char *ap_server_argv0;
+extern int scoreboard_fd;
+#include <signal.h>
+#ifndef SIGPIPE
+#define SIGPIPE 14
+#endif
+#ifdef NSIG
+#undef NSIG
+#endif
#endif /*! APACHE_OS_H*/
diff --git a/usr.sbin/httpd/src/os/unix/os.c b/usr.sbin/httpd/src/os/unix/os.c
index 776b3c7e19d..18a0395da62 100644
--- a/usr.sbin/httpd/src/os/unix/os.c
+++ b/usr.sbin/httpd/src/os/unix/os.c
@@ -26,8 +26,15 @@ void ap_is_not_here(void) {}
* dynamic shared object (DSO) mechanism
*/
-#ifdef RHAPSODY
+#ifdef HAVE_DYLD /* NeXT/Apple dynamic linker */
#include <mach-o/dyld.h>
+
+/*
+ * NSUnlinkModule() is a noop in old versions of dyld.
+ * Let's install an error handler to deal with "multiply defined
+ * symbol" runtime errors.
+ */
+#ifdef DYLD_CANT_UNLOAD
#include "httpd.h"
#include "http_log.h"
@@ -49,7 +56,6 @@ NSModule multiple_symbol_handler (NSSymbol s, NSModule old, NSModule new)
* every time we reload a module. Workaround here is to just
* rebind to the new symbol, and forget about the old one.
* This is crummy, because it's basically a memory leak.
- * (See Radar 2262020 against dyld).
*/
#ifdef DEBUG
@@ -73,11 +79,12 @@ void linkEdit_symbol_handler (NSLinkEditErrors c, int errorNumber,
abort();
}
-#endif /*RHAPSODY*/
+#endif /* DYLD_CANT_UNLOAD */
+#endif /* HAVE_DYLD */
void ap_os_dso_init(void)
{
-#if defined(RHAPSODY)
+#if defined(HAVE_DYLD) && defined(DYLD_CANT_UNLOAD)
NSLinkEditErrorHandlers handlers;
handlers.undefined = undefined_symbol_handler;
@@ -95,14 +102,14 @@ void *ap_os_dso_load(const char *path)
handle = shl_load(path, BIND_IMMEDIATE|BIND_VERBOSE|BIND_NOSTART, 0L);
return (void *)handle;
-#elif defined(RHAPSODY)
+#elif defined(HAVE_DYLD)
NSObjectFileImage image;
if (NSCreateObjectFileImageFromFile(path, &image) !=
NSObjectFileImageSuccess)
return NULL;
return NSLinkModule(image, path, TRUE);
-#elif defined(OSF1) ||\
+#elif defined(OSF1) || defined(SEQUENT) ||\
(defined(__FreeBSD_version) && (__FreeBSD_version >= 220000))
return dlopen((char *)path, RTLD_NOW | RTLD_GLOBAL);
@@ -116,7 +123,7 @@ void ap_os_dso_unload(void *handle)
#if defined(HPUX) || defined(HPUX10)
shl_unload((shl_t)handle);
-#elif defined(RHAPSODY)
+#elif defined(HAVE_DYLD)
NSUnLinkModule(handle,FALSE);
#else
@@ -138,7 +145,7 @@ void *ap_os_dso_sym(void *handle, const char *symname)
status = shl_findsym((shl_t *)&handle, symname, TYPE_DATA, &symaddr);
return (status == -1 ? NULL : symaddr);
-#elif defined(RHAPSODY)
+#elif defined(HAVE_DYLD)
NSSymbol symbol;
char *symname2 = (char*)malloc(sizeof(char)*(strlen(symname)+2));
sprintf(symname2, "_%s", symname);
@@ -154,6 +161,9 @@ void *ap_os_dso_sym(void *handle, const char *symname)
free(symbol);
return retval;
+#elif defined(SEQUENT)
+ return dlsym(handle, (char *)symname);
+
#else
return dlsym(handle, symname);
#endif
@@ -163,7 +173,7 @@ const char *ap_os_dso_error(void)
{
#if defined(HPUX) || defined(HPUX10)
return strerror(errno);
-#elif defined(RHAPSODY)
+#elif defined(HAVE_DYLD)
return NULL;
#else
return dlerror();
diff --git a/usr.sbin/httpd/src/os/unix/os.h b/usr.sbin/httpd/src/os/unix/os.h
index 496cfa9f9e8..6689dfae5c6 100644
--- a/usr.sbin/httpd/src/os/unix/os.h
+++ b/usr.sbin/httpd/src/os/unix/os.h
@@ -60,7 +60,9 @@
#include "ap_config.h"
+#ifndef PLATFORM
#define PLATFORM "Unix"
+#endif
/*
* This file in included in all Apache source code. It contains definitions
@@ -89,6 +91,7 @@ extern int ap_os_is_path_absolute(const char *file);
/* Other ap_os_ routines not used by this platform */
#define ap_os_is_filename_valid(f) (1)
+#define ap_os_kill(pid, sig) kill(pid, sig)
/*
* Abstraction layer for loading
diff --git a/usr.sbin/httpd/src/os/win32/ApacheModuleRewrite.dsp b/usr.sbin/httpd/src/os/win32/ApacheModuleRewrite.dsp
index 91de834bc45..4a0ffd1bf68 100644
--- a/usr.sbin/httpd/src/os/win32/ApacheModuleRewrite.dsp
+++ b/usr.sbin/httpd/src/os/win32/ApacheModuleRewrite.dsp
@@ -45,7 +45,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
@@ -55,7 +55,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
-# ADD LINK32 ..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 ..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:windows /dll /machine:I386
!ELSEIF "$(CFG)" == "ApacheModuleRewrite - Win32 Debug"
@@ -71,7 +71,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
@@ -81,7 +81,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
-# ADD LINK32 ..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 ..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:windows /dll /debug /machine:I386
!ENDIF
diff --git a/usr.sbin/httpd/src/os/win32/ApacheModuleRewrite.mak b/usr.sbin/httpd/src/os/win32/ApacheModuleRewrite.mak
index cd9de2327c6..6d2e5659088 100644
--- a/usr.sbin/httpd/src/os/win32/ApacheModuleRewrite.mak
+++ b/usr.sbin/httpd/src/os/win32/ApacheModuleRewrite.mak
@@ -64,7 +64,7 @@ CLEAN :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\
- "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE"\
+ "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN"\
/Fp"$(INTDIR)\ApacheModuleRewrite.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\
/FD /c
CPP_OBJS=.\ApacheModuleRewriteR/
@@ -76,7 +76,7 @@ BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\
- winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo\
+ winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo\
/subsystem:windows /dll /incremental:no\
/pdb:"$(OUTDIR)\ApacheModuleRewrite.pdb" /machine:I386\
/out:"$(OUTDIR)\ApacheModuleRewrite.dll"\
@@ -123,9 +123,9 @@ CLEAN :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\
- "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE"\
- /Fp"$(INTDIR)\ApacheModuleRewrite.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\
- /FD /c
+ "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /D\
+ "WIN32_LEAN_AND_MEAN" /Fp"$(INTDIR)\ApacheModuleRewrite.pch" /YX\
+ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
CPP_OBJS=.\ApacheModuleRewriteD/
CPP_SBRS=.
MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
@@ -135,7 +135,7 @@ BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\
- winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo\
+ winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo\
/subsystem:windows /dll /incremental:yes\
/pdb:"$(OUTDIR)\ApacheModuleRewrite.pdb" /debug /machine:I386\
/out:"$(OUTDIR)\ApacheModuleRewrite.dll"\
@@ -191,18 +191,21 @@ SOURCE=..\..\modules\standard\mod_rewrite.c
DEP_CPP_MOD_R=\
"..\..\include\alloc.h"\
"..\..\include\ap.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
"..\..\include\ap_mmn.h"\
"..\..\include\buff.h"\
- "..\..\include\conf.h"\
"..\..\include\hsregex.h"\
+ "..\..\include\http_conf_globals.h"\
"..\..\include\http_config.h"\
"..\..\include\http_core.h"\
"..\..\include\http_log.h"\
"..\..\include\http_request.h"\
+ "..\..\include\http_vhost.h"\
"..\..\include\httpd.h"\
+ "..\..\include\util_uri.h"\
"..\..\modules\standard\mod_rewrite.h"\
".\os.h"\
- ".\passwd.h"\
".\readdir.h"\
@@ -215,10 +218,12 @@ DEP_CPP_MOD_R=\
DEP_CPP_MOD_R=\
"..\..\include\alloc.h"\
"..\..\include\ap.h"\
+ "..\..\include\ap_config.h"\
+ "..\..\include\ap_ctype.h"\
"..\..\include\ap_mmn.h"\
"..\..\include\buff.h"\
- "..\..\include\conf.h"\
"..\..\include\hsregex.h"\
+ "..\..\include\http_conf_globals.h"\
"..\..\include\http_config.h"\
"..\..\include\http_core.h"\
"..\..\include\http_log.h"\
diff --git a/usr.sbin/httpd/src/os/win32/apache.ico b/usr.sbin/httpd/src/os/win32/apache.ico
new file mode 100644
index 00000000000..161bcf7841c
--- /dev/null
+++ b/usr.sbin/httpd/src/os/win32/apache.ico
Binary files differ
diff --git a/usr.sbin/httpd/src/os/win32/apache.rc b/usr.sbin/httpd/src/os/win32/apache.rc
new file mode 100644
index 00000000000..6dde63f9501
--- /dev/null
+++ b/usr.sbin/httpd/src/os/win32/apache.rc
@@ -0,0 +1,84 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winresrc.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_APACHE ICON DISCARDABLE "apache.ico"
+#endif // Neutral resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.K.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""winresrc.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.K.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/usr.sbin/httpd/src/os/win32/installer/apache.iwz b/usr.sbin/httpd/src/os/win32/installer/apache.iwz
index d9e6a9d18db..6af3320c83f 100644
--- a/usr.sbin/httpd/src/os/win32/installer/apache.iwz
+++ b/usr.sbin/httpd/src/os/win32/installer/apache.iwz
@@ -4,39 +4,38 @@ iDate=1
iTime=1
Flag=fe000000
ISX.EXE Size=630784
-ISX.EXE Date=11:43:52 24/2/1998
+ISX.EXE Date=10:43:52 24/2/1998
ISX.EXE Ver=2.0.0.143
SETUP.EXE Size=45312
-SETUP.EXE Date=10:53:32 18/1/1997
+SETUP.EXE Date=9:53:32 18/1/1997
SETUP.EXE Ver=3.0.111.0
SETUP.INS Size=70160
-SETUP.INS Date=14:16:56 11/2/1998
+SETUP.INS Date=13:16:56 11/2/1998
SETUP.INS Ver=Not available
_INST16.EX_ Size=282766
-_INST16.EX_ Date=10:56:04 18/1/1997
+_INST16.EX_ Date=9:56:04 18/1/1997
_INST16.EX_ Ver=Not available
_INST32I.EX_ Size=320411
-_INST32I.EX_ Date=11:04:08 18/1/1997
+_INST32I.EX_ Date=10:04:08 18/1/1997
_INST32I.EX_ Ver=Not available
ISDEPEND.INI Size=320411
-ISDEPEND.INI Date=11:04:08 18/1/1997
+ISDEPEND.INI Date=10:04:08 18/1/1997
ISDEPEND.INI Ver=Not available
SWDEPEND.INI Size=320411
-SWDEPEND.INI Date=11:04:08 18/1/1997
+SWDEPEND.INI Date=10:04:08 18/1/1997
SWDEPEND.INI Ver=Not available
ICOMP.EXE Size=119808
-ICOMP.EXE Date=15:05:10 15/1/1996
+ICOMP.EXE Date=14:05:10 15/1/1996
ICOMP.EXE Ver=3.00.062
SPLIT.EXE Size=90624
-SPLIT.EXE Date=15:09:36 15/1/1996
+SPLIT.EXE Date=14:09:36 15/1/1996
SPLIT.EXE Ver=3.00.060
PACKLIST.EXE Size=87552
-PACKLIST.EXE Date=15:10:30 15/1/1996
+PACKLIST.EXE Date=14:10:30 15/1/1996
PACKLIST.EXE Ver=3.00.060
Version=2.02
DevTool=Generic Windows
Platform=Win32
-DisksBuilt=1
DisksDir=apache\650MB\
TabsVisit=1111001110000111100011
LangNum=451
@@ -46,9 +45,9 @@ LangDir=LANG\ENG\
AppName=Apache
AppExe=
AppExeFile=
-Version=1.3.3
+Version=1.3.7 dev
Company=Apache Group
-Title=Apache Web Server 1.3.3
+Title=Apache Web Server 1.3.7 dev
TitleType=1
BackgrndBmp=
BackgrndAlign=4
@@ -62,44 +61,44 @@ SmsMode=0
Types=3
Type1Components=6
Type1Name=Custom
-Type1ComponentList=1 2 3 4 5 6
+Type1ComponentList=1 3 4 6 5 2
Type2Components=5
Type2Name=Typical
-Type2ComponentList=1 3 4 5 6
+Type2ComponentList=1 3 4 6 5
Type3Components=2
Type3Name=Compact
Type3ComponentList=1 6
[Components]
Components=6
-Component1Groups=5
+Component1Groups=6
Component1Name=Application Files
Component1Description=Application files needed to run the application
-Component1GroupList=1 3 24 25 4
-Component2Groups=14
+Component1GroupList=1 3 24 25 4 35
+Component2Groups=17
Component2Name=Source Code
Component2Description=Source code for Apache and support tools
-Component2GroupList=10 11 12 13 14 15 16 17 18 19 20 21 22 23
-Component3Groups=5
+Component2GroupList=10 11 12 13 14 15 16 17 18 19 20 21 22 23 31 32 34
+Component3Groups=6
Component3Name=Apache Manual
Component3Description=Apache documentation
-Component3GroupList=5 6 7 8 9
+Component3GroupList=5 6 7 8 9 36
Component4Groups=1
Component4Name=Additional Modules
Component4Description=Apache modules to extend the server
Component4GroupList=2
-Component5Groups=1
+Component5Groups=2
Component5Name=Icons
Component5Description=Icons for directory indexes
-Component5GroupList=27
+Component5GroupList=27 33
Component6Groups=4
Component6Name=Required Directories
Component6Description=
Component6GroupList=26 28 29 30
[Groups]
-Groups=30
-Group1Size=328050
+Groups=36
+Group1Size=346325
Group1Files=9
Group1Name=Program Executables
Group1Dir=<INSTALLDIR>
@@ -114,7 +113,7 @@ Group1File6=C:\Apache\LICENSE
Group1File7=C:\Apache\README
Group1File8=C:\apache\Makefile.tmpl
Group1File9=C:\apache\README-NT.TXT
-Group2Size=135680
+Group2Size=133120
Group2Files=10
Group2Name=Additional Modules
Group2Dir=<INSTALLDIR>\modules
@@ -130,7 +129,7 @@ Group2File7=C:\Apache\modules\ApacheModuleSpeling.dll
Group2File8=C:\Apache\modules\ApacheModuleStatus.dll
Group2File9=C:\Apache\modules\ApacheModuleUserTrack.dll
Group2File10=C:\apache\modules\ApacheModuleRewrite.dll
-Group3Size=38714
+Group3Size=49860
Group3Files=6
Group3Name=Configuration Files
Group3Dir=<INSTALLDIR>\.tmp
@@ -150,8 +149,8 @@ Group4Update=1
Group4TargetOS=-1
Group4File1=C:\Apache\htdocs\index.html
Group4File2=C:\apache\htdocs\apache_pb.gif
-Group5Size=253396
-Group5Files=31
+Group5Size=295033
+Group5Files=34
Group5Name=Manual
Group5Dir=<INSTALLDIR>\htdocs\manual
Group5Update=0
@@ -187,6 +186,9 @@ Group5File28=C:\apache\htdocs\manual\unixware.html
Group5File29=C:\apache\htdocs\manual\upgrading_to_1_3.html
Group5File30=C:\apache\htdocs\manual\windows.html
Group5File31=C:\apache\htdocs\manual\bind.html
+Group5File32=C:\apache\htdocs\manual\suexec_1_2.html
+Group5File33=C:\apache\htdocs\manual\install-tpf.html
+Group5File34=C:\apache\htdocs\manual\readme-tpf.html
Group6Size=42478
Group6Files=8
Group6Name=images
@@ -201,7 +203,7 @@ Group6File5=C:\apache\htdocs\manual\images\mod_rewrite_fig1.fig
Group6File6=C:\apache\htdocs\manual\images\mod_rewrite_fig1.gif
Group6File7=C:\apache\htdocs\manual\images\mod_rewrite_fig2.fig
Group6File8=C:\apache\htdocs\manual\images\mod_rewrite_fig2.gif
-Group7Size=321048
+Group7Size=329371
Group7Files=22
Group7Name=misc
Group7Dir=[Manual]\misc
@@ -229,7 +231,7 @@ Group7File19=C:\Apache\htdocs\manual\misc\security_tips.html
Group7File20=C:\Apache\htdocs\manual\misc\vif-info.html
Group7File21=C:\Apache\htdocs\manual\misc\windoz_keepalive.html
Group7File22=C:\apache\htdocs\manual\misc\HTTP_Features.tsv
-Group8Size=531149
+Group8Size=558131
Group8Files=48
Group8Name=mod
Group8Dir=[Manual]\mod
@@ -283,8 +285,8 @@ Group8File45=C:\Apache\htdocs\manual\mod\mod_unique_id.html
Group8File46=C:\Apache\htdocs\manual\mod\mod_userdir.html
Group8File47=C:\Apache\htdocs\manual\mod\mod_usertrack.html
Group8File48=C:\apache\htdocs\manual\mod\mod_mmap_static.html
-Group9Size=97112
-Group9Files=12
+Group9Size=112629
+Group9Files=13
Group9Name=vhosts
Group9Dir=[Manual]\vhosts
Group9Update=0
@@ -301,8 +303,9 @@ Group9File9=C:\Apache\htdocs\manual\vhosts\ip-based.html
Group9File10=C:\Apache\htdocs\manual\vhosts\name-based.html
Group9File11=C:\Apache\htdocs\manual\vhosts\vhosts-in-depth.html
Group9File12=C:\Apache\htdocs\manual\vhosts\virtual-host.html
-Group10Size=463830
-Group10Files=17
+Group9File13=C:\apache\htdocs\manual\vhosts\mass.html
+Group10Size=523748
+Group10Files=19
Group10Name=src
Group10Dir=<INSTALLDIR>\src
Group10Update=0
@@ -324,7 +327,9 @@ Group10File14=C:\Apache\src\PORTING
Group10File15=C:\Apache\src\README
Group10File16=C:\Apache\src\README.EBCDIC
Group10File17=C:\apache\src\BUILD.NOTES
-Group11Size=68859
+Group10File18=C:\apache\src\Makefile_win32.txt
+Group10File19=C:\apache\src\Makefile_win32_debug.txt
+Group11Size=92924
Group11Files=10
Group11Name=ap
Group11Dir=[src]\ap
@@ -338,10 +343,10 @@ Group11File5=C:\Apache\src\ap\ap_signal.c
Group11File6=C:\Apache\src\ap\ap_slack.c
Group11File7=C:\Apache\src\ap\ap_snprintf.c
Group11File8=C:\Apache\src\ap\Makefile.tmpl
-Group11File9=C:\apache\src\ap\.indent.pro
-Group11File10=C:\apache\src\ap\ap_fnmatch.c
-Group12Size=246696
-Group12Files=30
+Group11File9=C:\apache\src\ap\ap_fnmatch.c
+Group11File10=C:\apache\src\ap\ap_md5c.c
+Group12Size=255397
+Group12Files=29
Group12Name=include
Group12Dir=[src]\include
Group12Update=0
@@ -374,38 +379,35 @@ Group12File25=C:\apache\src\include\util_uri.h
Group12File26=C:\apache\src\include\ap_compat.h
Group12File27=C:\apache\src\include\ap_config.h
Group12File28=C:\apache\src\include\ap_ctype.h
-Group12File29=C:\apache\src\include\.indent.pro
-Group12File30=C:\apache\src\include\ap_mmn.h
-Group13Size=771650
-Group13Files=24
+Group12File29=C:\apache\src\include\ap_mmn.h
+Group13Size=789788
+Group13Files=22
Group13Name=main
Group13Dir=[src]\main
Group13Update=0
Group13TargetOS=-1
-Group13File1=C:\apache\src\main\.indent.pro
-Group13File2=C:\apache\src\main\alloc.c
-Group13File3=C:\apache\src\main\buff.c
-Group13File4=C:\apache\src\main\gen_test_char.c
-Group13File5=C:\apache\src\main\gen_test_char.dsp
-Group13File6=C:\apache\src\main\gen_test_char.mak
-Group13File7=C:\apache\src\main\gen_uri_delims.c
-Group13File8=C:\apache\src\main\gen_uri_delims.dsp
-Group13File9=C:\apache\src\main\gen_uri_delims.mak
-Group13File10=C:\apache\src\main\http_config.c
-Group13File11=C:\apache\src\main\http_core.c
-Group13File12=C:\apache\src\main\http_log.c
-Group13File13=C:\apache\src\main\http_main.c
-Group13File14=C:\apache\src\main\http_protocol.c
-Group13File15=C:\apache\src\main\http_request.c
-Group13File16=C:\apache\src\main\http_vhost.c
-Group13File17=C:\apache\src\main\Makefile.tmpl
-Group13File18=C:\apache\src\main\md5c.c
-Group13File19=C:\apache\src\main\rfc1413.c
-Group13File20=C:\apache\src\main\util.c
-Group13File21=C:\apache\src\main\util_date.c
-Group13File22=C:\apache\src\main\util_md5.c
-Group13File23=C:\apache\src\main\util_script.c
-Group13File24=C:\apache\src\main\util_uri.c
+Group13File1=C:\apache\src\main\alloc.c
+Group13File2=C:\apache\src\main\buff.c
+Group13File3=C:\apache\src\main\gen_test_char.c
+Group13File4=C:\apache\src\main\gen_test_char.dsp
+Group13File5=C:\apache\src\main\gen_test_char.mak
+Group13File6=C:\apache\src\main\gen_uri_delims.c
+Group13File7=C:\apache\src\main\gen_uri_delims.dsp
+Group13File8=C:\apache\src\main\gen_uri_delims.mak
+Group13File9=C:\apache\src\main\http_config.c
+Group13File10=C:\apache\src\main\http_core.c
+Group13File11=C:\apache\src\main\http_log.c
+Group13File12=C:\apache\src\main\http_main.c
+Group13File13=C:\apache\src\main\http_protocol.c
+Group13File14=C:\apache\src\main\http_request.c
+Group13File15=C:\apache\src\main\http_vhost.c
+Group13File16=C:\apache\src\main\Makefile.tmpl
+Group13File17=C:\apache\src\main\rfc1413.c
+Group13File18=C:\apache\src\main\util.c
+Group13File19=C:\apache\src\main\util_date.c
+Group13File20=C:\apache\src\main\util_md5.c
+Group13File21=C:\apache\src\main\util_script.c
+Group13File22=C:\apache\src\main\util_uri.c
Group14Size=895
Group14Files=1
Group14Name=modules
@@ -413,8 +415,8 @@ Group14Dir=[src]\modules
Group14Update=0
Group14TargetOS=-1
Group14File1=C:\Apache\src\modules\README
-Group15Size=49171
-Group15Files=4
+Group15Size=48416
+Group15Files=3
Group15Name=example
Group15Dir=[modules]\example
Group15Update=0
@@ -422,86 +424,81 @@ Group15TargetOS=-1
Group15File1=C:\Apache\src\modules\example\Makefile.tmpl
Group15File2=C:\Apache\src\modules\example\mod_example.c
Group15File3=C:\Apache\src\modules\example\README
-Group15File4=C:\apache\src\modules\example\.indent.pro
-Group16Size=13944
-Group16Files=3
+Group16Size=13194
+Group16Files=2
Group16Name=experimental
Group16Dir=[modules]\experimental
Group16Update=0
Group16TargetOS=-1
Group16File1=C:\Apache\src\modules\experimental\Makefile.tmpl
Group16File2=C:\Apache\src\modules\experimental\mod_mmap_static.c
-Group16File3=C:\apache\src\modules\experimental\.indent.pro
-Group17Size=824
-Group17Files=2
+Group17Size=69
+Group17Files=1
Group17Name=extra
Group17Dir=[modules]\extra
Group17Update=0
Group17TargetOS=-1
Group17File1=C:\Apache\src\modules\extra\Makefile.tmpl
-Group17File2=C:\apache\src\modules\extra\.indent.pro
-Group18Size=205432
-Group18Files=12
+Group18Size=205708
+Group18Files=11
Group18Name=proxy
Group18Dir=[modules]\proxy
Group18Update=0
Group18TargetOS=-1
-Group18File1=C:\apache\src\modules\proxy\.indent.pro
-Group18File2=C:\apache\src\modules\proxy\ApacheModuleProxy.dsp
-Group18File3=C:\apache\src\modules\proxy\ApacheModuleProxy.mak
-Group18File4=C:\apache\src\modules\proxy\Makefile.libdir
-Group18File5=C:\apache\src\modules\proxy\Makefile.tmpl
-Group18File6=C:\apache\src\modules\proxy\mod_proxy.c
-Group18File7=C:\apache\src\modules\proxy\mod_proxy.h
-Group18File8=C:\apache\src\modules\proxy\proxy_cache.c
-Group18File9=C:\apache\src\modules\proxy\proxy_connect.c
-Group18File10=C:\apache\src\modules\proxy\proxy_ftp.c
-Group18File11=C:\apache\src\modules\proxy\proxy_http.c
-Group18File12=C:\apache\src\modules\proxy\proxy_util.c
-Group19Size=831125
-Group19Files=37
+Group18File1=C:\apache\src\modules\proxy\ApacheModuleProxy.dsp
+Group18File2=C:\apache\src\modules\proxy\ApacheModuleProxy.mak
+Group18File3=C:\apache\src\modules\proxy\Makefile.libdir
+Group18File4=C:\apache\src\modules\proxy\Makefile.tmpl
+Group18File5=C:\apache\src\modules\proxy\mod_proxy.c
+Group18File6=C:\apache\src\modules\proxy\mod_proxy.h
+Group18File7=C:\apache\src\modules\proxy\proxy_cache.c
+Group18File8=C:\apache\src\modules\proxy\proxy_connect.c
+Group18File9=C:\apache\src\modules\proxy\proxy_ftp.c
+Group18File10=C:\apache\src\modules\proxy\proxy_http.c
+Group18File11=C:\apache\src\modules\proxy\proxy_util.c
+Group19Size=863524
+Group19Files=36
Group19Name=standard
Group19Dir=[modules]\standard
Group19Update=0
Group19TargetOS=-1
-Group19File1=C:\apache\src\modules\standard\.indent.pro
-Group19File2=C:\apache\src\modules\standard\Makefile.tmpl
-Group19File3=C:\apache\src\modules\standard\mod_access.c
-Group19File4=C:\apache\src\modules\standard\mod_actions.c
-Group19File5=C:\apache\src\modules\standard\mod_alias.c
-Group19File6=C:\apache\src\modules\standard\mod_asis.c
-Group19File7=C:\apache\src\modules\standard\mod_auth.c
-Group19File8=C:\apache\src\modules\standard\mod_auth_anon.c
-Group19File9=C:\apache\src\modules\standard\mod_auth_db.c
-Group19File10=C:\apache\src\modules\standard\mod_auth_db.module
-Group19File11=C:\apache\src\modules\standard\mod_auth_dbm.c
-Group19File12=C:\apache\src\modules\standard\mod_autoindex.c
-Group19File13=C:\apache\src\modules\standard\mod_cern_meta.c
-Group19File14=C:\apache\src\modules\standard\mod_cgi.c
-Group19File15=C:\apache\src\modules\standard\mod_digest.c
-Group19File16=C:\apache\src\modules\standard\mod_dir.c
-Group19File17=C:\apache\src\modules\standard\mod_env.c
-Group19File18=C:\apache\src\modules\standard\mod_expires.c
-Group19File19=C:\apache\src\modules\standard\mod_headers.c
-Group19File20=C:\apache\src\modules\standard\mod_imap.c
-Group19File21=C:\apache\src\modules\standard\mod_include.c
-Group19File22=C:\apache\src\modules\standard\mod_info.c
-Group19File23=C:\apache\src\modules\standard\mod_log_agent.c
-Group19File24=C:\apache\src\modules\standard\mod_log_config.c
-Group19File25=C:\apache\src\modules\standard\mod_log_referer.c
-Group19File26=C:\apache\src\modules\standard\mod_mime.c
-Group19File27=C:\apache\src\modules\standard\mod_mime_magic.c
-Group19File28=C:\apache\src\modules\standard\mod_negotiation.c
-Group19File29=C:\apache\src\modules\standard\mod_rewrite.c
-Group19File30=C:\apache\src\modules\standard\mod_rewrite.h
-Group19File31=C:\apache\src\modules\standard\mod_setenvif.c
-Group19File32=C:\apache\src\modules\standard\mod_so.c
-Group19File33=C:\apache\src\modules\standard\mod_speling.c
-Group19File34=C:\apache\src\modules\standard\mod_status.c
-Group19File35=C:\apache\src\modules\standard\mod_unique_id.c
-Group19File36=C:\apache\src\modules\standard\mod_userdir.c
-Group19File37=C:\apache\src\modules\standard\mod_usertrack.c
-Group20Size=170813
+Group19File1=C:\apache\src\modules\standard\Makefile.tmpl
+Group19File2=C:\apache\src\modules\standard\mod_access.c
+Group19File3=C:\apache\src\modules\standard\mod_actions.c
+Group19File4=C:\apache\src\modules\standard\mod_alias.c
+Group19File5=C:\apache\src\modules\standard\mod_asis.c
+Group19File6=C:\apache\src\modules\standard\mod_auth.c
+Group19File7=C:\apache\src\modules\standard\mod_auth_anon.c
+Group19File8=C:\apache\src\modules\standard\mod_auth_db.c
+Group19File9=C:\apache\src\modules\standard\mod_auth_db.module
+Group19File10=C:\apache\src\modules\standard\mod_auth_dbm.c
+Group19File11=C:\apache\src\modules\standard\mod_autoindex.c
+Group19File12=C:\apache\src\modules\standard\mod_cern_meta.c
+Group19File13=C:\apache\src\modules\standard\mod_cgi.c
+Group19File14=C:\apache\src\modules\standard\mod_digest.c
+Group19File15=C:\apache\src\modules\standard\mod_dir.c
+Group19File16=C:\apache\src\modules\standard\mod_env.c
+Group19File17=C:\apache\src\modules\standard\mod_expires.c
+Group19File18=C:\apache\src\modules\standard\mod_headers.c
+Group19File19=C:\apache\src\modules\standard\mod_imap.c
+Group19File20=C:\apache\src\modules\standard\mod_include.c
+Group19File21=C:\apache\src\modules\standard\mod_info.c
+Group19File22=C:\apache\src\modules\standard\mod_log_agent.c
+Group19File23=C:\apache\src\modules\standard\mod_log_config.c
+Group19File24=C:\apache\src\modules\standard\mod_log_referer.c
+Group19File25=C:\apache\src\modules\standard\mod_mime.c
+Group19File26=C:\apache\src\modules\standard\mod_mime_magic.c
+Group19File27=C:\apache\src\modules\standard\mod_negotiation.c
+Group19File28=C:\apache\src\modules\standard\mod_rewrite.c
+Group19File29=C:\apache\src\modules\standard\mod_rewrite.h
+Group19File30=C:\apache\src\modules\standard\mod_setenvif.c
+Group19File31=C:\apache\src\modules\standard\mod_so.c
+Group19File32=C:\apache\src\modules\standard\mod_speling.c
+Group19File33=C:\apache\src\modules\standard\mod_status.c
+Group19File34=C:\apache\src\modules\standard\mod_unique_id.c
+Group19File35=C:\apache\src\modules\standard\mod_userdir.c
+Group19File36=C:\apache\src\modules\standard\mod_usertrack.c
+Group20Size=170796
Group20Files=25
Group20Name=regex
Group20Dir=[src]\regex
@@ -532,47 +529,48 @@ Group20File22=C:\Apache\src\regex\split.c
Group20File23=C:\Apache\src\regex\tests
Group20File24=C:\Apache\src\regex\utils.h
Group20File25=C:\Apache\src\regex\WHATSNEW
-Group21Size=182644
-Group21Files=27
+Group21Size=210232
+Group21Files=28
Group21Name=support
Group21Dir=[src]\support
Group21Update=0
Group21TargetOS=-1
-Group21File1=C:\apache\src\support\.indent.pro
-Group21File2=C:\apache\src\support\ab.1
-Group21File3=C:\apache\src\support\ab.c
-Group21File4=C:\apache\src\support\apachectl
-Group21File5=C:\apache\src\support\apachectl.1
-Group21File6=C:\apache\src\support\apxs.8
-Group21File7=C:\apache\src\support\apxs.pl
-Group21File8=C:\apache\src\support\dbmmanage
-Group21File9=C:\apache\src\support\dbmmanage.1
-Group21File10=C:\apache\src\support\htdigest.1
-Group21File11=C:\apache\src\support\htdigest.c
-Group21File12=C:\apache\src\support\htpasswd.1
-Group21File13=C:\apache\src\support\htpasswd.c
-Group21File14=C:\apache\src\support\httpd.8
-Group21File15=C:\apache\src\support\log_server_status
-Group21File16=C:\apache\src\support\logresolve.8
-Group21File17=C:\apache\src\support\logresolve.c
-Group21File18=C:\apache\src\support\logresolve.pl
-Group21File19=C:\apache\src\support\Makefile.tmpl
-Group21File20=C:\apache\src\support\phf_abuse_log.cgi
-Group21File21=C:\apache\src\support\rotatelogs.8
-Group21File22=C:\apache\src\support\rotatelogs.c
-Group21File23=C:\apache\src\support\split-logfile
-Group21File24=C:\apache\src\support\suexec.8
-Group21File25=C:\apache\src\support\suexec.c
-Group21File26=C:\apache\src\support\suexec.h
-Group21File27=C:\apache\src\support\httpd.exp
+Group21File1=C:\apache\src\support\ab.c
+Group21File2=C:\apache\src\support\apachectl
+Group21File3=C:\apache\src\support\apxs.8
+Group21File4=C:\apache\src\support\apxs.pl
+Group21File5=C:\apache\src\support\dbmmanage
+Group21File6=C:\apache\src\support\dbmmanage.1
+Group21File7=C:\apache\src\support\htdigest.1
+Group21File8=C:\apache\src\support\htdigest.c
+Group21File9=C:\apache\src\support\htpasswd.1
+Group21File10=C:\apache\src\support\htpasswd.c
+Group21File11=C:\apache\src\support\httpd.8
+Group21File12=C:\apache\src\support\log_server_status
+Group21File13=C:\apache\src\support\logresolve.8
+Group21File14=C:\apache\src\support\logresolve.c
+Group21File15=C:\apache\src\support\logresolve.pl
+Group21File16=C:\apache\src\support\Makefile.tmpl
+Group21File17=C:\apache\src\support\phf_abuse_log.cgi
+Group21File18=C:\apache\src\support\rotatelogs.8
+Group21File19=C:\apache\src\support\rotatelogs.c
+Group21File20=C:\apache\src\support\split-logfile
+Group21File21=C:\apache\src\support\suexec.8
+Group21File22=C:\apache\src\support\suexec.c
+Group21File23=C:\apache\src\support\suexec.h
+Group21File24=C:\apache\src\support\httpd.exp
+Group21File25=C:\apache\src\support\htpasswd.dsp
+Group21File26=C:\apache\src\support\htpasswd.mak
+Group21File27=C:\apache\src\support\ab.8
+Group21File28=C:\apache\src\support\apachectl.8
Group22Size=0
Group22Files=0
Group22Name=os
Group22Dir=[src]\os
Group22Update=0
Group22TargetOS=-1
-Group23Size=199605
-Group23Files=43
+Group23Size=210812
+Group23Files=46
Group23Name=win32
Group23Dir=[os]\win32
Group23Update=0
@@ -620,14 +618,17 @@ Group23File40=C:\apache\src\os\win32\registry.h
Group23File41=C:\apache\src\os\win32\service.c
Group23File42=C:\apache\src\os\win32\service.h
Group23File43=C:\apache\src\os\win32\util_win32.c
-Group24Size=54784
+Group23File44=C:\apache\src\os\win32\apache.ico
+Group23File45=C:\apache\src\os\win32\apache.rc
+Group23File46=C:\apache\src\os\win32\resource.h
+Group24Size=84480
Group24Files=1
Group24Name=Installer DLL
Group24Dir=<INSTALLDIR>
Group24Update=0
Group24TargetOS=-1
Group24File1=C:\Apache\install.dll
-Group25Size=280576
+Group25Size=254005
Group25Files=1
Group25Name=Shared DLLs
Group25Dir=<WINSYSDIR>
@@ -640,7 +641,7 @@ Group26Name=logs
Group26Dir=<INSTALLDIR>\logs
Group26Update=0
Group26TargetOS=-1
-Group27Size=37074
+Group27Size=37127
Group27Files=76
Group27Name=icons
Group27Dir=<INSTALLDIR>\icons
@@ -741,6 +742,91 @@ Group30Name=cgi-bin
Group30Dir=<INSTALLDIR>\cgi-bin
Group30Update=0
Group30TargetOS=-1
+Group31Size=37002
+Group31Files=2
+Group31Name=installer
+Group31Dir=[win32]\installer
+Group31Update=0
+Group31TargetOS=-1
+Group31File1=C:\apache\src\os\win32\installer\apache.iwz
+Group31File2=C:\apache\src\os\win32\installer\README.TXT
+Group32Size=30356
+Group32Files=4
+Group32Name=installdll
+Group32Dir=[installer]\installdll
+Group32Update=0
+Group32TargetOS=-1
+Group32File1=C:\apache\src\os\win32\installer\installdll\install.c
+Group32File2=C:\apache\src\os\win32\installer\installdll\install.def
+Group32File3=C:\apache\src\os\win32\installer\installdll\install.dsp
+Group32File4=C:\apache\src\os\win32\installer\installdll\install.mak
+Group33Size=8247
+Group33Files=33
+Group33Name=small
+Group33Dir=[icons]\small
+Group33Update=0
+Group33TargetOS=-1
+Group33File1=C:\apache\icons\small\back.gif
+Group33File2=C:\apache\icons\small\binary.gif
+Group33File3=C:\apache\icons\small\binhex.gif
+Group33File4=C:\apache\icons\small\blank.gif
+Group33File5=C:\apache\icons\small\broken.gif
+Group33File6=C:\apache\icons\small\burst.gif
+Group33File7=C:\apache\icons\small\comp1.gif
+Group33File8=C:\apache\icons\small\comp2.gif
+Group33File9=C:\apache\icons\small\compressed.gif
+Group33File10=C:\apache\icons\small\continued.gif
+Group33File11=C:\apache\icons\small\dir.gif
+Group33File12=C:\apache\icons\small\dir2.gif
+Group33File13=C:\apache\icons\small\forward.gif
+Group33File14=C:\apache\icons\small\generic.gif
+Group33File15=C:\apache\icons\small\generic2.gif
+Group33File16=C:\apache\icons\small\generic3.gif
+Group33File17=C:\apache\icons\small\image.gif
+Group33File18=C:\apache\icons\small\image2.gif
+Group33File19=C:\apache\icons\small\index.gif
+Group33File20=C:\apache\icons\small\movie.gif
+Group33File21=C:\apache\icons\small\rainbow.gif
+Group33File22=C:\apache\icons\small\README.txt
+Group33File23=C:\apache\icons\small\sound.gif
+Group33File24=C:\apache\icons\small\sound2.gif
+Group33File25=C:\apache\icons\small\tar.gif
+Group33File26=C:\apache\icons\small\text.gif
+Group33File27=C:\apache\icons\small\transfer.gif
+Group33File28=C:\apache\icons\small\unknown.gif
+Group33File29=C:\apache\icons\small\uu.gif
+Group33File30=C:\apache\icons\small\key.gif
+Group33File31=C:\apache\icons\small\patch.gif
+Group33File32=C:\apache\icons\small\ps.gif
+Group33File33=C:\apache\icons\small\doc.gif
+Group34Size=21478
+Group34Files=8
+Group34Name=test
+Group34Dir=[installdll]\test
+Group34Update=0
+Group34TargetOS=-1
+Group34File1=C:\apache\src\os\win32\installer\installdll\test\resource.h
+Group34File2=C:\apache\src\os\win32\installer\installdll\test\test.c
+Group34File3=C:\apache\src\os\win32\installer\installdll\test\test.def
+Group34File4=C:\apache\src\os\win32\installer\installdll\test\test.dsp
+Group34File5=C:\apache\src\os\win32\installer\installdll\test\test.h
+Group34File6=C:\apache\src\os\win32\installer\installdll\test\test.ico
+Group34File7=C:\apache\src\os\win32\installer\installdll\test\test.mak
+Group34File8=C:\apache\src\os\win32\installer\installdll\test\test.rc
+Group35Size=58368
+Group35Files=1
+Group35Name=bin
+Group35Dir=<INSTALLDIR>\bin
+Group35Update=0
+Group35TargetOS=-1
+Group35File1=C:\apache\bin\htpasswd.exe
+Group36Size=7223
+Group36Files=1
+Group36Name=search
+Group36Dir=[manual]\search
+Group36Update=0
+Group36TargetOS=-1
+Group36File1=C:\apache\htdocs\manual\search\manual-index.cgi
[Sequence]
DestinationLocationDir=<ProgramFilesDir>\Apache Group\Apache
@@ -805,7 +891,7 @@ Reg9Val1Type=0
Reg9Val1Name=(Default)
Reg9Val1Data=(value not set)
Reg9Vals=1
-Reg10Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3.3
+Reg10Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3.7 dev
Reg10Val1Type=0
Reg10Val1Name=(Default)
Reg10Val1Data=(value not set)
@@ -819,20 +905,20 @@ Regs=10
Reg1Path=HKEY_LOCAL_MACHINE\SOFTWARE
Reg2Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group
Reg3Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache
-Reg4Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3.3
-Reg5Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3.3
+Reg4Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3.7 dev
+Reg5Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3.7 dev
Reg5ValName=ServerRoot
Reg5ValType=0
Reg5ValData=<INSTALLDIR>
Regs=5
[Icons]
-Icons=3
-Icon1Param=-d "<INSTALLDIR>"
+Icons=5
+Icon1Param=-d "<INSTALLDIR>" -s
Icon1Cmd=[Program Executables]\Apache.exe
-Icon1Description=Apache Server
+Icon1Description=Start Apache as console app
Icon1WorkingDir=[Program Executables]
-Icon1IconFile=
+Icon1IconFile=[Program Executables]\Apache.exe
Icon1RealFile=C:\Apache\Apache.exe
Icon1WhichIcon=0
Icon1KeyVirtual=0
@@ -861,12 +947,34 @@ Icon3KeyVirtual=0
Icon3KeyFlags=0
Icon3StartMenu=0
Icon3Window=0
+Icon4Param=-d "<INSTALLDIR>" -u
+Icon4Cmd=[Program Executables]\Apache.exe
+Icon4Description=Uninstall Apache Service (NT only)
+Icon4WorkingDir=[Program Executables]
+Icon4IconFile=
+Icon4RealFile=C:\Apache\Apache.exe
+Icon4WhichIcon=0
+Icon4KeyVirtual=0
+Icon4KeyFlags=0
+Icon4StartMenu=0
+Icon4Window=0
+Icon5Param=-d "<INSTALLDIR>" -k shutdown
+Icon5Cmd=[Program Executables]\Apache.exe
+Icon5Description=Shutdown Apache console app
+Icon5WorkingDir=[Program Executables]
+Icon5IconFile=
+Icon5RealFile=C:\Apache\Apache.exe
+Icon5WhichIcon=0
+Icon5KeyVirtual=0
+Icon5KeyFlags=0
+Icon5StartMenu=0
+Icon5Window=0
[VisualBasic]
PRJFile=
[Ext]
-Ext1Dlg=Exit Install
+Ext1Dlg=Setup Complete
Ext1Param1=[Installer DLL]\install.dll
Ext1Param2=BeforeExit
Ext1Op=DLL
diff --git a/usr.sbin/httpd/src/os/win32/installer/installdll/install.c b/usr.sbin/httpd/src/os/win32/installer/installdll/install.c
index f6f775ec945..39da17a104d 100644
--- a/usr.sbin/httpd/src/os/win32/installer/installdll/install.c
+++ b/usr.sbin/httpd/src/os/win32/installer/installdll/install.c
@@ -4,17 +4,65 @@
* 26/06/97 PCS 1.000 Initial version
* 22/02/98 PCS 1.001 Used the excellent NTemacs to apply proper formating
* 04/05/98 PCS 1.002 Copy conf files to *.conf.default, then to *.conf
+ * 16/02/99 PCS 1.003 Add logging to "install.log" in the installed directory
*/
-#include <windows.h>
-#include <winsock.h>
+#define VERSION ( "1.003 " __DATE__ " " __TIME__ )
+
+#include <winsock2.h>
#include <string.h>
#include <stdio.h>
#include <direct.h>
+#include <time.h>
+
+#include "conf.h"
+#include "ap.h"
+
+#ifdef strftime
+#undef strftime
+#endif
+
+#define AP_WIN32ERROR 1
/* Global to store the instance handle */
HINSTANCE hInstance = NULL;
+static char *szLogFilename = NULL;
+static FILE *fpLog = NULL;
+
+void LogMessage(char *fmt, ...)
+{
+ char buf[4000];
+ va_list ap;
+ struct tm *tms;
+ time_t nowtime;
+ char *bp = buf;
+ int rv;
+ int free = sizeof(buf);
+
+ if (!fpLog) {
+ return;
+ }
+
+ nowtime = time(NULL);
+ tms = localtime(&nowtime);
+ rv = strftime(bp, free, "%c", tms);
+ bp += rv;
+ free -= rv;
+ if (free) {
+ *bp++ = ' ';
+ free--;
+ }
+
+ va_start(ap, fmt);
+ rv = ap_vsnprintf(bp, free, fmt, ap);
+ va_end(ap);
+
+ free -= rv;
+
+ fprintf(fpLog, "%s\n", buf);
+}
+
/*
* MessageBox_error() is a helper function to display an error in a
* message box, optionally including a Win32 error message. If
@@ -23,45 +71,104 @@ HINSTANCE hInstance = NULL;
* the output string. The output string is given as a printf-format
* and replacement arguments. The hWnd, title and mb_opt fields are
* passed on to the Win32 MessageBox() call.
- *
- * We shouldn't use a fixed length buffer to build up the printf
- * text. Umm.
*/
-#define AP_WIN32ERROR 1
-
int MessageBox_error(HWND hWnd, int opt, char *title,
int mb_opt, char *fmt, ...)
{
- char buf[4000];
+ char buf[1000];
va_list ap;
+ int free = sizeof(buf); /* Number of bytes free in the buffer */
+ int rv;
+ char *p;
va_start(ap, fmt);
- wvsprintf(buf, fmt, ap);
+ rv = ap_vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
- if (opt & AP_WIN32ERROR) {
- char *p;
-
- strcat(buf, "\r\r(");
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- GetLastError(),
- 0,
- buf + strlen(buf),
- 4000 - strlen(buf),
- NULL);
- p = buf+strlen(buf)-1;
- while (*p == '\r' || *p == '\n')
- p--;
- p++;
- *p = '\0';
- strcat(buf, ")");
+ free -= rv;
+
+ if (opt & AP_WIN32ERROR && free > 3) {
+ /* We checked in the "if" that we have enough space in buf for
+ * at least three extra characters.
+ */
+ p = buf + strlen(buf);
+ *p++ = '\r';
+ *p++ = '\r';
+ *p++ = '(';
+ free -= 3;
+ /* NB: buf is now not null terminated */
+
+ /* Now put the error message straight into buf. This function
+ * takes the free buffer size as the 6th argument.
+ */
+ rv = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ GetLastError(),
+ 0,
+ p,
+ free,
+ NULL);
+
+ if (rv == 0) {
+ /* FormatMessage failed, so get rid of the "\r\r(" we just placed
+ * in the buffer, since there is no system error message.
+ */
+ p -= 3;
+ *p = '\0';
+ free += 3;
+ } else {
+ free -= rv;
+ p += rv;
+
+ /* Strip any trailing \r or \n characters to make it look nice on
+ * the screen.
+ */
+ while (*(p-1) == '\r' || *(p-1) == '\n')
+ p--, free++;
+ *p = '\0';
+
+ /* Append a trailing ) */
+ if (free >= 1) {
+ *p++ = ')';
+ *p++ = '\0';
+ }
+ }
+ }
+
+ for (p = buf; *p; p++) {
+ if (*p == '\n' || *p == '\r') {
+ *p = ' ';
+ }
}
+ LogMessage("MSG %s", buf);
return MessageBox(hWnd, buf, title, mb_opt);
}
+int OpenLog(HWND hwnd, char *dir, char *fn)
+{
+ szLogFilename = malloc(strlen(dir) + 1 + strlen(fn) + 1);
+ sprintf(szLogFilename, "%s\\%s", dir, fn);
+
+ if ((fpLog = fopen(szLogFilename, "a+")) == NULL) {
+ MessageBox_error(hwnd,
+ AP_WIN32ERROR,
+ "Installation Problem",
+ MB_OK | MB_ICONSTOP,
+ "Cannot open log file %s", szLogFilename);
+ return -1;
+ }
+ return 0;
+}
+
+void CloseLog(void)
+{
+ if (fpLog) {
+ fclose(fpLog);
+ }
+}
+
/*
* The next few functions handle expanding the @@ServerRoot@@ type
* sequences found in the distribution files. The main entry point
@@ -262,8 +369,8 @@ int WINAPI ExpandConfFile(HWND hwnd, LPSTR szInst, LPSTR szinFile, LPSTR szoutFi
FILE *infp;
FILE *outfp;
- sprintf(inFile, "%s\\%s", szInst, szinFile);
- sprintf(outFile, "%s\\%s", szInst, szoutFile);
+ ap_snprintf(inFile, sizeof(inFile), "%s\\%s", szInst, szinFile);
+ ap_snprintf(outFile, sizeof(outFile), "%s\\%s", szInst, szoutFile);
if (!(infp = fopen(inFile, "r"))) {
MessageBox_error(hwnd,
@@ -348,8 +455,11 @@ int WINAPI ExpandConfFile(HWND hwnd, LPSTR szInst, LPSTR szinFile, LPSTR szoutFi
fclose(infp);
fclose(outfp);
+ LogMessage("COPY: expanded %s to %s", inFile, outFile);
+
if (options & OPT_DELETESOURCE) {
unlink(inFile);
+ LogMessage("COPY: deleted file %s", inFile);
}
return 0;
@@ -375,6 +485,9 @@ int FillInReplaceTable(HWND hwnd, REPLACETABLE table, char *szInst)
#endif
for (p = item->value; *p; p++)
if (*p == '\\') *p = '/';
+
+ LogMessage("FillInReplaceTable tmpl=%s value=%s", item->tmpl, item->value);
+
continue;
}
#if NEED_FQDN
@@ -452,14 +565,6 @@ ACTIONITEM actionTable[] = {
{ CMD_COPY, ".tmp\\highperformance.conf-dist", "conf\\highperformance.conf-dist",
OPT_EXPAND|OPT_OVERWRITE|OPT_DELETESOURCE },
- /* Move the default htdocs files into place, provided they don't already
- * exist.
- */
- { CMD_COPY, ".tmp\\index.html", "htdocs\\index.html", OPT_DELETESOURCE|OPT_SILENT },
- { CMD_RM, ".tmp\\index.html", NULL, OPT_SILENT },
- { CMD_COPY, ".tmp\\apache_pb.gif", "htdocs\\apache_pb.gif", OPT_DELETESOURCE|OPT_SILENT },
- { CMD_RM, ".tmp\\apache_pb.gif", NULL, OPT_SILENT },
-
{ CMD_RMDIR, ".tmp", NULL },
{ CMD_END, NULL, NULL, OPT_NONE }
@@ -477,10 +582,22 @@ CHAR WINAPI BeforeExit(HWND hwnd, LPSTR szSrcDir, LPSTR szSupport, LPSTR szInst,
ACTIONITEM *pactionItem;
int end = 0;
+ OpenLog(hwnd, szInst, "install.log");
+ LogMessage("STARTED %s", VERSION);
+ LogMessage("src=%s support=%s inst=%s",
+ szSrcDir, szSupport, szInst);
+
FillInReplaceTable(hwnd, replaceHttpd, szInst);
pactionItem = actionTable;
while (!end) {
+
+ LogMessage("command=%d 1in=%s out=%s options=%d",
+ pactionItem->command,
+ pactionItem->in ? pactionItem->in : "NULL",
+ pactionItem->out ? pactionItem->out : "NULL",
+ pactionItem->options);
+
switch(pactionItem->command) {
case CMD_END:
end = 1;
@@ -498,7 +615,7 @@ CHAR WINAPI BeforeExit(HWND hwnd, LPSTR szSrcDir, LPSTR szSupport, LPSTR szInst,
case CMD_RM: {
char inFile[MAX_INPUT_LINE];
- sprintf(inFile, "%s\\%s", szInst, pactionItem->in);
+ ap_snprintf(inFile, sizeof(inFile), "%s\\%s", szInst, pactionItem->in);
if (unlink(inFile) < 0 && !(pactionItem->options & OPT_SILENT)) {
MessageBox_error(hwnd, AP_WIN32ERROR, "Error during configuration",
MB_ICONHAND,
@@ -506,12 +623,13 @@ CHAR WINAPI BeforeExit(HWND hwnd, LPSTR szSrcDir, LPSTR szSupport, LPSTR szInst,
inFile);
return 0;
}
+ LogMessage("RM: deleted file %s", inFile);
break;
}
case CMD_RMDIR: {
char inFile[MAX_INPUT_LINE];
- sprintf(inFile, "%s\\%s", szInst, pactionItem->in);
+ ap_snprintf(inFile, sizeof(inFile), "%s\\%s", szInst, pactionItem->in);
if (rmdir(inFile) < 0) {
MessageBox_error(hwnd, AP_WIN32ERROR, "Error during configuration",
MB_ICONHAND,
@@ -519,6 +637,7 @@ CHAR WINAPI BeforeExit(HWND hwnd, LPSTR szSrcDir, LPSTR szSupport, LPSTR szInst,
inFile);
return 0;
}
+ LogMessage("RMDIR: deleted directory %s", inFile);
break;
}
default:
@@ -531,6 +650,10 @@ CHAR WINAPI BeforeExit(HWND hwnd, LPSTR szSrcDir, LPSTR szSupport, LPSTR szInst,
}
pactionItem++;
}
+
+ LogMessage("FINISHED OK");
+ CloseLog();
+
return 1;
}
diff --git a/usr.sbin/httpd/src/os/win32/installer/installdll/install.dsp b/usr.sbin/httpd/src/os/win32/installer/installdll/install.dsp
index 26ea521ab69..9c33d71a788 100644
--- a/usr.sbin/httpd/src/os/win32/installer/installdll/install.dsp
+++ b/usr.sbin/httpd/src/os/win32/installer/installdll/install.dsp
@@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
@@ -69,7 +69,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "../../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
@@ -92,6 +92,10 @@ LINK32=link.exe
# PROP Default_Filter ""
# Begin Source File
+SOURCE=..\..\..\..\ap\ap_snprintf.c
+# End Source File
+# Begin Source File
+
SOURCE=.\install.c
# End Source File
# Begin Source File
diff --git a/usr.sbin/httpd/src/os/win32/installer/installdll/install.mak b/usr.sbin/httpd/src/os/win32/installer/installdll/install.mak
index db4ad3a82d9..65d7608ba54 100644
--- a/usr.sbin/httpd/src/os/win32/installer/installdll/install.mak
+++ b/usr.sbin/httpd/src/os/win32/installer/installdll/install.mak
@@ -27,10 +27,6 @@ NULL=
NULL=nul
!ENDIF
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
!IF "$(CFG)" == "install - Win32 Release"
OUTDIR=.\Release
@@ -50,6 +46,7 @@ ALL : "$(OUTDIR)\install.dll"
!ENDIF
CLEAN :
+ -@erase "$(INTDIR)\ap_snprintf.obj"
-@erase "$(INTDIR)\install.obj"
-@erase "$(INTDIR)\vc50.idb"
-@erase "$(OUTDIR)\install.dll"
@@ -59,11 +56,46 @@ CLEAN :
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
- /Fp"$(INTDIR)\install.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+CPP=cl.exe
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "../../../../include" /D "WIN32" /D\
+ "NDEBUG" /D "_WINDOWS" /Fp"$(INTDIR)\install.pch" /YX /Fo"$(INTDIR)\\"\
+ /Fd"$(INTDIR)\\" /FD /c
CPP_OBJS=.\Release/
CPP_SBRS=.
+
+.c{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+RSC=rc.exe
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\install.bsc"
BSC32_SBRS= \
@@ -76,6 +108,7 @@ LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
DEF_FILE= \
".\install.def"
LINK32_OBJS= \
+ "$(INTDIR)\ap_snprintf.obj" \
"$(INTDIR)\install.obj"
"$(OUTDIR)\install.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
@@ -102,6 +135,7 @@ ALL : "$(OUTDIR)\install.dll"
!ENDIF
CLEAN :
+ -@erase "$(INTDIR)\ap_snprintf.obj"
-@erase "$(INTDIR)\install.obj"
-@erase "$(INTDIR)\vc50.idb"
-@erase "$(INTDIR)\vc50.pdb"
@@ -114,32 +148,12 @@ CLEAN :
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\
- /Fp"$(INTDIR)\install.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+CPP=cl.exe
+CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /I "../../../../include" /D "WIN32"\
+ /D "_DEBUG" /D "_WINDOWS" /Fp"$(INTDIR)\install.pch" /YX /Fo"$(INTDIR)\\"\
+ /Fd"$(INTDIR)\\" /FD /c
CPP_OBJS=.\Debug/
CPP_SBRS=.
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\install.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
- advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll\
- /incremental:yes /pdb:"$(OUTDIR)\install.pdb" /debug /machine:I386\
- /def:".\install.def" /out:"$(OUTDIR)\install.dll"\
- /implib:"$(OUTDIR)\install.lib" /pdbtype:sept
-DEF_FILE= \
- ".\install.def"
-LINK32_OBJS= \
- "$(INTDIR)\install.obj"
-
-"$(OUTDIR)\install.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
.c{$(CPP_OBJS)}.obj::
$(CPP) @<<
@@ -171,13 +185,112 @@ LINK32_OBJS= \
$(CPP_PROJ) $<
<<
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\install.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll\
+ /incremental:yes /pdb:"$(OUTDIR)\install.pdb" /debug /machine:I386\
+ /def:".\install.def" /out:"$(OUTDIR)\install.dll"\
+ /implib:"$(OUTDIR)\install.lib" /pdbtype:sept
+DEF_FILE= \
+ ".\install.def"
+LINK32_OBJS= \
+ "$(INTDIR)\ap_snprintf.obj" \
+ "$(INTDIR)\install.obj"
+
+"$(OUTDIR)\install.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
!IF "$(CFG)" == "install - Win32 Release" || "$(CFG)" ==\
"install - Win32 Debug"
+SOURCE=..\..\..\..\ap\ap_snprintf.c
+
+!IF "$(CFG)" == "install - Win32 Release"
+
+DEP_CPP_AP_SN=\
+ "..\..\..\..\include\alloc.h"\
+ "..\..\..\..\include\ap.h"\
+ "..\..\..\..\include\ap_config.h"\
+ "..\..\..\..\include\ap_ctype.h"\
+ "..\..\..\..\include\ap_mmn.h"\
+ "..\..\..\..\include\buff.h"\
+ "..\..\..\..\include\hsregex.h"\
+ "..\..\..\..\include\httpd.h"\
+ "..\..\..\..\include\util_uri.h"\
+ "..\..\os.h"\
+ "..\..\readdir.h"\
+
+
+"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) $(DEP_CPP_AP_SN) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "install - Win32 Debug"
+
+DEP_CPP_AP_SN=\
+ "..\..\..\..\include\alloc.h"\
+ "..\..\..\..\include\ap.h"\
+ "..\..\..\..\include\ap_config.h"\
+ "..\..\..\..\include\ap_ctype.h"\
+ "..\..\..\..\include\ap_mmn.h"\
+ "..\..\..\..\include\buff.h"\
+ "..\..\..\..\include\hsregex.h"\
+ "..\..\..\..\include\httpd.h"\
+ "..\..\..\..\include\util_uri.h"\
+ "..\..\os.h"\
+ "..\..\readdir.h"\
+
+
+"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) $(DEP_CPP_AP_SN) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
SOURCE=.\install.c
-"$(INTDIR)\install.obj" : $(SOURCE) "$(INTDIR)"
+!IF "$(CFG)" == "install - Win32 Release"
+
+DEP_CPP_INSTA=\
+ "..\..\..\..\include\ap.h"\
+ "..\..\..\..\include\ap_config.h"\
+ "..\..\..\..\include\ap_ctype.h"\
+ "..\..\..\..\include\ap_mmn.h"\
+ "..\..\..\..\include\conf.h"\
+ "..\..\..\..\include\hsregex.h"\
+ "..\..\os.h"\
+
+
+"$(INTDIR)\install.obj" : $(SOURCE) $(DEP_CPP_INSTA) "$(INTDIR)"
+
+!ELSEIF "$(CFG)" == "install - Win32 Debug"
+
+DEP_CPP_INSTA=\
+ "..\..\..\..\include\ap.h"\
+ "..\..\..\..\include\ap_config.h"\
+ "..\..\..\..\include\ap_ctype.h"\
+ "..\..\..\..\include\ap_mmn.h"\
+ "..\..\..\..\include\conf.h"\
+ "..\..\..\..\include\hsregex.h"\
+ "..\..\os.h"\
+
+
+"$(INTDIR)\install.obj" : $(SOURCE) $(DEP_CPP_INSTA) "$(INTDIR)"
+
+
+!ENDIF
!ENDIF
diff --git a/usr.sbin/httpd/src/os/win32/installer/installdll/test/resource.h b/usr.sbin/httpd/src/os/win32/installer/installdll/test/resource.h
index 2b47ca12b5c..6d1f9d8b4e5 100644
--- a/usr.sbin/httpd/src/os/win32/installer/installdll/test/resource.h
+++ b/usr.sbin/httpd/src/os/win32/installer/installdll/test/resource.h
@@ -4,20 +4,23 @@
//
#define IDM_TEST 102
#define IDI_TEST 106
+#define IDM_EXIT 106
#define IDD_ABOUT 107
+#define IDD_SETDIRECTORY 109
+#define IDM_ABOUT 303
+#define IDC_DIRECTORY 1000
#define IDM_BEFOREEXIT 40001
-#define IDM_EXIT 106
-#define IDM_ABOUT 303
-#define IDC_STATIC -1
+#define IDM_CONFIGURE 40001
+#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
-#define _APS_NEXT_RESOURCE_VALUE 109
+#define _APS_NEXT_RESOURCE_VALUE 110
#define _APS_NEXT_COMMAND_VALUE 40002
-#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/usr.sbin/httpd/src/os/win32/installer/installdll/test/test.c b/usr.sbin/httpd/src/os/win32/installer/installdll/test/test.c
index c2b5ed43668..8a595094ba5 100644
--- a/usr.sbin/httpd/src/os/win32/installer/installdll/test/test.c
+++ b/usr.sbin/httpd/src/os/win32/installer/installdll/test/test.c
@@ -3,6 +3,7 @@
*/
#include <windows.h>
+#include <direct.h>
#include "test.h"
@@ -12,12 +13,17 @@ HINSTANCE hInst; // current instance
char szAppName[100]; // Name of the app
char szTitle[100]; // The title bar text
+// This is imported from the Apache INSTALL.DLL
extern CHAR WINAPI BeforeExit(HWND, LPSTR,LPSTR,LPSTR,LPSTR);
BOOL InitApplication(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);
+BOOL CenterWindow (HWND hwndChild, HWND hwndParent);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK SetDirectory(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
+
+char szInstDir[MAX_PATH];
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
@@ -30,6 +36,8 @@ int APIENTRY WinMain(HINSTANCE hInstance,
lstrcpy (szAppName, APPNAME);
lstrcpy (szTitle, APPNAME);
+ getcwd(szInstDir, sizeof(szInstDir));
+
if (!hPrevInstance) {
if (!InitApplication(hInstance)) {
return (FALSE);
@@ -82,8 +90,14 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
hInst = hInstance;
hWnd = CreateWindow(szAppName, szTitle, WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
- NULL, NULL, hInstance, NULL);
+ CW_USEDEFAULT, // x
+ 0, // y
+ 400, // width
+ 100, // height
+ NULL, // parent
+ NULL, // menu
+ hInstance, // instance handle
+ NULL);
if (!hWnd) {
return (FALSE);
@@ -111,10 +125,20 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)About);
break;
- case IDM_BEFOREEXIT:
- BeforeExit(hWnd, "C:\\", "C:\\", "C:\\Apache", NULL);
+ case IDM_CONFIGURE:
+ {
+ int rc;
+
+ if (DialogBox(hInst, MAKEINTRESOURCE(IDD_SETDIRECTORY), hWnd, (DLGPROC)SetDirectory) == FALSE)
+ break;
+ rc = BeforeExit(hWnd, szInstDir, szInstDir, szInstDir, NULL);
+ if (rc == 1) {
+ MessageBox(hWnd, "Configuration successful",
+ "Configuration successful",
+ MB_OK);
+ }
break;
-
+ }
case IDM_EXIT:
DestroyWindow (hWnd);
break;
@@ -139,6 +163,7 @@ LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
switch (message) {
case WM_INITDIALOG:
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
return (TRUE);
case WM_COMMAND:
@@ -152,3 +177,93 @@ LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
return FALSE;
}
+LRESULT CALLBACK SetDirectory(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+
+ switch (message) {
+ case WM_INITDIALOG:
+ CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+ SetDlgItemText(hDlg, IDC_DIRECTORY, szInstDir);
+ //SetFocus(GetDlgItem(hDlg, IDC_DIRECTORY));
+ return (TRUE);
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDCANCEL:
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+ case IDOK:
+ GetDlgItemText(hDlg, IDC_DIRECTORY, szInstDir, sizeof(szInstDir));
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+//
+// FUNCTION: CenterWindow(HWND, HWND)
+//
+// PURPOSE: Centers one window over another.
+//
+// COMMENTS:
+//
+// In this function, we save the instance handle in a global variable and
+// create and display the main program window.
+//
+// This functionwill center one window over another ensuring that
+// the placement of the window is within the 'working area', meaning
+// that it is both within the display limits of the screen, and not
+// obscured by the tray or other framing elements of the desktop.
+BOOL CenterWindow (HWND hwndChild, HWND hwndParent)
+{
+ RECT rChild, rParent, rWorkArea;
+ int wChild, hChild, wParent, hParent;
+ int xNew, yNew;
+ BOOL bResult;
+
+ // Get the Height and Width of the child window
+ GetWindowRect (hwndChild, &rChild);
+ wChild = rChild.right - rChild.left;
+ hChild = rChild.bottom - rChild.top;
+
+ // Get the Height and Width of the parent window
+ GetWindowRect (hwndParent, &rParent);
+ wParent = rParent.right - rParent.left;
+ hParent = rParent.bottom - rParent.top;
+
+ // Get the limits of the 'workarea'
+ bResult = SystemParametersInfo(
+ SPI_GETWORKAREA, // system parameter to query or set
+ sizeof(RECT),
+ &rWorkArea,
+ 0);
+ if (!bResult) {
+ rWorkArea.left = rWorkArea.top = 0;
+ rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
+ rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
+ }
+
+ // Calculate new X position, then adjust for workarea
+ xNew = rParent.left + ((wParent - wChild) /2);
+ if (xNew < rWorkArea.left) {
+ xNew = rWorkArea.left;
+ } else if ((xNew+wChild) > rWorkArea.right) {
+ xNew = rWorkArea.right - wChild;
+ }
+
+ // Calculate new Y position, then adjust for workarea
+ yNew = rParent.top + ((hParent - hChild) /2);
+ if (yNew < rWorkArea.top) {
+ yNew = rWorkArea.top;
+ } else if ((yNew+hChild) > rWorkArea.bottom) {
+ yNew = rWorkArea.bottom - hChild;
+ }
+
+ // Set it, and return
+ return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+}
+
diff --git a/usr.sbin/httpd/src/os/win32/installer/installdll/test/test.mak b/usr.sbin/httpd/src/os/win32/installer/installdll/test/test.mak
index 7f875d2bf40..6dcad364beb 100644
--- a/usr.sbin/httpd/src/os/win32/installer/installdll/test/test.mak
+++ b/usr.sbin/httpd/src/os/win32/installer/installdll/test/test.mak
@@ -207,15 +207,6 @@ LINK32_OBJS= \
!IF "$(CFG)" == "test - Win32 Release" || "$(CFG)" == "test - Win32 Debug"
SOURCE=.\test.c
-
-!IF "$(CFG)" == "test - Win32 Release"
-
-
-"$(INTDIR)\test.obj" : $(SOURCE) "$(INTDIR)"
-
-
-!ELSEIF "$(CFG)" == "test - Win32 Debug"
-
DEP_CPP_TEST_=\
".\test.h"\
@@ -223,8 +214,6 @@ DEP_CPP_TEST_=\
"$(INTDIR)\test.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
-!ENDIF
-
SOURCE=.\test.rc
DEP_RSC_TEST_R=\
".\test.h"\
diff --git a/usr.sbin/httpd/src/os/win32/installer/installdll/test/test.rc b/usr.sbin/httpd/src/os/win32/installer/installdll/test/test.rc
index 6f5a94712ee..45ef47efb94 100644
--- a/usr.sbin/httpd/src/os/win32/installer/installdll/test/test.rc
+++ b/usr.sbin/httpd/src/os/win32/installer/installdll/test/test.rc
@@ -41,14 +41,11 @@ IDI_TEST ICON DISCARDABLE "test.ico"
IDM_TEST MENU DISCARDABLE
BEGIN
- POPUP "&File"
+ POPUP "&Configure"
BEGIN
+ MENUITEM "&Configure", IDM_CONFIGURE
MENUITEM "E&xit", IDM_EXIT
END
- POPUP "&Test"
- BEGIN
- MENUITEM "Call &BeforeExit", IDM_BEFOREEXIT
- END
POPUP "&Help"
BEGIN
MENUITEM "&About", IDM_ABOUT
@@ -91,14 +88,27 @@ END
// Dialog
//
-IDD_ABOUT DIALOG DISCARDABLE 0, 0, 186, 47
+IDD_ABOUT DIALOG DISCARDABLE 0, 0, 186, 62
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Sans Serif"
BEGIN
- DEFPUSHBUTTON "OK",IDOK,129,26,50,14
- LTEXT "Apache Install DLL Tester",IDC_STATIC,7,7,172,14,NOT
- WS_GROUP
+ DEFPUSHBUTTON "OK",IDOK,129,41,50,14
+ LTEXT "Apache post-install configuration tester",IDC_STATIC,7,
+ 7,172,10,NOT WS_GROUP
+ LTEXT "Copyright 1999 The Apache Group",IDC_STATIC,7,21,172,9
+END
+
+IDD_SETDIRECTORY DIALOG DISCARDABLE 0, 0, 186, 63
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Configure Apache"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,39,42,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,95,42,50,14
+ LTEXT "Directory where Apache was installled",IDC_STATIC,7,7,
+ 164,11
+ EDITTEXT IDC_DIRECTORY,7,22,172,12,ES_AUTOHSCROLL
END
@@ -115,7 +125,15 @@ BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
- BOTTOMMARGIN, 40
+ BOTTOMMARGIN, 55
+ END
+
+ IDD_SETDIRECTORY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 56
END
END
#endif // APSTUDIO_INVOKED
diff --git a/usr.sbin/httpd/src/os/win32/os.h b/usr.sbin/httpd/src/os/win32/os.h
index da4dd739050..80ffd7e65e3 100644
--- a/usr.sbin/httpd/src/os/win32/os.h
+++ b/usr.sbin/httpd/src/os/win32/os.h
@@ -18,7 +18,7 @@
#include <direct.h>
#define STATUS
-#define WIN32_LEAN_AND_MEAN
+/*#define WIN32_LEAN_AND_MEAN Now defined in project files */
#ifndef STRICT
#define STRICT
#endif
@@ -34,6 +34,7 @@
#define USE_MMAP_SCOREBOARD
#define MULTITHREAD
#define HAVE_CANONICAL_FILENAME
+#define HAVE_DRIVE_LETTERS
typedef int uid_t;
typedef int gid_t;
typedef int pid_t;
@@ -119,4 +120,7 @@ API_EXPORT(int) ap_os_is_filename_valid(const char *file);
#define ap_os_dso_sym(h,s) GetProcAddress(h,s)
#define ap_os_dso_error() "" /* for now */
+/* Other ap_os_ routines not used by this platform */
+#define ap_os_kill(pid, sig) kill(pid, sig)
+
#endif /* ! APACHE_OS_H */
diff --git a/usr.sbin/httpd/src/os/win32/registry.c b/usr.sbin/httpd/src/os/win32/registry.c
index 0e54ca89811..23eeb5e4495 100644
--- a/usr.sbin/httpd/src/os/win32/registry.c
+++ b/usr.sbin/httpd/src/os/win32/registry.c
@@ -15,6 +15,16 @@
* release to a development or beta version.
*/
+/* To allow for multiple services, store the configuration file's full path
+ * under each service entry:
+ *
+ * HKLM\System\CurrentControlSet\Services\[service name]\Parameters\ConfPath
+ *
+ * The default configuration path (for console apache) is still stored:
+ *
+ * HKLM\Software\[Vendor]\[Software]\[Version]\ServerRoot
+ */
+
#include <windows.h>
#include <stdio.h>
@@ -28,10 +38,13 @@
#define VENDOR "Apache Group"
#define SOFTWARE "Apache"
-#define VERSION "1.3.4"
+#define VERSION "1.3.9"
#define REGKEY "SOFTWARE\\" VENDOR "\\" SOFTWARE "\\" VERSION
+#define SERVICEKEYPRE "System\\CurrentControlSet\\Services\\"
+#define SERVICEKEYPOST "\\Parameters"
+
/*
* The Windows API registry key functions don't set the last error
* value (the windows equivalent of errno). So we need to set it
@@ -79,7 +92,7 @@
* message will be logged at priority "warning".
*/
-static int ap_registry_get_key_int(pool *p, char *key, char *pBuffer, int nSizeBuffer, char **ppValue)
+static int ap_registry_get_key_int(pool *p, char *key, char *name, char *pBuffer, int nSizeBuffer, char **ppValue)
{
long rv;
HKEY hKey;
@@ -88,19 +101,18 @@ static int ap_registry_get_key_int(pool *p, char *key, char *pBuffer, int nSizeB
int retval;
rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- REGKEY,
+ key,
0,
KEY_READ,
&hKey);
if (rv == ERROR_FILE_NOT_FOUND) {
ap_log_error(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,NULL,
- "Registry does not contain key " REGKEY);
+ "Registry does not contain key %s",key);
return -1;
}
if (rv != ERROR_SUCCESS) {
- do_error(rv, "RegOpenKeyEx HKLM\\" REGKEY,
- NULL);
+ do_error(rv, "RegOpenKeyEx HKLM\\%s",key);
return -4;
}
@@ -110,7 +122,7 @@ static int ap_registry_get_key_int(pool *p, char *key, char *pBuffer, int nSizeB
* buffer if the return value is ERROR_SUCCESS.
*/
rv = RegQueryValueEx(hKey,
- key, /* key name */
+ name, /* key name */
NULL, /* reserved */
NULL, /* type */
NULL, /* for value */
@@ -139,7 +151,7 @@ static int ap_registry_get_key_int(pool *p, char *key, char *pBuffer, int nSizeB
}
rv = RegQueryValueEx(hKey,
- key, /* key name */
+ name, /* key name */
NULL, /* reserved */
NULL, /* type */
pValue, /* for value */
@@ -149,7 +161,7 @@ static int ap_registry_get_key_int(pool *p, char *key, char *pBuffer, int nSizeB
if (rv == ERROR_FILE_NOT_FOUND) {
ap_log_error(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,NULL,
- "Registry does not contain value " REGKEY "\\%s", key);
+ "Registry does not contain value %s\\%s", key, name);
retval = -1;
}
else if (rv == ERROR_MORE_DATA) {
@@ -169,7 +181,7 @@ static int ap_registry_get_key_int(pool *p, char *key, char *pBuffer, int nSizeB
rv = RegCloseKey(hKey);
if (rv != ERROR_SUCCESS) {
- do_error(rv, "RegCloseKey HKLM\\" REGKEY, NULL);
+ do_error(rv, "RegCloseKey HKLM\\%s", key);
if (retval == 0) {
/* Keep error status from RegQueryValueEx, if any */
retval = -4;
@@ -191,7 +203,7 @@ int ap_registry_get_server_root(pool *p, char *dir, int size)
{
int rv;
- rv = ap_registry_get_key_int(p, "ServerRoot", dir, size, NULL);
+ rv = ap_registry_get_key_int(p, REGKEY, "ServerRoot", dir, size, NULL);
if (rv < 0) {
dir[0] = '\0';
}
@@ -199,10 +211,61 @@ int ap_registry_get_server_root(pool *p, char *dir, int size)
return (rv < -1) ? -1 : 0;
}
+char *ap_get_service_key(char *service_name)
+{
+ char *key = malloc(strlen(SERVICEKEYPRE) +
+ strlen(service_name) +
+ strlen(SERVICEKEYPOST) + 1);
+
+ sprintf(key,"%s%s%s", SERVICEKEYPRE, service_name, SERVICEKEYPOST);
+
+ return(key);
+}
+
+int ap_registry_get_service_conf(pool *p, char *dir, int size, char *service_name)
+{
+ int rv;
+ char *key = ap_get_service_key(service_name);
+
+ rv = ap_registry_get_key_int(p, key, "ConfPath", dir, size, NULL);
+ if (rv < 0) {
+ dir[0] = '\0';
+ }
+
+ free(key);
+ return (rv < -1) ? -1 : 0;
+}
+
/**********************************************************************
* The rest of this file deals with storing keys or values in the registry
*/
+char *ap_registry_parse_key(int index, char *key)
+{
+ char *head = key, *skey;
+ int i;
+
+ if(!key)
+ return(NULL);
+
+ for(i = 0; i <= index; i++)
+ {
+ if(key && key[0] == '\\')
+ key++;
+ if (!key)
+ return(NULL);
+ head = key;
+ key = strchr(head, '\\');
+ }
+
+ if(!key)
+ return(strdup(head));
+ *key = '\0';
+ skey = strdup(head);
+ *key = '\\';
+ return(skey);
+}
+
/*
* ap_registry_create_apache_key() creates the Apache registry key
* (HLKM\SOFTWARE\Apache Group\Apache\version, as defined at the start
@@ -215,31 +278,25 @@ int ap_registry_get_server_root(pool *p, char *dir, int size)
* already have been logged.
*/
-static int ap_registry_create_apache_key(void)
+static int ap_registry_create_key(char *longkey)
{
- static char *keys[] =
- { "SOFTWARE",
- VENDOR,
- SOFTWARE,
- VERSION,
- NULL
- };
int index;
HKEY hKey;
HKEY hKeyNext;
int retval;
int rv;
+ char *key;
hKey = HKEY_LOCAL_MACHINE;
index = 0;
retval = 0;
/* Walk the tree, creating at each stage if necessary */
- while (keys[index]) {
+ while (key=ap_registry_parse_key(index,longkey)) {
int result;
rv = RegCreateKeyEx(hKey,
- keys[index], /* subkey */
+ key, /* subkey */
0, /* reserved */
NULL, /* class */
REG_OPTION_NON_VOLATILE,
@@ -248,7 +305,7 @@ static int ap_registry_create_apache_key(void)
&hKeyNext,
&result);
if (rv != ERROR_SUCCESS) {
- do_error(rv, "RegCreateKeyEx(%s)", keys[index]);
+ do_error(rv, "RegCreateKeyEx(%s)", longkey);
retval = -4;
}
@@ -266,11 +323,12 @@ static int ap_registry_create_apache_key(void)
break;
}
+ free(key);
hKey = hKeyNext;
index++;
}
- if (keys[index] == NULL) {
+ if (!key) {
/* Close the final key we opened, if we walked the entire
* tree
*/
@@ -283,6 +341,8 @@ static int ap_registry_create_apache_key(void)
}
}
}
+ else
+ free(key);
return retval;
}
@@ -302,14 +362,14 @@ static int ap_registry_create_apache_key(void)
* logged via aplog_error().
*/
-static int ap_registry_store_key_int(char *key, DWORD type, void *value, int value_size)
+static int ap_registry_store_key_int(char *key, char *name, DWORD type, void *value, int value_size)
{
long rv;
HKEY hKey;
int retval;
rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- REGKEY,
+ key,
0,
KEY_WRITE,
&hKey);
@@ -317,7 +377,7 @@ static int ap_registry_store_key_int(char *key, DWORD type, void *value, int val
if (rv == ERROR_FILE_NOT_FOUND) {
/* Key could not be opened -- try to create it
*/
- if (ap_registry_create_apache_key() < 0) {
+ if (ap_registry_create_key(key) < 0) {
/* Creation failed (error already reported) */
return -4;
}
@@ -325,28 +385,26 @@ static int ap_registry_store_key_int(char *key, DWORD type, void *value, int val
/* Now it has been created we should be able to open it
*/
rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- REGKEY,
+ key,
0,
KEY_WRITE,
&hKey);
if (rv == ERROR_FILE_NOT_FOUND) {
- ap_log_error(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,NULL,
- "Registry does not contain key " REGKEY " after creation");
-
+ ap_log_error(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,NULL,
+ "Registry does not contain key %s after creation",key);
return -1;
}
}
if (rv != ERROR_SUCCESS) {
- do_error(rv, "RegOpenKeyEx HKLM\\" REGKEY,
- NULL);
- return -4;
+ do_error(rv, "RegOpenKeyEx HKLM\\%s", key);
+ return -4;
}
/* Now set the value and data */
rv = RegSetValueEx(hKey,
- key, /* value key name */
+ name, /* value key name */
0, /* reserved */
type, /* type */
value, /* value data */
@@ -369,17 +427,34 @@ static int ap_registry_store_key_int(char *key, DWORD type, void *value, int val
*/
rv = RegCloseKey(hKey);
if (rv != ERROR_SUCCESS) {
- do_error(rv, "RegCloseKey HKLM\\" REGKEY, NULL);
- if (retval == 0) {
- /* Keep error status from RegQueryValueEx, if any */
- retval = -4;
- }
+ do_error(rv, "RegCloseKey HKLM\\%s", key);
+ if (retval == 0) {
+ /* Keep error status from RegQueryValueEx, if any */
+ retval = -4;
+ }
}
return retval;
}
/*
+ * Sets the service confpath value within the registry. Returns 0 on success
+ * or -1 on error. If -1 is return the error will already have been
+ * logged via aplog_error().
+ */
+
+int ap_registry_set_service_conf(char *conf, char *service_name)
+{
+ int rv;
+ char *key = ap_get_service_key(service_name);
+
+ rv = ap_registry_store_key_int(key, "ConfPath", REG_SZ, conf, strlen(conf)+1);
+ free(key);
+
+ return rv < 0 ? -1: 0;
+}
+
+/*
* Sets the serverroot value within the registry. Returns 0 on success
* or -1 on error. If -1 is return the error will already have been
* logged via aplog_error().
@@ -389,7 +464,8 @@ int ap_registry_set_server_root(char *dir)
{
int rv;
- rv = ap_registry_store_key_int("ServerRoot", REG_SZ, dir, strlen(dir)+1);
+ rv = ap_registry_store_key_int(REGKEY, "ServerRoot", REG_SZ, dir, strlen(dir)+1);
return rv < 0 ? -1 : 0;
}
+
diff --git a/usr.sbin/httpd/src/os/win32/registry.h b/usr.sbin/httpd/src/os/win32/registry.h
index cb603184af9..7075e786068 100644
--- a/usr.sbin/httpd/src/os/win32/registry.h
+++ b/usr.sbin/httpd/src/os/win32/registry.h
@@ -4,3 +4,5 @@
extern int ap_registry_get_server_root(pool *p, char *dir, int size);
extern int ap_registry_set_server_root(char *dir);
+extern int ap_registry_get_service_conf(pool *p, char *dir, int size, char *service_name);
+extern int ap_registry_set_service_conf(char *dir, char *service_name);
diff --git a/usr.sbin/httpd/src/os/win32/resource.h b/usr.sbin/httpd/src/os/win32/resource.h
new file mode 100644
index 00000000000..820bb6aaaff
--- /dev/null
+++ b/usr.sbin/httpd/src/os/win32/resource.h
@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Apache.rc
+//
+#define IDI_APACHE 101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/usr.sbin/httpd/src/os/win32/service.c b/usr.sbin/httpd/src/os/win32/service.c
index 8888aa1449b..8108ae1ad93 100644
--- a/usr.sbin/httpd/src/os/win32/service.c
+++ b/usr.sbin/httpd/src/os/win32/service.c
@@ -26,59 +26,35 @@ static struct
FILE *logFile;
} globdat;
-static void WINAPI service_main_fn(DWORD, char **);
+static void WINAPI service_main_fn(DWORD, LPTSTR *);
static void WINAPI service_ctrl(DWORD ctrlCode);
static int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint);
-static void InstallService();
-static void RemoveService();
+static int ap_start_service(SC_HANDLE);
+static int ap_stop_service(SC_HANDLE);
-
-int service_main(int (*main_fn)(int, char **), int argc, char **argv,
- char *service_name,
- int install_flag, int run_as_service)
+int service_main(int (*main_fn)(int, char **), int argc, char **argv )
{
SERVICE_TABLE_ENTRY dispatchTable[] =
{
- { service_name, service_main_fn },
+ { "", service_main_fn },
{ NULL, NULL }
};
- globdat.name = service_name;
+ globdat.main_fn = main_fn;
+ globdat.stop_event = create_event(0, 0, "apache-signal");
+ globdat.connected = 1;
- if(install_flag > 0)
- {
- InstallService();
- return(0);
- }
- else if(install_flag < 0)
+ if(!StartServiceCtrlDispatcher(dispatchTable))
{
- RemoveService();
- return(0);
+ /* This is a genuine failure of the SCM. */
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "Error starting service control dispatcher");
+ return(globdat.exit_status);
}
else
{
- globdat.main_fn = main_fn;
- globdat.stop_event = create_event(0, 0, "apache-signal");
-
- if(run_as_service)
- {
- globdat.connected = 1;
- if(!StartServiceCtrlDispatcher(dispatchTable))
- {
- return((*main_fn)(argc, argv));
- }
- else
- {
- return(globdat.exit_status);
- }
- }
- else
- {
- globdat.connected = 0;
- return((*main_fn)(argc, argv));
- }
+ return(globdat.exit_status);
}
-
}
void service_cd()
@@ -90,25 +66,27 @@ void service_cd()
chdir(buf);
}
-void __stdcall service_main_fn(DWORD argc, char **argv)
+void __stdcall service_main_fn(DWORD argc, LPTSTR *argv)
{
-
+ ap_server_argv0 = globdat.name = argv[0];
if(!(globdat.hServiceStatus = RegisterServiceCtrlHandler( globdat.name, service_ctrl)))
{
- globdat.exit_status = -1;
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "Failure registering service handler");
return;
}
-
ReportStatusToSCMgr(
SERVICE_START_PENDING, // service state
NO_ERROR, // exit code
3000); // wait hint
- globdat.exit_status = (*globdat.main_fn)( argc, argv );
-
-
+ service_cd();
+ if( service_init() )
+ /* Arguments are ok except for \! */
+ globdat.exit_status = (*globdat.main_fn)( argc, argv );
+
ReportStatusToSCMgr(SERVICE_STOPPED, NO_ERROR, 0);
return;
@@ -207,20 +185,25 @@ int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint)
return(1);
}
-
-void InstallService()
+void InstallService(char *service_name, char *conf)
{
SC_HANDLE schService;
SC_HANDLE schSCManager;
TCHAR szPath[512];
+ TCHAR szQuotedPath[512];
+
+ printf("Installing the %s service to use %s\n", service_name, conf);
if (GetModuleFileName( NULL, szPath, 512 ) == 0)
{
- exit(1);
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "GetModuleFileName failed");
return;
}
+ ap_snprintf(szQuotedPath, 512, "\"%s\"", szPath);
+
schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
@@ -233,13 +216,13 @@ void InstallService()
else {
schService = CreateService(
schSCManager, // SCManager database
- globdat.name, // name of service
- globdat.name, // name to display
+ service_name, // name of service
+ service_name, // name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
- szPath, // service's binary
+ szQuotedPath, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // dependencies
@@ -249,8 +232,9 @@ void InstallService()
if (schService) {
CloseServiceHandle(schService);
- /* Now store the server_root in the registry */
- ap_registry_set_server_root(ap_server_root);
+ /* Now store the server_root in the registry */
+ if(!ap_registry_set_service_conf(conf, service_name))
+ printf("The %s service has been installed successfully.\n", service_name );
}
else {
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
@@ -259,17 +243,16 @@ void InstallService()
CloseServiceHandle(schSCManager);
}
-
}
-
-
-void RemoveService()
+void RemoveService(char *service_name)
{
SC_HANDLE schService;
SC_HANDLE schSCManager;
+ printf("Removing the %s service\n", service_name);
+
schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
@@ -280,7 +263,7 @@ void RemoveService()
"OpenSCManager failed");
}
else {
- schService = OpenService(schSCManager, globdat.name, SERVICE_ALL_ACCESS);
+ schService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS);
if (schService == NULL) {
/* Could not open the service */
@@ -289,28 +272,160 @@ void RemoveService()
}
else {
/* try to stop the service */
- if (ControlService(schService, SERVICE_CONTROL_STOP, &globdat.ssStatus)) {
- Sleep(1000);
- while(QueryServiceStatus(schService, &globdat.ssStatus)) {
- if(globdat.ssStatus.dwCurrentState == SERVICE_STOP_PENDING)
- Sleep(1000);
- else
- break;
- }
- }
+ ap_stop_service(schService);
// now remove the service
if (DeleteService(schService) == 0)
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
"DeleteService failed");
+ else
+ printf("The %s service has been removed successfully.\n", service_name );
CloseServiceHandle(schService);
}
+ /* SCM removes registry parameters */
+ CloseServiceHandle(schSCManager);
+ }
+
+}
+
+/* A hack to determine if we're running as a service without waiting for
+ * the SCM to fail; if AllocConsole succeeds, we're a service.
+ */
+
+BOOL isProcessService() {
+ if( !AllocConsole() )
+ return FALSE;
+ FreeConsole();
+ return TRUE;
+}
+
+/* Determine is service_name is a valid service
+ */
+
+BOOL isValidService(char *service_name) {
+ SC_HANDLE schSCM, schSVC;
+ int Err;
+
+ if (!(schSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "OpenSCManager failed");
+ return FALSE;
+ }
+
+ if ((schSVC = OpenService(schSCM, service_name, SERVICE_ALL_ACCESS))) {
+ CloseServiceHandle(schSVC);
+ CloseServiceHandle(schSCM);
+ return TRUE;
+ }
+
+ Err = GetLastError();
+ if (Err != ERROR_SERVICE_DOES_NOT_EXIST && Err != ERROR_INVALID_NAME)
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "OpenService failed");
+
+ return FALSE;
+}
+
+int send_signal_to_service(char *service_name, char *sig) {
+ SC_HANDLE schService;
+ SC_HANDLE schSCManager;
+ int success = FALSE;
+
+ enum { start, restart, stop, unknown } action;
+ static char *param[] = { "start", "restart", "shutdown" };
+ static char *participle[] = { "starting", "restarting", "stopping" };
+ static char *past[] = { "started", "restarted", "stopped" };
+
+ for (action = start; action < unknown; action++)
+ if (!strcasecmp(sig, param[action]))
+ break;
+
+ if (action == unknown) {
+ printf("signal must be start, restart, or shutdown\n");
+ return FALSE;
+ }
+
+ schSCManager = OpenSCManager(
+ NULL, // machine (NULL == local)
+ NULL, // database (NULL == default)
+ SC_MANAGER_ALL_ACCESS // access required
+ );
+ if (!schSCManager) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "OpenSCManager failed");
+ }
+ else {
+ schService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS);
+
+ if (schService == NULL) {
+ /* Could not open the service */
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "OpenService failed");
+ }
+ else {
+ if (!QueryServiceStatus(schService, &globdat.ssStatus))
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
+ "QueryService failed");
+ else {
+ if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED && action == stop)
+ printf("The %s service is not started.\n", service_name);
+ else if (globdat.ssStatus.dwCurrentState == SERVICE_RUNNING && action == start)
+ printf("The %s service has already been started.\n", service_name);
+ else {
+ printf("The %s service is %s.\n", service_name, participle[action]);
+
+ if (action == stop || action == restart)
+ success = ap_stop_service(schService);
+ if (action == start || action == restart)
+ success = ap_start_service(schService);
+
+ if( success )
+ printf("The %s service has %s.\n", service_name, past[action]);
+ else
+ printf("Failed to %s the %s service.\n", sig, service_name );
+ }
+ CloseServiceHandle(schService);
+ }
+ }
+ /* SCM removes registry parameters */
CloseServiceHandle(schSCManager);
}
+ return success;
+}
+int ap_stop_service(SC_HANDLE schService)
+{
+ if (ControlService(schService, SERVICE_CONTROL_STOP, &globdat.ssStatus)) {
+ Sleep(1000);
+ while (QueryServiceStatus(schService, &globdat.ssStatus)) {
+ if (globdat.ssStatus.dwCurrentState == SERVICE_STOP_PENDING)
+ Sleep(1000);
+ else
+ break;
+ }
+ }
+ if (QueryServiceStatus(schService, &globdat.ssStatus))
+ if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED)
+ return TRUE;
+ return FALSE;
}
+int ap_start_service(SC_HANDLE schService) {
+ if (StartService(schService, 0, NULL)) {
+ Sleep(1000);
+ while(QueryServiceStatus(schService, &globdat.ssStatus)) {
+ if(globdat.ssStatus.dwCurrentState == SERVICE_START_PENDING)
+ Sleep(1000);
+ else
+ break;
+ }
+ }
+ if (QueryServiceStatus(schService, &globdat.ssStatus))
+ if (globdat.ssStatus.dwCurrentState == SERVICE_RUNNING)
+ return TRUE;
+ return FALSE;
+}
+
#endif /* WIN32 */
-
diff --git a/usr.sbin/httpd/src/os/win32/service.h b/usr.sbin/httpd/src/os/win32/service.h
index e8b3316ea3d..822596c4161 100644
--- a/usr.sbin/httpd/src/os/win32/service.h
+++ b/usr.sbin/httpd/src/os/win32/service.h
@@ -3,11 +3,15 @@
#define SERVICE_H
#ifdef WIN32
-int service_main(int (*main_fn)(int, char **), int argc, char **argv,
- char *service_name,
- int install_flag, int run_as_service);
+int service_main(int (*main_fn)(int, char **), int argc, char **argv);
void service_set_status(int status);
void service_cd();
+BOOL isProcessService();
+BOOL isValidService(char *service_name);
+void InstallService(char *service_name, char *conf);
+void RemoveService(char *service_name);
+int service_init();
+int send_signal_to_service(char *service_name, char *sig);
#endif /* WIN32 */
#endif /* SERVICE_H */
diff --git a/usr.sbin/httpd/src/os/win32/util_win32.c b/usr.sbin/httpd/src/os/win32/util_win32.c
index 249faf28e6a..348e0f9e2aa 100644
--- a/usr.sbin/httpd/src/os/win32/util_win32.c
+++ b/usr.sbin/httpd/src/os/win32/util_win32.c
@@ -571,7 +571,7 @@ API_EXPORT(int) os_strftime(char *s, size_t max, const char *format,
API_EXPORT(int) ap_os_is_filename_valid(const char *file)
{
const char *segstart;
- char seglength;
+ unsigned int seglength;
const char *pos;
static const char * const invalid_characters = "?\"<>*|:";
static const char * const invalid_filenames[] = {
@@ -621,8 +621,8 @@ API_EXPORT(int) ap_os_is_filename_valid(const char *file)
}
while (*pos) {
- int idx;
- int baselength;
+ unsigned int idx;
+ unsigned int baselength;
while (*pos == '/' || *pos == '\\') {
pos++;
@@ -642,7 +642,7 @@ API_EXPORT(int) ap_os_is_filename_valid(const char *file)
/* Test 2 */
for (idx = 0; idx < seglength; idx++) {
- if (segstart[idx] < 32 ||
+ if ((segstart[idx] > 0 && segstart[idx] < 32) ||
strchr(invalid_characters, segstart[idx])) {
return 0;
}
@@ -665,7 +665,8 @@ API_EXPORT(int) ap_os_is_filename_valid(const char *file)
* if it does not include any dot characters). */
if (baselength == 3 || baselength == 4) {
for (idx = 0; invalid_filenames[idx]; idx++) {
- if (!strnicmp(invalid_filenames[idx], segstart, baselength)) {
+ if (strlen(invalid_filenames[idx]) == baselength &&
+ !strnicmp(invalid_filenames[idx], segstart, baselength)) {
return 0;
}
}
diff --git a/usr.sbin/httpd/src/regex/debug.c b/usr.sbin/httpd/src/regex/debug.c
index 1c18964c373..fdf49f6cdea 100644
--- a/usr.sbin/httpd/src/regex/debug.c
+++ b/usr.sbin/httpd/src/regex/debug.c
@@ -6,6 +6,7 @@
#include <sys/types.h>
#include "hsregex.h"
+#include "ap_ctype.h"
#include "utils.h"
#include "regex2.h"
#include "debug.ih"
diff --git a/usr.sbin/httpd/src/regex/main.c b/usr.sbin/httpd/src/regex/main.c
index 3d333040142..1c4364cae9f 100644
--- a/usr.sbin/httpd/src/regex/main.c
+++ b/usr.sbin/httpd/src/regex/main.c
@@ -20,6 +20,8 @@ regoff_t endoff = 0;
extern int split();
extern void regprint();
+extern int optind;
+extern char *optarg;
/*
- main - do the simple case, hand off to regress() for regression
@@ -37,8 +39,6 @@ char *argv[];
int c;
int errflg = 0;
register int i;
- extern int optind;
- extern char *optarg;
progname = argv[0];
diff --git a/usr.sbin/httpd/src/regex/regex.3 b/usr.sbin/httpd/src/regex/regex.3
index 6d4f9b89b8d..100c8a7f71c 100644
--- a/usr.sbin/httpd/src/regex/regex.3
+++ b/usr.sbin/httpd/src/regex/regex.3
@@ -36,7 +36,7 @@ matches that internal form against a string and reports results,
transforms error codes from either into human-readable messages,
and
.I regfree
-frees any dynamically allocated storage used by the internal form
+frees any dynamically-allocated storage used by the internal form
of an RE.
.PP
The header
@@ -353,7 +353,7 @@ caution in software intended to be portable to other systems.
Be warned also that they are considered experimental and changes are possible.
.PP
.I Regfree
-frees any dynamically allocated storage associated with the compiled RE
+frees any dynamically-allocated storage associated with the compiled RE
pointed to by
.IR preg .
The remaining
diff --git a/usr.sbin/httpd/src/regex/regex.7 b/usr.sbin/httpd/src/regex/regex.7
index fcec9a8b37c..d89012bda1d 100644
--- a/usr.sbin/httpd/src/regex/regex.7
+++ b/usr.sbin/httpd/src/regex/regex.7
@@ -93,7 +93,7 @@ or a collating-sequence name for either)
enclosed in `[.' and `.]' stands for the
sequence of characters of that collating element.
The sequence is a single element of the bracket expression's list.
-A bracket expression containing a multi-character collating element
+A bracket expression containing a multi-character collating element
can thus match more than one character,
e.g. if the collating sequence includes a `ch' collating element,
then the RE `[[.ch.]]*c' matches the first five characters
diff --git a/usr.sbin/httpd/src/regex/split.c b/usr.sbin/httpd/src/regex/split.c
index 188bdb775b9..6359aba8ab4 100644
--- a/usr.sbin/httpd/src/regex/split.c
+++ b/usr.sbin/httpd/src/regex/split.c
@@ -1,6 +1,8 @@
#include <stdio.h>
#include <string.h>
+extern int split(char *, char *[], int, char *);
+
/*
- split - divide a string into fields, like awk split()
= int split(char *string, char *fields[], int nfields, char *sep);
diff --git a/usr.sbin/httpd/src/support/Makefile.tmpl b/usr.sbin/httpd/src/support/Makefile.tmpl
index 216d9657ea4..33c13777739 100644
--- a/usr.sbin/httpd/src/support/Makefile.tmpl
+++ b/usr.sbin/httpd/src/support/Makefile.tmpl
@@ -1,6 +1,6 @@
CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
-LIBS=-los -lap $(EXTRA_LIBS) $(LIBS1)
+LIBS=-lap -los $(EXTRA_LIBS) $(LIBS1)
INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS) -L$(OSDIR) -L$(SRCDIR)/ap
@@ -35,18 +35,12 @@ apxs: apxs.pl
-e 's%@CFLAGS@%$(CFLAGS)%g' \
-e 's%@CFLAGS_SHLIB@%$(CFLAGS_SHLIB)%g' \
-e 's%@LD_SHLIB@%$(LD_SHLIB)%g' \
- -e 's%@LDFLAGS_SHLIB@%$(LDFLAGS_SHLIB)%g' \
+ -e 's%@LDFLAGS_MOD_SHLIB@%$(LDFLAGS_MOD_SHLIB)%g' \
-e 's%@LIBS_SHLIB@%$(LIBS_SHLIB)%g' && chmod a+x apxs
suexec: suexec.o
$(CC) $(CFLAGS) suexec.o -o suexec $(LDFLAGS) $(LIBS)
-ca-fix: ca-fix.c
- $(CC) $(INCLUDES) $(CFLAGS) $(SSL_CFLAGS) \
- $(LDFLAGS) $(SSL_LDFLAGS) \
- -o ca-fix ca-fix.c \
- $(LIBS) $(SSL_LIBS)
-
clean:
rm -f $(TARGETS) *.o
@@ -74,7 +68,7 @@ ab.o: ab.c $(INCDIR)/ap_config.h $(INCDIR)/ap_config_auto.h \
$(OSDIR)/os.h $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h
htdigest.o: htdigest.c $(INCDIR)/ap_config.h \
$(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(INCDIR)/ap_ctype.h \
- $(INCDIR)/hsregex.h ../main/md5c.c $(INCDIR)/ap_md5.h
+ $(INCDIR)/hsregex.h $(INCDIR)/ap_md5.h
htpasswd.o: htpasswd.c $(INCDIR)/ap_config.h \
$(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(INCDIR)/ap_ctype.h \
$(INCDIR)/hsregex.h
diff --git a/usr.sbin/httpd/src/support/README b/usr.sbin/httpd/src/support/README
new file mode 100644
index 00000000000..80e9cafde0a
--- /dev/null
+++ b/usr.sbin/httpd/src/support/README
@@ -0,0 +1,62 @@
+Support files:
+
+ab
+ ABuse your server with this benchmarker. Rudimentary
+ command line testing tool.
+
+apachectl
+ Apache run-time Control script. To facilitate the
+ administrator and/or your rc.d scripts to control the
+ functioning of the Apache httpd daemon.
+
+apxs
+ APache eXtenSion tool. Eases building and installing
+ DSO style modules.
+
+dbmmanage
+ Create and update user authentication files in the faster
+ DBM format used by mod_auth_db.
+
+htdigest
+ Create and update user authentication files used in
+ DIGEST authentification. See mod_auth_digest.
+
+htpasswd
+ Create and update user authentication files used in
+ BASIC authentification. I.e. the htpasswd files.
+ See mod_auth.
+
+httpd.8
+ General apache man page.
+
+log_server_status
+ This script is designed to be run at a frequent interval by something
+ like cron. It connects to the server and downloads the status
+ information. It reformats the information to a single line and logs
+ it to a file.
+
+logresolve
+ resolve hostnames for IP-adresses in Apache logfiles
+
+phf_abuse_log.cgi
+ This script can be used to detect people trying to abuse an ancient
+ and long plugged security hole which existed in a CGI script distributed
+ with Apache 1.0.3 and earlier versions.
+
+rotatelogs
+ rotate Apache logs without having to kill the server.
+
+split-logfile
+ This script will take a combined virtual hosts access
+ log file and break its contents into separate files.
+
+suexec
+ Switch User For Exec. Used internally by apache,
+ see the document `Apache suEXEC Support'
+ under http://www.apache.org/docs/suexec.html .
+
+SHA1
+ This directory includes some utilities to allow Apache 1.3.6 to
+ recognize passwords in SHA1 format, as used by Netscape web
+ servers. It is not installed by default.
+
diff --git a/usr.sbin/httpd/src/support/SHA1/README.sha1 b/usr.sbin/httpd/src/support/SHA1/README.sha1
new file mode 100644
index 00000000000..3998e1fdd91
--- /dev/null
+++ b/usr.sbin/httpd/src/support/SHA1/README.sha1
@@ -0,0 +1,34 @@
+This directory includes some utilities to allow Apache 1.3.6 to
+recognize passwords in SHA1 format, as used by Netscape web servers.
+
+From Netscape's admin interface, export the password database to an
+ldif file and then use convert.pl in this distribution to generate
+apache style password files.
+
+Note: SHA1 support is useful for migration purposes, but is less
+ secure than Apache's password format, since Apache's (MD5)
+ password format uses a random eight character salt to generate
+ one of many possible hashes for the same password. Netscape
+ uses plain SHA1 without a salt, so the same password
+ will always generate the same hash, making it easier
+ to break since the search space is smaller.
+
+This code was contributed by Clinton Wong <clintdw@netcom.com>.
+
+README.sha1
+ this file
+
+convert-sha1.pl
+ takes an ldif dump from Netscape's web server on
+ standard in, outputs apache htpasswd format on standard out.
+
+ Usage: convert.pl < ldif > passwords
+
+htpasswd-sha1.pl
+ perl script to generate entries in apache htpasswd format.
+
+ Usage: htpasswd-sha1.pl some_user some_password
+
+ldif-sha1.example
+ sample ldif dump with one sha1 password and one crypt password.
+
diff --git a/usr.sbin/httpd/src/support/SHA1/convert-sha1.pl b/usr.sbin/httpd/src/support/SHA1/convert-sha1.pl
new file mode 100644
index 00000000000..35228022a08
--- /dev/null
+++ b/usr.sbin/httpd/src/support/SHA1/convert-sha1.pl
@@ -0,0 +1,36 @@
+#!/usr/bin/perl -w
+use strict;
+
+# This is public domain code. Do whatever you want with it.
+# It was originally included in Clinton Wong's Apache 1.3.6 SHA1/ldif
+# patch distribution as sample code for converting accounts from
+# ldif format (as used by Netscape web servers) to Apache password format.
+
+my $uid='';
+my $passwd='';
+
+while (my $line = <>) {
+ chomp $line;
+ if ( $line =~ /uid:\s*(.+)/) { $uid = $1 }
+ if ( $line =~ /userpassword:\s*(\{\w+\}.+)/) {
+ $passwd = $1;
+ $passwd =~ s/^\{crypt\}//i; # Apache stores crypt without a magic string
+ }
+
+ if (length($line)==0) {
+
+ if (length $uid and length $passwd) {
+ print $uid, ':', $passwd, "\n";
+ } # output if we have something to print
+
+ $uid = '';
+ $passwd = '';
+
+ } # if newline
+} # while something to read
+
+# handle last entry if there isn't a newline before EOF
+ if (length $uid and length $passwd) {
+ print $uid, ':', $passwd, "\n";
+}
+
diff --git a/usr.sbin/httpd/src/support/SHA1/htpasswd-sha1.pl b/usr.sbin/httpd/src/support/SHA1/htpasswd-sha1.pl
new file mode 100644
index 00000000000..ad624d1101f
--- /dev/null
+++ b/usr.sbin/httpd/src/support/SHA1/htpasswd-sha1.pl
@@ -0,0 +1,22 @@
+#!/usr/bin/perl -w
+use strict;
+#
+# Utility which takes a username and password
+# on the command line and generates a username
+# sha1-encrytped password on the stdout.
+#
+# Typical useage:
+# ./htpasswd-sha1.pl dirkx MySecret >> sha1-passwd
+#
+# This is public domain code. Do whatever you want with it.
+# It was originally included in Clinton Wong's Apache 1.3.6 SHA1/ldif
+# patch distribution as sample code for generating entries for
+# Apache password files using SHA1.
+
+use MIME::Base64; # http://www.cpan.org/modules/by-module/MIME/
+use Digest::SHA1; # http://www.cpan.org/modules/by-module/MD5/
+
+if ($#ARGV!=1) { die "Usage $0: user password\n" }
+
+print $ARGV[0], ':{SHA}', encode_base64( Digest::SHA1::sha1($ARGV[1]) );
+
diff --git a/usr.sbin/httpd/src/support/SHA1/ldif-sha1.example b/usr.sbin/httpd/src/support/SHA1/ldif-sha1.example
new file mode 100644
index 00000000000..b8fe917eaf3
--- /dev/null
+++ b/usr.sbin/httpd/src/support/SHA1/ldif-sha1.example
@@ -0,0 +1,19 @@
+dn: cn=someuser
+cn: someuser
+sn: someuser
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+uid: someuser
+userpassword: {SHA}GvF+c3IdvgxAARuC7Uuxp9vjzik=
+
+dn: cn=anotheruser
+cn: anotheruser
+sn: anotheruser
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+uid: anotheruser
+userpassword: {crypt}eFnp.4sz5XnH6
diff --git a/usr.sbin/httpd/src/support/ab.1 b/usr.sbin/httpd/src/support/ab.8
index 2a034d2d9ee..871c457797a 100644
--- a/usr.sbin/httpd/src/support/ab.1
+++ b/usr.sbin/httpd/src/support/ab.8
@@ -1,4 +1,5 @@
.TH ab 1 "March 1998"
+.\" $Id: ab.8,v 1.1 1999/09/29 06:30:07 beck Exp $
.\" Copyright (c) 1998-1999 The Apache Group. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -6,7 +7,7 @@
.\" are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
+.\" notice, this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in
@@ -54,7 +55,7 @@
.SH NAME
ab \- Apache HTTP server benchmarking tool
.SH SYNOPSIS
-.B ab
+.B ab
[
.B \-k
] [
@@ -63,14 +64,40 @@ ab \- Apache HTTP server benchmarking tool
.BI \-t " timelimit"
] [
.BI \-c " concurrency"
+] [
+.BI \-p " POST file"
+] [
+.BI \-A " Authenticate username:password"
+] [
+.BI \-P " Proxy Authenticate username:password"
+] [
+.BI \-H " Custom header"
+] [
+.BI \-C " Cookie name=value"
+] [
+.BI \-T " content-type"
+] [
+.BI \-v " verbosity"
+]
+] [
+.BI \-w " output HTML"
]
-.I [http://]hostname[:port]/path
+] [
+.BI \-x " <table> attributes"
+]
+] [
+.BI \-y " <tr> attributes"
+]
+] [
+.BI \-z " <td> attributes"
+]
+.I [http://]hostname[:port]/path
.B ab
[
-.B \-v
+.B \-V
] [
-.B \-h
+.B \-h
]
.PP
.SH DESCRIPTION
@@ -78,11 +105,11 @@ ab \- Apache HTTP server benchmarking tool
is a tool for benchmarking your Apache HyperText Transfer Protocol (HTTP)
server. It is designed to give you an impression on how performant is your
current Apache installation. This especially shows you how much requests per
-time your Apache installation is capable to serve.
+time your Apache installation is capable to serve.
.PP
.SH OPTIONS
.TP 12
-.B \-k
+.B \-k
Enable the HTTP KeepAlive feature, i.e. perform multiple requests within one
HTTP session instead. Default is no KeepAlive.
.TP 12
@@ -93,22 +120,91 @@ benchmarking results.
.TP 12
.BI \-t " timelimit"
Seconds to max. spend for benchmarking. This implies
-a
-.B \-n
+a
+.B \-n
.B 50000
internally. Use this to benchmark the server within a fixed total amount of
-time. Per default there is no timelimit.
+time. Per default there is no timelimit.
.TP 12
.BI \-c " concurrency"
-Number of multiple requests per time to perform.
+Number of multiple requests per time to perform.
Default is one request per time.
+
.TP 12
-.B \-v
-Display version and copyright information.
+.BI \-p " POST file"
+File containing data to POST.
+
.TP 12
-.B \-h
+.BI \-A " Authorization username:password"
+Supply BASIC Authentification credentials to the server. The username
+and password are separated by a single ':' and send on the wire uuencoded.
+The string is send regardless of wether the server needs it; (i.e. has
+send an 401. Authentifcation needed).
+
+.TP 12
+.BI \-p " Proxy-Authorization username:password"
+Supply BASIC Authentification credentials to a proxy en-route. The username
+and password are separated by a single ':' and send on the wire uuencoded.
+The string is send regardless of wether the proxy needs it; (i.e. has
+send an 407 Proxy authentifcation needed).
+
+.TP 12
+.BI \-C " Cookie name=value"
+Add a 'Cookie:' line to the request. The argument is typically in the form
+of a 'name=value' pair. This field is repeatable.
+
+.TP 12
+.BI \-p " Header string"
+Postfix extra headers to the request. The argument is typically in the form
+of a valid header line; containing a colon separated field value pair. (i.e.
+'Accept-Encoding: zip/zop;8bit').
+
+.TP 12
+.BI \-T " content-type"
+Content-type header to use for POST data.
+
+.TP 12
+.B \-v
+Set verbosity level - 4 and above prints information on headers, 3 and
+above prints response codes (404, 200, etc.), 2 and above prints
+warnings and info.
+
+.TP 12
+.BI \-w
+Print out results in HTML tables. Default table is two columns wide,
+with a white background.
+.TP 12
+.BI \-x " attributes"
+String to use as attributes for <table>. Attributes are inserted
+<table
+.B here
+>
+.TP 12
+.BI \-y " attributes"
+String to use as attributes for <tr>.
+.TP 12
+.BI \-z " attributes"
+String to use as attributes for <td>.
+.TP 12
+.B \-V
+Display version number and exit.
+.TP 12
+.B \-h
Display usage information.
.PD
+.SH BUGS
+There are various statically declared buffers of fixed length. Combined
+with the lazy parsing of the command line arguments, the response headers
+from the server and other external inputs this might bite you.
+.P
+It does not implement HTTP/1.x fully; only accepts some 'expected' forms
+of responses. The rather heavy use of
+.BR strstr(3)
+shows up top in profile,
+which might indicate a performance problem; i.e. you would measure the
+.BR ab
+performance rather than the server's.
+
.SH SEE ALSO
.BR httpd(8)
.
diff --git a/usr.sbin/httpd/src/support/ab.c b/usr.sbin/httpd/src/support/ab.c
index 051d19e8dd8..0d968b247a2 100644
--- a/usr.sbin/httpd/src/support/ab.c
+++ b/usr.sbin/httpd/src/support/ab.c
@@ -6,7 +6,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
@@ -55,33 +55,35 @@
*
*/
-/*
-** This program is based on ZeusBench V1.0 written by Adam Twiss
-** which is Copyright (c) 1996 by Zeus Technology Ltd. http://www.zeustech.net/
-**
-** This software is provided "as is" and any express or implied waranties,
-** including but not limited to, the implied warranties of merchantability and
-** fitness for a particular purpose are disclaimed. In no event shall
-** Zeus Technology Ltd. be liable for any direct, indirect, incidental, special,
-** exemplary, or consequential damaged (including, but not limited to,
-** procurement of substitute good or services; loss of use, data, or profits;
-** or business interruption) however caused and on theory of liability. Whether
-** in contract, strict liability or tort (including negligence or otherwise)
-** arising in any way out of the use of this software, even if advised of the
-** possibility of such damage.
-**
-*/
+/*
+ ** This program is based on ZeusBench V1.0 written by Adam Twiss
+ ** which is Copyright (c) 1996 by Zeus Technology Ltd. http://www.zeustech.net/
+ **
+ ** This software is provided "as is" and any express or implied waranties,
+ ** including but not limited to, the implied warranties of merchantability and
+ ** fitness for a particular purpose are disclaimed. In no event shall
+ ** Zeus Technology Ltd. be liable for any direct, indirect, incidental, special,
+ ** exemplary, or consequential damaged (including, but not limited to,
+ ** procurement of substitute good or services; loss of use, data, or profits;
+ ** or business interruption) however caused and on theory of liability. Whether
+ ** in contract, strict liability or tort (including negligence or otherwise)
+ ** arising in any way out of the use of this software, even if advised of the
+ ** possibility of such damage.
+ **
+ */
/*
-** HISTORY:
-** - Originally written by Adam Twiss <adam@zeus.co.uk>, March 1996
-** with input from Mike Belshe <mbelshe@netscape.com> and
-** Michael Campanella <campanella@stevms.enet.dec.com>
-** - Enhanced by Dean Gaudet <dgaudet@apache.org>, November 1997
-** - Cleaned up by Ralf S. Engelschall <rse@apache.org>, March 1998
-** - POST and verbosity by Kurt Sussman <kls@merlot.com>, August 1998
-**
-*/
+ ** HISTORY:
+ ** - Originally written by Adam Twiss <adam@zeus.co.uk>, March 1996
+ ** with input from Mike Belshe <mbelshe@netscape.com> and
+ ** Michael Campanella <campanella@stevms.enet.dec.com>
+ ** - Enhanced by Dean Gaudet <dgaudet@apache.org>, November 1997
+ ** - Cleaned up by Ralf S. Engelschall <rse@apache.org>, March 1998
+ ** - POST and verbosity by Kurt Sussman <kls@merlot.com>, August 1998
+ ** - HTML table output added by David N. Welton <davidw@prosa.it>, January 1999
+ ** - Added Cookie, Arbitrary header and auth support. <dirkx@webweaving.org>, April 199
+ **
+ */
/*
* BUGS:
@@ -95,7 +97,7 @@
* only an issue for loopback usage
*/
-#define VERSION "1.2"
+#define VERSION "1.3a"
/* -------------------------------------------------------------------- */
@@ -118,12 +120,22 @@
#include <sys/ioctl.h>
#include <string.h>
-#define ap_select select
-#else /* (!)NO_APACHE_INCLUDES */
+#define ap_select select
+#else /* (!)NO_APACHE_INCLUDES */
#include "ap_config.h"
+#include "ap.h"
+#ifdef CHARSET_EBCDIC
+#include "ebcdic.h"
+#endif
#include <fcntl.h>
#include <sys/time.h>
-#endif /* NO_APACHE_INCLUDES */
+
+#ifndef NO_WRITEV
+#include <sys/types.h>
+#include <sys/uio.h>
+#endif
+
+#endif /* NO_APACHE_INCLUDES */
/* ------------------- DEFINITIONS -------------------------- */
/* maximum number of requests on a time limited test */
@@ -139,20 +151,21 @@
struct connection {
int fd;
int state;
- int read; /* amount of bytes read */
- int bread; /* amount of body read */
- int length; /* Content-Length value used for keep-alive */
- char cbuff[CBUFFSIZE]; /* a buffer to store server response header */
- int cbx; /* offset in cbuffer */
- int keepalive; /* non-zero if a keep-alive request */
- int gotheader; /* non-zero if we have the entire header in cbuff */
+ int read; /* amount of bytes read */
+ int bread; /* amount of body read */
+ int length; /* Content-Length value used for keep-alive */
+ char cbuff[CBUFFSIZE]; /* a buffer to store server response header */
+ int cbx; /* offset in cbuffer */
+ int keepalive; /* non-zero if a keep-alive request */
+ int gotheader; /* non-zero if we have the entire header in
+ * cbuff */
struct timeval start, connect, done;
};
struct data {
- int read; /* number of bytes read */
- int ctime; /* time in ms to connect */
- int time; /* time in ms for connection */
+ int read; /* number of bytes read */
+ int ctime; /* time in ms to connect */
+ int time; /* time in ms for connection */
};
#define ap_min(a,b) ((a)<(b))?(a):(b)
@@ -160,28 +173,37 @@ struct data {
/* --------------------- GLOBALS ---------------------------- */
-int verbosity = 0; /* no verbosity by default */
-int posting = 0; /* GET by default */
-int requests = 1; /* Number of requests to make */
-int concurrency = 1; /* Number of multiple requests to make */
-int tlimit = 0; /* time limit in cs */
-int keepalive = 0; /* try and do keepalive connections */
-char servername[1024]; /* name that server reports */
-char hostname[1024]; /* host name */
-char path[1024]; /* path name */
-char postfile[1024]; /* name of file containing post data */
-char* postdata; /* *buffer containing data from postfile */
-int postlen = 0; /* length of data to be POSTed */
-char content_type[1024]; /* content type to put in POST header */
-int port = 80; /* port number */
-
-int doclen = 0; /* the length the document should be */
-int totalread = 0; /* total number of bytes read */
-int totalbread = 0; /* totoal amount of entity body read */
-int totalposted = 0; /* total number of bytes posted, inc. headers */
-int done = 0; /* number of requests we have done */
-int doneka = 0; /* number of keep alive connections done */
-int good = 0, bad = 0; /* number of good and bad requests */
+int verbosity = 0; /* no verbosity by default */
+int posting = 0; /* GET by default */
+int requests = 1; /* Number of requests to make */
+int concurrency = 1; /* Number of multiple requests to make */
+int tlimit = 0; /* time limit in cs */
+int keepalive = 0; /* try and do keepalive connections */
+char servername[1024]; /* name that server reports */
+char hostname[1024]; /* host name */
+char path[1024]; /* path name */
+char postfile[1024]; /* name of file containing post data */
+char *postdata; /* *buffer containing data from postfile */
+int postlen = 0; /* length of data to be POSTed */
+char content_type[1024]; /* content type to put in POST header */
+char cookie[1024], /* optional cookie line */
+ auth[1024], /* optional (basic/uuencoded)
+ * authentification */
+ hdrs[4096]; /* optional arbitrary headers */
+int port = 80; /* port number */
+
+int use_html = 0; /* use html in the report */
+char *tablestring;
+char *trstring;
+char *tdstring;
+
+int doclen = 0; /* the length the document should be */
+int totalread = 0; /* total number of bytes read */
+int totalbread = 0; /* totoal amount of entity body read */
+int totalposted = 0; /* total number of bytes posted, inc. headers */
+int done = 0; /* number of requests we have done */
+int doneka = 0; /* number of keep alive connections done */
+int good = 0, bad = 0; /* number of good and bad requests */
/* store error cases */
int err_length = 0, err_conn = 0, err_except = 0;
@@ -196,11 +218,11 @@ int reqlen;
/* one global throw-away buffer to read stuff into */
char buffer[8192];
-struct connection *con; /* connection array */
-struct data *stats; /* date for each request */
+struct connection *con; /* connection array */
+struct data *stats; /* date for each request */
-fd_set readbits, writebits; /* bits for select */
-struct sockaddr_in server; /* server addr structure */
+fd_set readbits, writebits; /* bits for select */
+struct sockaddr_in server; /* server addr structure */
/* --------------------------------------------------------- */
@@ -209,7 +231,7 @@ struct sockaddr_in server; /* server addr structure */
static void err(char *s)
{
if (errno) {
- perror(s);
+ perror(s);
}
else {
printf("%s", s);
@@ -219,18 +241,33 @@ static void err(char *s)
/* --------------------------------------------------------- */
-/* write out request to a connection - assumes we can write
+/* write out request to a connection - assumes we can write
(small) request out in one go into our new socket buffer */
-static void write_request(struct connection *c)
+static void write_request(struct connection * c)
{
+#ifndef NO_WRITEV
+ struct iovec out[2]; int outcnt = 1;
+#endif
gettimeofday(&c->connect, 0);
- /* XXX: this could use writev for posting -- more efficient -djg */
- write(c->fd, request, reqlen);
+#ifndef NO_WRITEV
+ out[0].iov_base = request;
+ out[0].iov_len = reqlen;
+
if (posting) {
- write(c->fd,postdata, postlen);
- totalposted += (reqlen + postlen);
+ out[1].iov_base = postdata;
+ out[1].iov_len = postlen;
+ outcnt = 2;
+ totalposted += (reqlen + postlen);
}
+ writev(c->fd,out, outcnt);
+#else
+ write(c->fd,request,reqlen);
+ if (posting) {
+ write(c->fd,postdata,postlen);
+ totalposted += (reqlen + postlen);
+ }
+#endif
c->state = STATE_READ;
FD_SET(c->fd, &readbits);
@@ -283,65 +320,191 @@ static void output_results(void)
printf("\n");
printf("Concurrency Level: %d\n", concurrency);
printf("Time taken for tests: %d.%03d seconds\n",
- timetaken / 1000, timetaken % 1000);
+ timetaken / 1000, timetaken % 1000);
printf("Complete requests: %d\n", done);
printf("Failed requests: %d\n", bad);
if (bad)
- printf(" (Connect: %d, Length: %d, Exceptions: %d)\n",
- err_conn, err_length, err_except);
+ printf(" (Connect: %d, Length: %d, Exceptions: %d)\n",
+ err_conn, err_length, err_except);
if (err_response)
- printf("Non-2xx responses: %d\n", err_response);
+ printf("Non-2xx responses: %d\n", err_response);
if (keepalive)
- printf("Keep-Alive requests: %d\n", doneka);
+ printf("Keep-Alive requests: %d\n", doneka);
printf("Total transferred: %d bytes\n", totalread);
if (posting)
- printf("Total POSTed: %d\n", totalposted);
+ printf("Total POSTed: %d\n", totalposted);
printf("HTML transferred: %d bytes\n", totalbread);
/* avoid divide by zero */
if (timetaken) {
- printf("Requests per second: %.2f\n", 1000 * (float) (done) / timetaken);
- printf("Transfer rate: %.2f kb/s received\n",
- (float) (totalread) / timetaken);
- if (posting) {
- printf(" %.2f kb/s sent\n",
- (float)(totalposted)/timetaken);
- printf(" %.2f kb/s total\n",
- (float)(totalread + totalposted)/timetaken);
- }
+ printf("Requests per second: %.2f\n", 1000 * (float) (done) / timetaken);
+ printf("Transfer rate: %.2f kb/s received\n",
+ (float) (totalread) / timetaken);
+ if (posting) {
+ printf(" %.2f kb/s sent\n",
+ (float) (totalposted) / timetaken);
+ printf(" %.2f kb/s total\n",
+ (float) (totalread + totalposted) / timetaken);
+ }
}
{
- /* work out connection times */
- int i;
- int totalcon = 0, total = 0;
- int mincon = 9999999, mintot = 999999;
- int maxcon = 0, maxtot = 0;
-
- for (i = 0; i < requests; i++) {
- struct data s = stats[i];
- mincon = ap_min(mincon, s.ctime);
- mintot = ap_min(mintot, s.time);
- maxcon = ap_max(maxcon, s.ctime);
- maxtot = ap_max(maxtot, s.time);
- totalcon += s.ctime;
- total += s.time;
- }
- printf("\nConnnection Times (ms)\n");
- printf(" min avg max\n");
- printf("Connect: %5d %5d %5d\n", mincon, totalcon / requests, maxcon);
- printf("Processing: %5d %5d %5d\n",
- mintot - mincon, (total/requests) - (totalcon/requests),
- maxtot - maxcon);
- printf("Total: %5d %5d %5d\n", mintot, total / requests, maxtot);
+ /* work out connection times */
+ int i;
+ int totalcon = 0, total = 0;
+ int mincon = 9999999, mintot = 999999;
+ int maxcon = 0, maxtot = 0;
+
+ for (i = 0; i < requests; i++) {
+ struct data s = stats[i];
+ mincon = ap_min(mincon, s.ctime);
+ mintot = ap_min(mintot, s.time);
+ maxcon = ap_max(maxcon, s.ctime);
+ maxtot = ap_max(maxtot, s.time);
+ totalcon += s.ctime;
+ total += s.time;
+ }
+ if (requests > 0) { /* avoid division by zero (if 0 requests) */
+ printf("\nConnnection Times (ms)\n");
+ printf(" min avg max\n");
+ printf("Connect: %5d %5d %5d\n", mincon, totalcon / requests, maxcon);
+ printf("Processing: %5d %5d %5d\n",
+ mintot - mincon, (total / requests) - (totalcon / requests),
+ maxtot - maxcon);
+ printf("Total: %5d %5d %5d\n", mintot, total / requests, maxtot);
+ }
+ }
+}
+
+/* --------------------------------------------------------- */
+
+/* calculate and output results in HTML */
+
+static void output_html_results(void)
+{
+ int timetaken;
+
+ gettimeofday(&endtime, 0);
+ timetaken = timedif(endtime, start);
+
+ printf("\n\n<table %s>\n", tablestring);
+ printf("<tr %s><th colspan=2 %s>Server Software:</th>"
+ "<td colspan=2 %s>%s</td></tr>\n",
+ trstring, tdstring, tdstring, servername);
+ printf("<tr %s><th colspan=2 %s>Server Hostname:</th>"
+ "<td colspan=2 %s>%s</td></tr>\n",
+ trstring, tdstring, tdstring, hostname);
+ printf("<tr %s><th colspan=2 %s>Server Port:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, port);
+ printf("<tr %s><th colspan=2 %s>Document Path:</th>"
+ "<td colspan=2 %s>%s</td></tr>\n",
+ trstring, tdstring, tdstring, path);
+ printf("<tr %s><th colspan=2 %s>Document Length:</th>"
+ "<td colspan=2 %s>%d bytes</td></tr>\n",
+ trstring, tdstring, tdstring, doclen);
+ printf("<tr %s><th colspan=2 %s>Concurrency Level:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, concurrency);
+ printf("<tr %s><th colspan=2 %s>Time taken for tests:</th>"
+ "<td colspan=2 %s>%d.%03d seconds</td></tr>\n",
+ trstring, tdstring, tdstring, timetaken / 1000, timetaken % 1000);
+ printf("<tr %s><th colspan=2 %s>Complete requests:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, done);
+ printf("<tr %s><th colspan=2 %s>Failed requests:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, bad);
+ if (bad)
+ printf("<tr %s><td colspan=4 %s > (Connect: %d, Length: %d, Exceptions: %d)</td></tr>\n",
+ trstring, tdstring, err_conn, err_length, err_except);
+ if (err_response)
+ printf("<tr %s><th colspan=2 %s>Non-2xx responses:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, err_response);
+ if (keepalive)
+ printf("<tr %s><th colspan=2 %s>Keep-Alive requests:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, doneka);
+ printf("<tr %s><th colspan=2 %s>Total transferred:</th>"
+ "<td colspan=2 %s>%d bytes</td></tr>\n",
+ trstring, tdstring, tdstring, totalread);
+ if (posting)
+ printf("<tr %s><th colspan=2 %s>Total POSTed:</th>"
+ "<td colspan=2 %s>%d</td></tr>\n",
+ trstring, tdstring, tdstring, totalposted);
+ printf("<tr %s><th colspan=2 %s>HTML transferred:</th>"
+ "<td colspan=2 %s>%d bytes</td></tr>\n",
+ trstring, tdstring, tdstring, totalbread);
+
+ /* avoid divide by zero */
+ if (timetaken) {
+ printf("<tr %s><th colspan=2 %s>Requests per second:</th>"
+ "<td colspan=2 %s>%.2f</td></tr>\n",
+ trstring, tdstring, tdstring, 1000 * (float) (done) / timetaken);
+ printf("<tr %s><th colspan=2 %s>Transfer rate:</th>"
+ "<td colspan=2 %s>%.2f kb/s received</td></tr>\n",
+ trstring, tdstring, tdstring, (float) (totalread) / timetaken);
+ if (posting) {
+ printf("<tr %s><td colspan=2 %s>&nbsp;</td>"
+ "<td colspan=2 %s>%.2f kb/s sent</td></tr>\n",
+ trstring, tdstring, tdstring,
+ (float) (totalposted) / timetaken);
+ printf("<tr %s><td colspan=2 %s>&nbsp;</td>"
+ "<td colspan=2 %s>%.2f kb/s total</td></tr>\n",
+ trstring, tdstring, tdstring,
+ (float) (totalread + totalposted) / timetaken);
+ }
+ }
+
+ {
+ /* work out connection times */
+ int i;
+ int totalcon = 0, total = 0;
+ int mincon = 9999999, mintot = 999999;
+ int maxcon = 0, maxtot = 0;
+
+ for (i = 0; i < requests; i++) {
+ struct data s = stats[i];
+ mincon = ap_min(mincon, s.ctime);
+ mintot = ap_min(mintot, s.time);
+ maxcon = ap_max(maxcon, s.ctime);
+ maxtot = ap_max(maxtot, s.time);
+ totalcon += s.ctime;
+ total += s.time;
+ }
+
+ if (requests > 0) { /* avoid division by zero (if 0 requests) */
+ printf("<tr %s><th %s colspan=4>Connnection Times (ms)</th></tr>\n",
+ trstring, tdstring);
+ printf("<tr %s><th %s>&nbsp;</th> <th %s>min</th> <th %s>avg</th> <th %s>max</th></tr>\n",
+ trstring, tdstring, tdstring, tdstring, tdstring);
+ printf("<tr %s><th %s>Connect:</th>"
+ "<td %s>%5d</td>"
+ "<td %s>%5d</td>"
+ "<td %s>%5d</td></tr>\n",
+ trstring, tdstring, tdstring, mincon, tdstring, totalcon / requests, tdstring, maxcon);
+ printf("<tr %s><th %s>Processing:</th>"
+ "<td %s>%5d</td>"
+ "<td %s>%5d</td>"
+ "<td %s>%5d</td></tr>\n",
+ trstring, tdstring, tdstring, mintot - mincon, tdstring,
+ (total / requests) - (totalcon / requests), tdstring, maxtot - maxcon);
+ printf("<tr %s><th %s>Total:</th>"
+ "<td %s>%5d</td>"
+ "<td %s>%5d</td>"
+ "<td %s>%5d</td></tr>\n",
+ trstring, tdstring, tdstring, mintot, tdstring, total / requests, tdstring, maxtot);
+ }
+ printf("</table>\n");
}
}
/* --------------------------------------------------------- */
-/* start asynchronous non-blocking connection */
+/* start asnchronous non-blocking connection */
-static void start_connect(struct connection *c)
+static void start_connect(struct connection * c)
{
c->read = 0;
c->bread = 0;
@@ -351,25 +514,25 @@ static void start_connect(struct connection *c)
c->fd = socket(AF_INET, SOCK_STREAM, 0);
if (c->fd < 0)
- err("socket");
+ err("socket");
nonblock(c->fd);
gettimeofday(&c->start, 0);
- if (connect(c->fd, (struct sockaddr *) &server, sizeof(server)) < 0) {
- if (errno == EINPROGRESS) {
- c->state = STATE_CONNECTING;
- FD_SET(c->fd, &writebits);
- return;
- }
- else {
- close(c->fd);
- err_conn++;
- if (bad++ > 10) {
- err("\nTest aborted after 10 failures\n\n");
- }
- start_connect(c);
- }
+ if (connect(c->fd, (struct sockaddr *) & server, sizeof(server)) < 0) {
+ if (errno == EINPROGRESS) {
+ c->state = STATE_CONNECTING;
+ FD_SET(c->fd, &writebits);
+ return;
+ }
+ else {
+ close(c->fd);
+ err_conn++;
+ if (bad++ > 10) {
+ err("\nTest aborted after 10 failures\n\n");
+ }
+ start_connect(c);
+ }
}
/* connected first time */
@@ -380,31 +543,31 @@ static void start_connect(struct connection *c)
/* close down connection and save stats */
-static void close_connection(struct connection *c)
+static void close_connection(struct connection * c)
{
if (c->read == 0 && c->keepalive) {
- /* server has legitimately shut down an idle keep alive request */
- good--; /* connection never happend */
+ /* server has legitimately shut down an idle keep alive request */
+ good--; /* connection never happend */
}
else {
- if (good == 1) {
- /* first time here */
- doclen = c->bread;
- }
- else if (c->bread != doclen) {
- bad++;
- err_length++;
- }
-
- /* save out time */
- if (done < requests) {
- struct data s;
- gettimeofday(&c->done, 0);
- s.read = c->read;
- s.ctime = timedif(c->connect, c->start);
- s.time = timedif(c->done, c->start);
- stats[done++] = s;
- }
+ if (good == 1) {
+ /* first time here */
+ doclen = c->bread;
+ }
+ else if (c->bread != doclen) {
+ bad++;
+ err_length++;
+ }
+
+ /* save out time */
+ if (done < requests) {
+ struct data s;
+ gettimeofday(&c->done, 0);
+ s.read = c->read;
+ s.ctime = timedif(c->connect, c->start);
+ s.time = timedif(c->done, c->start);
+ stats[done++] = s;
+ }
}
close(c->fd);
@@ -420,148 +583,154 @@ static void close_connection(struct connection *c)
/* read data from connection */
-static void read_connection(struct connection *c)
+static void read_connection(struct connection * c)
{
int r;
char *part;
- char respcode[4]; /* 3 digits and null */
+ char respcode[4]; /* 3 digits and null */
r = read(c->fd, buffer, sizeof(buffer));
if (r == 0 || (r < 0 && errno != EAGAIN)) {
- good++;
- close_connection(c);
- return;
+ good++;
+ close_connection(c);
+ return;
}
if (r < 0 && errno == EAGAIN)
- return;
+ return;
c->read += r;
totalread += r;
if (!c->gotheader) {
- char *s;
- int l = 4;
- int space = CBUFFSIZE - c->cbx - 1; /* -1 to allow for 0 terminator */
- int tocopy = (space < r) ? space : r;
+ char *s;
+ int l = 4;
+ int space = CBUFFSIZE - c->cbx - 1; /* -1 to allow for 0
+ * terminator */
+ int tocopy = (space < r) ? space : r;
#ifndef CHARSET_EBCDIC
- memcpy(c->cbuff + c->cbx, buffer, space);
-#else /*CHARSET_EBCDIC*/
- ascii2ebcdic(c->cbuff + c->cbx, buffer, space);
-#endif /*CHARSET_EBCDIC*/
- c->cbx += tocopy;
- space -= tocopy;
- c->cbuff[c->cbx] = 0; /* terminate for benefit of strstr */
+ memcpy(c->cbuff + c->cbx, buffer, tocopy);
+#else /* CHARSET_EBCDIC */
+ ascii2ebcdic(c->cbuff + c->cbx, buffer, tocopy);
+#endif /* CHARSET_EBCDIC */
+ c->cbx += tocopy;
+ space -= tocopy;
+ c->cbuff[c->cbx] = 0; /* terminate for benefit of strstr */
if (verbosity >= 4) {
printf("LOG: header received:\n%s\n", c->cbuff);
}
- s = strstr(c->cbuff, "\r\n\r\n");
- /* this next line is so that we talk to NCSA 1.5 which blatantly breaks
- the http specifaction */
- if (!s) {
- s = strstr(c->cbuff, "\n\n");
- l = 2;
- }
-
- if (!s) {
- /* read rest next time */
- if (space)
- return;
- else {
- /* header is in invalid or too big - close connection */
- close(c->fd);
- if (bad++ > 10) {
- err("\nTest aborted after 10 failures\n\n");
- }
- FD_CLR(c->fd, &writebits);
- start_connect(c);
- }
- }
- else {
- /* have full header */
- if (!good) {
- /* this is first time, extract some interesting info */
- char *p, *q;
- p = strstr(c->cbuff, "Server:");
- q = servername;
- if (p) {
- p += 8;
- while (*p > 32)
- *q++ = *p++;
- }
- *q = 0;
- }
-
- /* XXX: this parsing isn't even remotely HTTP compliant...
- * but in the interest of speed it doesn't totally have to be,
- * it just needs to be extended to handle whatever servers
- * folks want to test against. -djg */
-
- /* check response code */
- part = strstr(c->cbuff, "HTTP"); /* really HTTP/1.x_ */
- strncpy(respcode, (part+strlen("HTTP/1.x_")), 3);
+ s = strstr(c->cbuff, "\r\n\r\n");
+ /*
+ * this next line is so that we talk to NCSA 1.5 which blatantly
+ * breaks the http specification
+ */
+ if (!s) {
+ s = strstr(c->cbuff, "\n\n");
+ l = 2;
+ }
+
+ if (!s) {
+ /* read rest next time */
+ if (space)
+ return;
+ else {
+ /* header is in invalid or too big - close connection */
+ close(c->fd);
+ if (bad++ > 10) {
+ err("\nTest aborted after 10 failures\n\n");
+ }
+ FD_CLR(c->fd, &writebits);
+ start_connect(c);
+ }
+ }
+ else {
+ /* have full header */
+ if (!good) {
+ /* this is first time, extract some interesting info */
+ char *p, *q;
+ p = strstr(c->cbuff, "Server:");
+ q = servername;
+ if (p) {
+ p += 8;
+ while (*p > 32)
+ *q++ = *p++;
+ }
+ *q = 0;
+ }
+
+ /*
+ * XXX: this parsing isn't even remotely HTTP compliant... but in
+ * the interest of speed it doesn't totally have to be, it just
+ * needs to be extended to handle whatever servers folks want to
+ * test against. -djg
+ */
+
+ /* check response code */
+ part = strstr(c->cbuff, "HTTP"); /* really HTTP/1.x_ */
+ strncpy(respcode, (part + strlen("HTTP/1.x_")), 3);
respcode[3] = '\0';
- if (respcode[0] != '2') {
- err_response++;
- if (verbosity >= 2) printf ("WARNING: Response code not 2xx (%s)\n", respcode);
- }
+ if (respcode[0] != '2') {
+ err_response++;
+ if (verbosity >= 2)
+ printf("WARNING: Response code not 2xx (%s)\n", respcode);
+ }
else if (verbosity >= 3) {
- printf("LOG: Response code = %s\n", respcode);
- }
-
- c->gotheader = 1;
- *s = 0; /* terminate at end of header */
- if (keepalive &&
- (strstr(c->cbuff, "Keep-Alive")
- || strstr(c->cbuff, "keep-alive"))) { /* for benefit of MSIIS */
- char *cl;
- cl = strstr(c->cbuff, "Content-Length:");
- /* handle NCSA, which sends Content-length: */
- if (!cl)
- cl = strstr(c->cbuff, "Content-length:");
- if (cl) {
- c->keepalive = 1;
- c->length = atoi(cl + 16);
- }
- }
- c->bread += c->cbx - (s + l - c->cbuff) + r - tocopy;
- totalbread += c->bread;
- }
+ printf("LOG: Response code = %s\n", respcode);
+ }
+
+ c->gotheader = 1;
+ *s = 0; /* terminate at end of header */
+ if (keepalive &&
+ (strstr(c->cbuff, "Keep-Alive")
+ || strstr(c->cbuff, "keep-alive"))) { /* for benefit of MSIIS */
+ char *cl;
+ cl = strstr(c->cbuff, "Content-Length:");
+ /* handle NCSA, which sends Content-length: */
+ if (!cl)
+ cl = strstr(c->cbuff, "Content-length:");
+ if (cl) {
+ c->keepalive = 1;
+ c->length = atoi(cl + 16);
+ }
+ }
+ c->bread += c->cbx - (s + l - c->cbuff) + r - tocopy;
+ totalbread += c->bread;
+ }
}
else {
- /* outside header, everything we have read is entity body */
- c->bread += r;
- totalbread += r;
+ /* outside header, everything we have read is entity body */
+ c->bread += r;
+ totalbread += r;
}
if (c->keepalive && (c->bread >= c->length)) {
- /* finished a keep-alive connection */
- good++;
- doneka++;
- /* save out time */
- if (good == 1) {
- /* first time here */
- doclen = c->bread;
- }
- else if (c->bread != doclen) {
- bad++;
- err_length++;
- }
- if (done < requests) {
- struct data s;
- gettimeofday(&c->done, 0);
- s.read = c->read;
- s.ctime = timedif(c->connect, c->start);
- s.time = timedif(c->done, c->start);
- stats[done++] = s;
- }
- c->keepalive = 0;
- c->length = 0;
- c->gotheader = 0;
- c->cbx = 0;
- c->read = c->bread = 0;
- write_request(c);
- c->start = c->connect; /* zero connect time with keep-alive */
+ /* finished a keep-alive connection */
+ good++;
+ doneka++;
+ /* save out time */
+ if (good == 1) {
+ /* first time here */
+ doclen = c->bread;
+ }
+ else if (c->bread != doclen) {
+ bad++;
+ err_length++;
+ }
+ if (done < requests) {
+ struct data s;
+ gettimeofday(&c->done, 0);
+ s.read = c->read;
+ s.ctime = timedif(c->connect, c->start);
+ s.time = timedif(c->done, c->start);
+ stats[done++] = s;
+ }
+ c->keepalive = 0;
+ c->length = 0;
+ c->gotheader = 0;
+ c->cbx = 0;
+ c->read = c->bread = 0;
+ write_request(c);
+ c->start = c->connect; /* zero connect time with keep-alive */
}
}
@@ -575,18 +744,20 @@ static void test(void)
fd_set sel_read, sel_except, sel_write;
int i;
- printf("Benchmarking %s (be patient)...", hostname);
- fflush(stdout);
+ if (!use_html) {
+ printf("Benchmarking %s (be patient)...", hostname);
+ fflush(stdout);
+ }
{
- /* get server information */
- struct hostent *he;
- he = gethostbyname(hostname);
- if (!he)
- err("bad hostname");
- server.sin_family = he->h_addrtype;
- server.sin_port = htons(port);
- server.sin_addr.s_addr = ((unsigned long *) (he->h_addr_list[0]))[0];
+ /* get server information */
+ struct hostent *he;
+ he = gethostbyname(hostname);
+ if (!he)
+ err("bad hostname");
+ server.sin_family = he->h_addrtype;
+ server.sin_port = htons(port);
+ server.sin_addr.s_addr = ((unsigned long *) (he->h_addr_list[0]))[0];
}
con = malloc(concurrency * sizeof(struct connection));
@@ -600,96 +771,111 @@ static void test(void)
/* setup request */
if (!posting) {
sprintf(request, "GET %s HTTP/1.0\r\n"
- "User-Agent: ApacheBench/%s\r\n"
- "%s"
- "Host: %s\r\n"
- "Accept: */*\r\n"
- "\r\n",
- path,
- VERSION,
- keepalive ? "Connection: Keep-Alive\r\n" : "",
- hostname);
+ "User-Agent: ApacheBench/%s\r\n"
+ "%s" "%s" "%s"
+ "Host: %s\r\n"
+ "Accept: */*\r\n"
+ "\r\n" "%s",
+ path,
+ VERSION,
+ keepalive ? "Connection: Keep-Alive\r\n" : "",
+ cookie, auth, hostname, hdrs);
}
else {
sprintf(request, "POST %s HTTP/1.0\r\n"
- "User-Agent: ApacheBench/%s\r\n"
- "%s"
- "Host: %s\r\n"
- "Accept: */*\r\n"
- "Content-length: %d\r\n"
- "Content-type: %s\r\n"
- "\r\n",
- path,
- VERSION,
- keepalive ? "Connection: Keep-Alive\r\n" : "",
- hostname, postlen,
- (content_type[0]) ? content_type : "text/plain");
+ "User-Agent: ApacheBench/%s\r\n"
+ "%s" "%s" "%s"
+ "Host: %s\r\n"
+ "Accept: */*\r\n"
+ "Content-length: %d\r\n"
+ "Content-type: %s\r\n"
+ "%s"
+ "\r\n",
+ path,
+ VERSION,
+ keepalive ? "Connection: Keep-Alive\r\n" : "",
+ cookie, auth,
+ hostname, postlen,
+ (content_type[0]) ? content_type : "text/plain", hdrs);
}
- if (verbosity >= 2) printf("INFO: POST header == \n---\n%s\n---\n", request);
+ if (verbosity >= 2)
+ printf("INFO: POST header == \n---\n%s\n---\n", request);
reqlen = strlen(request);
#ifdef CHARSET_EBCDIC
ebcdic2ascii(request, request, reqlen);
-#endif /*CHARSET_EBCDIC*/
+#endif /* CHARSET_EBCDIC */
/* ok - lets start */
gettimeofday(&start, 0);
/* initialise lots of requests */
for (i = 0; i < concurrency; i++)
- start_connect(&con[i]);
+ start_connect(&con[i]);
while (done < requests) {
- int n;
- /* setup bit arrays */
- memcpy(&sel_except, &readbits, sizeof(readbits));
- memcpy(&sel_read, &readbits, sizeof(readbits));
- memcpy(&sel_write, &writebits, sizeof(readbits));
-
- /* check for time limit expiry */
- gettimeofday(&now, 0);
- if (tlimit && timedif(now, start) > (tlimit * 1000)) {
- requests = done; /* so stats are correct */
- }
-
- /* Timeout of 30 seconds. */
- timeout.tv_sec = 30;
- timeout.tv_usec = 0;
- n = ap_select(FD_SETSIZE, &sel_read, &sel_write, &sel_except, &timeout);
- if (!n) {
- err("\nServer timed out\n\n");
- }
- if (n < 1)
- err("select");
-
- for (i = 0; i < concurrency; i++) {
- int s = con[i].fd;
- if (FD_ISSET(s, &sel_except)) {
- bad++;
- err_except++;
- start_connect(&con[i]);
- continue;
- }
- if (FD_ISSET(s, &sel_read))
- read_connection(&con[i]);
- if (FD_ISSET(s, &sel_write))
- write_request(&con[i]);
- }
+ int n;
+ /* setup bit arrays */
+ memcpy(&sel_except, &readbits, sizeof(readbits));
+ memcpy(&sel_read, &readbits, sizeof(readbits));
+ memcpy(&sel_write, &writebits, sizeof(readbits));
+
+ /* check for time limit expiry */
+ gettimeofday(&now, 0);
+ if (tlimit && timedif(now, start) > (tlimit * 1000)) {
+ requests = done; /* so stats are correct */
+ }
+
+ /* Timeout of 30 seconds. */
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+ n = ap_select(FD_SETSIZE, &sel_read, &sel_write, &sel_except, &timeout);
+ if (!n) {
+ err("\nServer timed out\n\n");
+ }
+ if (n < 1)
+ err("select");
+
+ for (i = 0; i < concurrency; i++) {
+ int s = con[i].fd;
+ if (FD_ISSET(s, &sel_except)) {
+ bad++;
+ err_except++;
+ start_connect(&con[i]);
+ continue;
+ }
+ if (FD_ISSET(s, &sel_read))
+ read_connection(&con[i]);
+ if (FD_ISSET(s, &sel_write))
+ write_request(&con[i]);
+ }
}
- output_results();
+ if (use_html)
+ output_html_results();
+ else
+ output_results();
}
/* ------------------------------------------------------- */
/* display copyright information */
-static void copyright(void)
+static void copyright(void)
{
- printf("This is ApacheBench, Version %s\n", VERSION);
- printf("Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n");
- printf("Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/\n");
- printf("\n");
+ if (!use_html) {
+ printf("This is ApacheBench, Version %s\n", VERSION);
+ printf("Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n");
+ printf("Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/\n");
+ printf("\n");
+ }
+ else {
+ printf("<p>\n");
+ printf(" This is ApacheBench, Version %s<br>\n", VERSION);
+ printf(" Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br>\n");
+ printf(" Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/<br>\n");
+ printf("</p>\n<p>\n");
+ }
}
/* display usage information */
@@ -703,6 +889,17 @@ static void usage(char *progname)
fprintf(stderr, " -p postfile File containg data to POST\n");
fprintf(stderr, " -T content-type Content-type header for POSTing\n");
fprintf(stderr, " -v verbosity How much troubleshooting info to print\n");
+ fprintf(stderr, " -w Print out results in HTML tables\n");
+ fprintf(stderr, " -x attributes String to insert as table attributes\n");
+ fprintf(stderr, " -y attributes String to insert as tr attributes\n");
+ fprintf(stderr, " -z attributes String to insert as td or th attributes\n");
+ fprintf(stderr, " -C attribute Add cookie, eg. 'Apache=1234. (repeatable)\n");
+ fprintf(stderr, " -H attribute Add Arbitrary header line, eg. 'Accept-Encoding: zop'\n");
+ fprintf(stderr, " Inserted after all normal header lines. (repeatable)\n");
+ fprintf(stderr, " -A attribute Add Basic WWW Authentication, the attributes\n");
+ fprintf(stderr, " are a colon separated username and password.\n");
+ fprintf(stderr, " -p attribute Add Basic Proxy Authentication, the attributes\n");
+ fprintf(stderr, " are a colon separated username and password.\n");
fprintf(stderr, " -V Print version number and exit\n");
fprintf(stderr, " -k Use HTTP KeepAlive feature\n");
fprintf(stderr, " -h Display usage information (this message)\n");
@@ -719,21 +916,21 @@ static int parse_url(char *url)
char *h;
char *p = NULL;
- if (strlen(url) > 7 && strncmp(url, "http://", 7) == 0)
- url += 7;
+ if (strlen(url) > 7 && strncmp(url, "http://", 7) == 0)
+ url += 7;
h = url;
if ((cp = strchr(url, ':')) != NULL) {
- *cp++ = '\0';
- p = cp;
- url = cp;
+ *cp++ = '\0';
+ p = cp;
+ url = cp;
}
if ((cp = strchr(url, '/')) == NULL)
- return 1;
+ return 1;
strcpy(path, cp);
*cp = '\0';
strcpy(hostname, h);
if (p != NULL)
- port = atoi(p);
+ port = atoi(p);
return 0;
}
@@ -747,21 +944,21 @@ static int open_postfile(char *pfile)
struct stat postfilestat;
if ((postfd = open(pfile, O_RDONLY)) == -1) {
- printf("Invalid postfile name (%s)\n", pfile);
- return errno;
+ printf("Invalid postfile name (%s)\n", pfile);
+ return errno;
}
if ((status = fstat(postfd, &postfilestat)) == -1) {
- perror("Can\'t stat postfile\n");
- return status;
+ perror("Can\'t stat postfile\n");
+ return status;
}
postdata = malloc(postfilestat.st_size);
if (!postdata) {
- printf("Can\'t alloc postfile buffer\n");
- return ENOMEM;
+ printf("Can\'t alloc postfile buffer\n");
+ return ENOMEM;
}
if (read(postfd, postdata, postfilestat.st_size) != postfilestat.st_size) {
- printf("error reading postfilen");
- return EIO;
+ printf("error reading postfilen");
+ return EIO;
}
postlen = postfilestat.st_size;
return 0;
@@ -775,61 +972,125 @@ extern int optind, opterr, optopt;
/* sort out command-line args and call test */
int main(int argc, char **argv)
{
- int c, r;
+ int c, r,l;
+ char tmp[1024];
+
+ /* table defaults */
+ tablestring = "";
+ trstring = "";
+ tdstring = "bgcolor=white";
+ cookie[0] = '\0';
+ auth[0] = '\0';
+ hdrs[0] = '\0';
optind = 1;
- while ((c = getopt(argc, argv, "n:c:t:T:p:v:kVh")) > 0) {
- switch (c) {
- case 'n':
- requests = atoi(optarg);
- if (!requests) {
- err("Invalid number of requests\n");
- }
- break;
- case 'k':
- keepalive = 1;
- break;
- case 'c':
- concurrency = atoi(optarg);
- break;
- case 'p':
- if (0 == (r = open_postfile(optarg))) {
- posting = 1;
- }
+ while ((c = getopt(argc, argv, "n:c:t:T:p:v:kVhwx:y:z:C:H:P:A:")) > 0) {
+ switch (c) {
+ case 'n':
+ requests = atoi(optarg);
+ if (!requests) {
+ err("Invalid number of requests\n");
+ }
+ break;
+ case 'k':
+ keepalive = 1;
+ break;
+ case 'c':
+ concurrency = atoi(optarg);
+ break;
+ case 'p':
+ if (0 == (r = open_postfile(optarg))) {
+ posting = 1;
+ }
else if (postdata) {
- exit(r);
+ exit(r);
}
- break;
- case 'v':
- verbosity = atoi(optarg);
- break;
- case 't':
- tlimit = atoi(optarg);
- requests = MAX_REQUESTS; /* need to size data array on something */
- break;
- case 'T':
- strcpy(content_type, optarg);
- break;
- case 'V':
- copyright();
- exit(0);
- break;
- case 'h':
- usage(argv[0]);
- break;
- default:
- fprintf(stderr, "%s: invalid option `%c'\n", argv[0], c);
- usage(argv[0]);
- break;
- }
+ break;
+ case 'v':
+ verbosity = atoi(optarg);
+ break;
+ case 't':
+ tlimit = atoi(optarg);
+ requests = MAX_REQUESTS; /* need to size data array on
+ * something */
+ break;
+ case 'T':
+ strcpy(content_type, optarg);
+ break;
+ case 'C':
+ strncat(cookie, "Cookie: ", sizeof(cookie));
+ strncat(cookie, optarg, sizeof(cookie));
+ strncat(cookie, "\r\n", sizeof(cookie));
+ break;
+ case 'A':
+ /* assume username passwd already to be in colon separated form. Ready
+ * to be uu-encoded.
+ */
+ while(isspace(*optarg))
+ optarg++;
+ l=ap_base64encode(tmp,optarg,strlen(optarg));
+ tmp[l]='\0';
+
+ strncat(auth, "Authorization: basic ", sizeof(auth));
+ strncat(auth, tmp, sizeof(auth));
+ strncat(auth, "\r\n", sizeof(auth));
+ break;
+ case 'P':
+ /*
+ * assume username passwd already to be in colon separated form.
+ */
+ while(isspace(*optarg))
+ optarg++;
+ l=ap_base64encode(tmp,optarg,strlen(optarg));
+ tmp[l]='\0';
+
+ strncat(auth, "Proxy-Authorization: basic ", sizeof(auth));
+ strncat(auth, tmp, sizeof(auth));
+ strncat(auth, "\r\n", sizeof(auth));
+ break;
+ case 'H':
+ strncat(hdrs, optarg, sizeof(hdrs));
+ strncat(hdrs, "\r\n", sizeof(hdrs));
+ break;
+ case 'V':
+ copyright();
+ exit(0);
+ break;
+ case 'w':
+ use_html = 1;
+ break;
+ /*
+ * if any of the following three are used, turn on html output
+ * automatically
+ */
+ case 'x':
+ use_html = 1;
+ tablestring = optarg;
+ break;
+ case 'y':
+ use_html = 1;
+ trstring = optarg;
+ break;
+ case 'z':
+ use_html = 1;
+ tdstring = optarg;
+ break;
+ case 'h':
+ usage(argv[0]);
+ break;
+ default:
+ fprintf(stderr, "%s: invalid option `%c'\n", argv[0], c);
+ usage(argv[0]);
+ break;
+ }
}
- if (optind != argc-1) {
- fprintf(stderr, "%s: wrong number of arguments\n", argv[0]);
- usage(argv[0]);
+ if (optind != argc - 1) {
+ fprintf(stderr, "%s: wrong number of arguments\n", argv[0]);
+ usage(argv[0]);
}
if (parse_url(argv[optind++])) {
- fprintf(stderr, "%s: invalid URL\n", argv[0]);
- usage(argv[0]);
+ fprintf(stderr, "%s: invalid URL\n", argv[0]);
+ usage(argv[0]);
}
copyright();
@@ -837,4 +1098,3 @@ int main(int argc, char **argv)
exit(0);
}
-
diff --git a/usr.sbin/httpd/src/support/apachectl b/usr.sbin/httpd/src/support/apachectl
index a3ea6fdc695..5b176d9d1a0 100644
--- a/usr.sbin/httpd/src/support/apachectl
+++ b/usr.sbin/httpd/src/support/apachectl
@@ -50,7 +50,7 @@ do
# check for pidfile
if [ -f $PIDFILE ] ; then
PID=`cat $PIDFILE`
- if kill -0 $PID; then
+ if [ "x$PID" != "x" ] && kill -0 $PID 2>/dev/null ; then
STATUS="httpd (pid $PID) running"
RUNNING=1
else
diff --git a/usr.sbin/httpd/src/support/apachectl.1 b/usr.sbin/httpd/src/support/apachectl.8
index ebda1bc256b..72300eb98b2 100644
--- a/usr.sbin/httpd/src/support/apachectl.1
+++ b/usr.sbin/httpd/src/support/apachectl.8
@@ -6,7 +6,7 @@
.\" are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
+.\" notice, this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in
@@ -54,30 +54,30 @@
.SH NAME
apachectl \- Apache HTTP server control interface
.SH SYNOPSIS
-.B apachectl
+.B apachectl
\fIcommand\fP [...]
.SH DESCRIPTION
.B apachectl
-is a front end to the Apache HyperText Transfer Protocol (HTTP)
-server. It is designed to help the administrator control the
-functioning of the Apache
+is a front end to the Apache HyperText Transfer Protocol (HTTP)
+server. It is designed to help the administrator control the
+functioning of the Apache
.B httpd
-daemon.
+daemon.
.PP
-.B NOTE:
-If your Apache installation uses non-standard paths, you will need to
-edit the
+.B NOTE:
+If your Apache installation uses non-standard paths, you will need to
+edit the
.B apachectl
-script to set the appropriate paths to your PID file and your
+script to set the appropriate paths to your PID file and your
.B httpd
binary. See the comments in the script for details.
.PP
-The
+The
.B apachectl
-script returns a 0 exit value on success, and >0 if an error
+script returns a 0 exit value on success, and >0 if an error
occurs. For more details, view the comments in the script.
.PP
-Full documentation for Apache is available at
+Full documentation for Apache is available at
.B http://www.apache.org/
.
.SH OPTIONS
@@ -92,14 +92,14 @@ Stops the Apache daemon.
.BI restart
Restarts the Apache daemon by sending it a SIGHUP. If the daemon
is not running, it is started.
-This command automatically checks the configuration files via
+This command automatically checks the configuration files via
.BI configtest
before initiating the restart to make sure Apache doesn't die.
.TP
.BI fullstatus
-Displays a full status report from
-.B mod_status.
-For this to work, you need to have mod_status enabled on your server
+Displays a full status report from
+.B mod_status.
+For this to work, you need to have mod_status enabled on your server
and a text-based browser such as \fIlynx\fP available on your system. The
URL used to access the status report can be set by editing the
.B STATUSURL
@@ -116,13 +116,13 @@ normal restart in that currently open connections are not aborted.
A side effect is that old log files will not be closed immediately.
This means that if used in a log rotation script, a substantial delay may be
necessary to ensure that the old log files are closed before processing them.
-This command automatically checks the configuration files via
+This command automatically checks the configuration files via
.BI configtest
before initiating the restart to make sure Apache doesn't die.
.TP
.BI configtest
Run a configuration file syntax test. It parses the configuration
-files and either reports
+files and either reports
.B "Syntax Ok"
or detailed information about the particular syntax error.
.TP
diff --git a/usr.sbin/httpd/src/support/apxs.8 b/usr.sbin/httpd/src/support/apxs.8
index 3c4c6a53792..464766c75fe 100644
--- a/usr.sbin/httpd/src/support/apxs.8
+++ b/usr.sbin/httpd/src/support/apxs.8
@@ -6,7 +6,7 @@
.\" are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
+.\" notice, this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in
@@ -56,15 +56,24 @@ apxs \- APache eXtenSion tool
.SH SYNOPSIS
.B apxs
.B \-g
+[
+.BI \-S " name=value
+]
.BI \-n " modname"
.B apxs
.B \-q
+[
+.BI \-S " name=value
+]
.IR query " ..."
.B apxs
.B \-c
[
+.BI \-S " name=value
+]
+[
.BI \-o " dsofile"
]
[
@@ -90,6 +99,25 @@ apxs \- APache eXtenSion tool
.B apxs
.B \-i
[
+.BI \-S " name=value
+]
+[
+.BI \-n " modname"
+]
+[
+.B \-a
+]
+[
+.B \-A
+]
+.IR dsofile " ..."
+
+.B apxs
+.B \-e
+[
+.BI \-S " name=value
+]
+[
.BI \-n " modname"
]
[
@@ -159,7 +187,7 @@ even a library archive (.a). The
tool automatically recognizes these extensions and automtaically used the C
source files for compilation while just using the object and archive files for
the linking phase. But when using such pre-compiled objects make sure they are
-compiled for position independent code (PIC) to be able to use them for a
+compiled for position independend code (PIC) to be able to use them for a
dynamically loaded shared object.
For instance with GCC you always just have to use
.BR -fpic .
@@ -198,18 +226,18 @@ by guessing it from the filename.
.PP
Query options:
.TP 12
-.B \-q
-Performs a query for
+.B \-q
+Performs a query for
.BR apxs 's
knowledge about certain settings. The
.I query
parameters can be one or more of the following strings:
.nf
CC TARGET
- CFLAGS SBINDIR
- CFLAGS_SHLIB INCLUDEDIR
- LD_SHLIB LIBEXECDIR
- LDFLAGS_SHLIB SYSCONFDIR
+ CFLAGS SBINDIR
+ CFLAGS_SHLIB INCLUDEDIR
+ LD_SHLIB LIBEXECDIR
+ LDFLAGS_SHLIB SYSCONFDIR
LIBS_SHLIB
.fi
Use this for manually determining settings. For instance use
@@ -219,6 +247,11 @@ Use this for manually determining settings. For instance use
inside your own Makefiles if you need manual access
to Apache's C header files.
.PP
+Configuration options:
+.TP 12
+.BI \-S " name=value"
+This option changes the apxs settings described above.
+.PP
Template Generation options:
.TP 12
.B \-g
@@ -278,42 +311,51 @@ This option is directly passed through to the linker command.
Use this to add your own libraries to search to the build process.
.TP 12
.BI \-Wc, "compiler-flags"
-This option passes
+This option passes
.I compiler-flags
as additional flags to the compiler command.
Use this to add local compiler-specific options.
.TP 12
.BI \-Wl, "linker-flags"
-This option passes
+This option passes
.I linker-flags
as additional flags to the linker command.
Use this to add local linker-specific options.
.PP
-DSO installation options:
+DSO installation and configuration options:
.TP 12
.B \-i
This indicates the installation operation and installs one or more
dynamically shared objects into the
-servers
+server's
.I libexec
directory.
.TP 12
.B \-a
-This additionally activates the module
-by automatically adding a corresponding
+This activates the module by automatically adding a corresponding
.B LoadModule
line to Apache's
.B httpd.conf
-configuration file (only if still no such entry exists).
+configuration file, or by enabling it if it already exists.
.TP 12
.B \-A
Same as option
.B \-a
-but the created
+but the created
.B LoadModule
-directive is
-prefixed with a hash sign (#), i.e. the module is
-just prepared for later activation but initially disabled.
+directive is prefixed with a hash sign (#), i.e. the module is
+just prepared for later activation but initially disabled.
+.TP 12
+.B \-e
+This indicates the editing operation, which can be used with the
+.B \-a
+and
+.B \-A
+options similarly to the
+.B \-i
+operation to edit Apache's
+.B httpd.conf
+configuration file without attempting to install the module.
.PD
.SH EXAMPLES
Assume you have an Apache module named mod_foo.c available which should extend
diff --git a/usr.sbin/httpd/src/support/apxs.pl b/usr.sbin/httpd/src/support/apxs.pl
index f08450cdab4..c9c5ea85ef5 100644
--- a/usr.sbin/httpd/src/support/apxs.pl
+++ b/usr.sbin/httpd/src/support/apxs.pl
@@ -68,18 +68,18 @@ package apxs;
## Configuration
##
-my $CFG_TARGET = '@TARGET@'; # substituted via Makefile.tmpl
-my $CFG_CC = '@CC@'; # substituted via Makefile.tmpl
-my $CFG_CFLAGS = '@CFLAGS@'; # substituted via Makefile.tmpl
-my $CFG_CFLAGS_SHLIB = '@CFLAGS_SHLIB@'; # substituted via Makefile.tmpl
-my $CFG_LD_SHLIB = '@LD_SHLIB@'; # substituted via Makefile.tmpl
-my $CFG_LDFLAGS_SHLIB = '@LDFLAGS_SHLIB@'; # substituted via Makefile.tmpl
-my $CFG_LIBS_SHLIB = '@LIBS_SHLIB@'; # substituted via Makefile.tmpl
-my $CFG_PREFIX = '@prefix@'; # substituted via APACI install
-my $CFG_SBINDIR = '@sbindir@'; # substituted via APACI install
-my $CFG_INCLUDEDIR = '@includedir@'; # substituted via APACI install
-my $CFG_LIBEXECDIR = '@libexecdir@'; # substituted via APACI install
-my $CFG_SYSCONFDIR = '@sysconfdir@'; # substituted via APACI install
+my $CFG_TARGET = '@TARGET@'; # substituted via Makefile.tmpl
+my $CFG_CC = '@CC@'; # substituted via Makefile.tmpl
+my $CFG_CFLAGS = '@CFLAGS@'; # substituted via Makefile.tmpl
+my $CFG_CFLAGS_SHLIB = '@CFLAGS_SHLIB@'; # substituted via Makefile.tmpl
+my $CFG_LD_SHLIB = '@LD_SHLIB@'; # substituted via Makefile.tmpl
+my $CFG_LDFLAGS_SHLIB = '@LDFLAGS_MOD_SHLIB@'; # substituted via Makefile.tmpl
+my $CFG_LIBS_SHLIB = '@LIBS_SHLIB@'; # substituted via Makefile.tmpl
+my $CFG_PREFIX = '@prefix@'; # substituted via APACI install
+my $CFG_SBINDIR = '@sbindir@'; # substituted via APACI install
+my $CFG_INCLUDEDIR = '@includedir@'; # substituted via APACI install
+my $CFG_LIBEXECDIR = '@libexecdir@'; # substituted via APACI install
+my $CFG_SYSCONFDIR = '@sysconfdir@'; # substituted via APACI install
##
## Cleanup the above stuff
@@ -91,6 +91,10 @@ $CFG_CFLAGS =~ s|\s+`.+apaci`||;
##
## Initial shared object support check
##
+if (not -x "$CFG_SBINDIR/$CFG_TARGET") {
+ print STDERR "apxs:Error: $CFG_SBINDIR/$CFG_TARGET not found or not executable\n";
+ exit(1);
+}
if (not grep(/mod_so/, `$CFG_SBINDIR/$CFG_TARGET -l`)) {
print STDERR "apxs:Error: Sorry, no shared object support for Apache\n";
print STDERR "apxs:Error: available under your platform. Make sure\n";
@@ -113,6 +117,8 @@ my @opt_I = ();
my @opt_L = ();
my @opt_l = ();
my @opt_W = ();
+my @opt_S = ();
+my $opt_e = 0;
my $opt_i = 0;
my $opt_a = 0;
my $opt_A = 0;
@@ -184,27 +190,49 @@ sub Getopts {
}
sub usage {
- print STDERR "Usage: apxs -g -n <modname>\n";
- print STDERR " apxs -q <query> ...\n";
- print STDERR " apxs -c [-o <dsofile>] [-D <name>[=<value>]] [-I <incdir>]\n";
- print STDERR " [-L <libdir>] [-l <libname>] [-Wc,<flags>] [-Wl,<flags>]\n";
- print STDERR " <files> ...\n";
- print STDERR " apxs -i [-a] [-A] [-n <modname>] <dsofile> ...\n";
+ print STDERR "Usage: apxs -g [-S <var>=<val>] -n <modname>\n";
+ print STDERR " apxs -q [-S <var>=<val>] <query> ...\n";
+ print STDERR " apxs -c [-S <var>=<val>] [-o <dsofile>] [-D <name>[=<value>]]\n";
+ print STDERR " [-I <incdir>] [-L <libdir>] [-l <libname>] [-Wc,<flags>]\n";
+ print STDERR " [-Wl,<flags>] <files> ...\n";
+ print STDERR " apxs -i [-S <var>=<val>] [-a] [-A] [-n <modname>] <dsofile> ...\n";
+ print STDERR " apxs -e [-S <var>=<val>] [-a] [-A] [-n <modname>] <dsofile> ...\n";
exit(1);
}
# option handling
my $rc;
-($rc, @ARGV) = &Getopts("qn:gco:I+D+L+l+W+iaA", @ARGV);
+($rc, @ARGV) = &Getopts("qn:gco:I+D+L+l+W+S+eiaA", @ARGV);
&usage if ($rc == 0);
&usage if ($#ARGV == -1 and not $opt_g);
-&usage if (not $opt_q and not ($opt_g and $opt_n) and not $opt_i and not $opt_c);
+&usage if (not $opt_q and not ($opt_g and $opt_n) and not $opt_i and not $opt_c and not $opt_e);
# argument handling
my @args = @ARGV;
my $name = 'unknown';
$name = $opt_n if ($opt_n ne '');
+if (@opt_S) {
+ my ($opt_S);
+ foreach $opt_S (@opt_S) {
+ if ($opt_S =~ m/^([^=]+)=(.*)$/) {
+ my ($var) = $1;
+ my ($val) = $2;
+ my $oldval = eval "\$CFG_$var";
+
+ unless ($var and $oldval) {
+ print STDERR "apxs:Error: no config variable $var\n";
+ &usage;
+ }
+
+ eval "\$CFG_${var}=\"${val}\"";
+ } else {
+ print STDERR "apxs:Error: malformatted -S option\n";
+ &usage;
+ }
+ }
+}
+
##
## Operation
##
@@ -354,7 +382,11 @@ if ($opt_c) {
$opt = '';
my ($opt_Wl, $opt_L, $opt_l);
foreach $opt_Wl (@opt_W) {
- $opt .= " $1" if ($opt_Wl =~ m|^\s*l,(.*)$|);
+ if($CFG_LD_SHLIB ne "gcc") {
+ $opt .= " $1" if ($opt_Wl =~ m|^\s*l,(.*)$|);
+ } else {
+ $opt .= " -W$opt_Wl";
+ }
}
foreach $opt_L (@opt_L) {
$opt .= " -L$opt_L";
@@ -370,12 +402,12 @@ if ($opt_c) {
&execute_cmds(@cmds);
# allow one-step compilation and installation
- if ($opt_i) {
+ if ($opt_i or $opt_e) {
@args = ( $dso_file );
}
}
-if ($opt_i) {
+if ($opt_i or $opt_e) {
##
## SHARED OBJECT INSTALLATION
##
@@ -393,8 +425,10 @@ if ($opt_i) {
}
my $t = $f;
$t =~ s|^.+/([^/]+)$|$1|;
- push(@cmds, "cp $f $CFG_LIBEXECDIR/$t");
- push(@cmds, "chmod 755 $CFG_LIBEXECDIR/$t");
+ if ($opt_i) {
+ push(@cmds, "cp $f $CFG_LIBEXECDIR/$t");
+ push(@cmds, "chmod 755 $CFG_LIBEXECDIR/$t");
+ }
# determine module symbolname and filename
my $filename = '';
@@ -455,29 +489,28 @@ if ($opt_i) {
exit(1);
}
- my $update = 0;
my $lmd;
+ my $c = '';
+ $c = '#' if ($opt_A);
foreach $lmd (@lmd) {
+ my $what = $opt_A ? "preparing" : "activating";
if ($content !~ m|\n#?\s*$lmd|) {
- my $c = '';
- $c = '#' if ($opt_A);
$content =~ s|^(.*\n#?\s*LoadModule\s+[^\n]+\n)|$1$c$lmd\n|sg;
- $update = 1;
- $lmd =~ m|LoadModule\s+(.+?)_module.*|;
- my $what = $opt_A ? "preparing" : "activating";
- print STDERR "[$what module `$1' in $CFG_SYSCONFDIR/$CFG_TARGET.conf]\n";
+ } else {
+ $content =~ s|^(.*\n)#?\s*$lmd[^\n]*\n|$1$c$lmd\n|sg;
}
+ $lmd =~ m|LoadModule\s+(.+?)_module.*|;
+ print STDERR "[$what module `$1' in $CFG_SYSCONFDIR/$CFG_TARGET.conf]\n";
}
my $amd;
foreach $amd (@amd) {
if ($content !~ m|\n#?\s*$amd|) {
- my $c = '';
- $c = '#' if ($opt_A);
$content =~ s|^(.*\n#?\s*AddModule\s+[^\n]+\n)|$1$c$amd\n|sg;
- $update = 1;
+ } else {
+ $content =~ s|^(.*\n)#?\s*$amd[^\n]*\n|$1$c$amd\n|sg;
}
}
- if ($update) {
+ if (@lmd or @amd) {
open(FP, ">$CFG_SYSCONFDIR/$CFG_TARGET.conf.new") || die;
print FP $content;
close(FP);
diff --git a/usr.sbin/httpd/src/support/ca-fix.c b/usr.sbin/httpd/src/support/ca-fix.c
deleted file mode 100644
index dab40933a15..00000000000
--- a/usr.sbin/httpd/src/support/ca-fix.c
+++ /dev/null
@@ -1,609 +0,0 @@
-/*
-** ca-fix, X.509 Certificate Patch Utility / Version 0.41
-**
-** Copyright (c) 1997-1998
-** Dr Stephen N. Henson <shenson@drh-consultancy.demon.co.uk>
-** http://www.drh-consultancy.demon.co.uk/
-**
-** Commercial and non-commercial use is permitted.
-**
-** Any software using this code must include the following message in its
-** startup code or documentation and in any advertising material:
-** "This Product includes cryptographic software written by Dr S N Henson
-** (shenson@bigfoot.com)"
-**
-** This software is allowed to be used in the mod_ssl package
-** without the above advertisment clause with permission by Dr S N Henson as
-** long as it's used under build-time only and never gets installed as part
-** of neither the Apache nor the mod_ssl package.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <bio.h>
-#include <objects.h>
-#include <asn1.h>
-#include <asn1_mac.h>
-#include <x509.h>
-#include <err.h>
-#include <crypto.h>
-#include <stack.h>
-#include <evp.h>
-#include <pem.h>
-
-#if SSLEAY_VERSION_NUMBER < 0x0900
-#define OBJ_create(a,b,c) OBJ_create_and_add_object(a,b,c)
-#endif
-
-typedef struct {
- int ca;
- ASN1_INTEGER *pathlen;
-} BASIC_CONSTRAINTS;
-
-int i2d_BASIC_CONSTRAINTS(BASIC_CONSTRAINTS *, unsigned char **);
-ASN1_OBJECT *__OBJ_txt2obj(char *);
-
-int i2d_BASIC_CONSTRAINTS(BASIC_CONSTRAINTS *a, unsigned char **pp)
-{
- M_ASN1_I2D_vars(a);
- if (a->ca)
- M_ASN1_I2D_len(a->ca, i2d_ASN1_BOOLEAN);
- M_ASN1_I2D_len(a->pathlen, i2d_ASN1_INTEGER);
-
- M_ASN1_I2D_seq_total();
- if (a->ca)
- M_ASN1_I2D_put(a->ca, i2d_ASN1_BOOLEAN);
- M_ASN1_I2D_put(a->pathlen, i2d_ASN1_INTEGER);
- M_ASN1_I2D_finish();
-}
-
-typedef struct {
- char *name;
- char *value;
- char flag;
-#define CERT_CRIT 0x1
-#define CERT_RAW 0x2
-#define CERT_RAW_FILE 0x4
-} EXT_ADD;
-
-STACK *exts;
-STACK *extusage;
-
-void add_ext(char *, char *, char);
-
-unsigned char extbuf[10240];
-
-int main(int argc, char **argv)
-{
- char *infile = NULL, *outfile = NULL, *keyname = NULL;
- BIO *in = NULL, *out = NULL, *inkey = NULL, *bio_err = NULL;
- char **args;
- int i;
- int badarg = 0;
- int bconsadd = 0, bconsdel = 0;
- int nset = 0, nsclr = 0;
- unsigned char ntype = 0, noout = 0, exthex = 0, extparse = 0;
- unsigned char bscrit = 0, nscrit = 0, keycrit = 0, print = 0, sign = 1;
- unsigned char setkey = 0;
- X509 *cert;
- EVP_PKEY *pkey = NULL;
- BASIC_CONSTRAINTS bcons = {0, NULL};
- EVP_MD *dgst;
-
- if (bio_err == NULL)
- bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
-
- ERR_load_crypto_strings();
- args = argv + 1;
-
- while (*args) {
- if (*args[0] == '-') {
- if (!strcmp(*args, "-caset")) {
- bconsadd = 1;
- bcons.ca = 0xff;
- }
- else if (!strcmp(*args, "-caunset")) {
- if (bcons.ca)
- badarg = 1;
- else
- bconsadd = 1;
- }
- else if (!strcmp(*args, "-caclr"))
- bconsdel = 1;
- else if (!strcmp(*args, "-setkey"))
- setkey = 1;
- else if (!strcmp(*args, "-print"))
- print = 1;
- else if (!strcmp(*args, "-noout"))
- noout = 1;
- else if (!strcmp(*args, "-nosign"))
- sign = 0;
- else if (!strcmp(*args, "-exthex"))
- exthex = 1;
- else if (!strcmp(*args, "-extparse"))
- extparse = 1;
- else if (!strcmp(*args, "-nsclr"))
- nsclr = 1;
- else if (!strcmp(*args, "-nobscrit"))
- bscrit = 0;
- else if (!strcmp(*args, "-bscrit"))
- bscrit = 1;
- else if (!strcmp(*args, "-nscrit"))
- nscrit = 1;
- else if (!strcmp(*args, "-extcrit"))
- keycrit = 1;
- else if (!strcmp(*args, "-pathlen")) {
- if (args[1]) {
- args++;
- bconsadd = 1;
- bcons.ca = 0xff;
- bcons.pathlen = ASN1_INTEGER_new();
- ASN1_INTEGER_set(bcons.pathlen,
- strtol(*args, NULL, 0));
- }
- else
- badarg = 1;
- }
- else if (!strcmp(*args, "-nscertype")) {
- if (args[1]) {
- args++;
- nset = 1;
- ntype = (unsigned char) strtol(*args, NULL, 0);
- }
- else
- badarg = 1;
- }
- else if (!strcmp(*args, "-rawfile")) {
- if (args[1] && args[2]) {
- add_ext(args[1], args[2], CERT_RAW_FILE);
- args += 2;
- }
- else
- badarg = 1;
- }
- else if (!strcmp(*args, "-Crawfile")) {
- if (args[1] && args[2]) {
- add_ext(args[1], args[2], CERT_RAW_FILE | CERT_CRIT);
- args += 2;
- }
- else
- badarg = 1;
- }
- else if (!strcmp(*args, "-rawext")) {
- if (args[1] && args[2]) {
- add_ext(args[1], args[2], CERT_RAW);
- args += 2;
- }
- else
- badarg = 1;
- }
- else if (!strcmp(*args, "-Crawext")) {
- if (args[1] && args[2]) {
- add_ext(args[1], args[2], CERT_RAW | CERT_CRIT);
- args += 2;
- }
- else
- badarg = 1;
- }
- else if (!strcmp(*args, "-ext")) {
- if (args[1] && args[2]) {
- add_ext(args[1], args[2], 0);
- args += 2;
- }
- else
- badarg = 1;
- }
- else if (!strcmp(*args, "-Cext")) {
- if (args[1] && args[2]) {
- add_ext(args[1], args[2], CERT_CRIT);
- args += 2;
- }
- else
- badarg = 1;
- }
- else if (!strcmp(*args, "-extusage")) {
- if (args[1]) {
- ASN1_OBJECT *obj;
- if (!extusage)
- extusage = sk_new(NULL);
- obj = __OBJ_txt2obj(args[1]);
- if (!obj) {
- BIO_printf(bio_err, "Error parsing extended usage object\n");
- ERR_print_errors(bio_err);
- exit(1);
- }
- else
- sk_push(extusage, (char *) obj);
- args++;
- }
- else
- badarg = 1;
- }
- else if (!strcmp(*args, "-delext")) {
- if (args[1]) {
- add_ext(args[1], NULL, 0);
- args++;
- }
- else
- badarg = 1;
- }
- else if (!strcmp(*args, "-inkey")) {
- if (args[1]) {
- args++;
- keyname = *args;
- }
- else
- badarg = 1;
- }
- else if (!strcmp(*args, "-in")) {
- if (args[1]) {
- args++;
- infile = *args;
- }
- else
- badarg = 1;
- }
- else if (!strcmp(*args, "-out")) {
- if (args[1]) {
- args++;
- outfile = *args;
- }
- else
- badarg = 1;
- }
- else
- badarg = 1;
- }
- else
- badarg = 1;
- args++;
- }
-
- if (badarg || (bconsadd && bconsdel)) {
- BIO_printf(bio_err, "ca-fix version 0.41, certificate patcher\n");
- BIO_printf(bio_err, "Written by Dr. S N Henson (shenson@bigfoot.com)\n");
- BIO_printf(bio_err, "ca-fix [args]\n");
- BIO_printf(bio_err, "-in cert.pem input certificate.\n");
- BIO_printf(bio_err, "-out cert.pem output certificate.\n");
- BIO_printf(bio_err, "-noout don't output certificate\n");
- BIO_printf(bio_err, "-nosign don't sign certificate\n");
- BIO_printf(bio_err, "-print print certificate\n");
- BIO_printf(bio_err, "-extparse ASN1 parse extensions\n");
- BIO_printf(bio_err, "-exthex hex dump extensions\n");
- BIO_printf(bio_err, "-caset set cA flag, add basic constraints\n");
- BIO_printf(bio_err, "-caunset don't set cA flag, add basic constraints\n");
- BIO_printf(bio_err, "-caclr delete basic constraints\n");
- BIO_printf(bio_err, "-pathlen n set path length to \'n\'\n");
- BIO_printf(bio_err, "-bscrit make basic constraints critical\n");
- BIO_printf(bio_err, "-nscrit make nscertype critical (not recommended)\n");
- BIO_printf(bio_err, "-nscertype num set nscertype to num\n");
- BIO_printf(bio_err, "-nsclr delete nscertype\n");
- BIO_printf(bio_err, "-inkey pkey.pem private key of signer\n");
- BIO_printf(bio_err, "Expert options:\n");
- BIO_printf(bio_err, "-setkey changed certificate public key to match signer\n");
- BIO_printf(bio_err, "-delext ext delete extension (can use OID)\n");
- BIO_printf(bio_err, "-ext genopt val add several extensions\n");
- BIO_printf(bio_err, "-Cext genopt val add several critical extensions\n");
- BIO_printf(bio_err, "genopt can be: keyUsage, nsCertType, nsBaseUrl, nsRevocationUrl,\n");
- BIO_printf(bio_err, " nsCaRevocationUrl, nsRenewalUrl, nsCaPolicyUrl,\n");
- BIO_printf(bio_err, " nsSslServerName, nsComment\n");
- BIO_printf(bio_err, "-rawext opt HEX add raw extension (can use OID)\n");
- BIO_printf(bio_err, "-Crawext opt HEX add critical raw extension (can use OID)\n");
- BIO_printf(bio_err, "-Crawfile opt fn add raw extension from file (can use OID)\n");
- BIO_printf(bio_err, "-rawfile opt fn add critical raw extension from file (can use OID)\n");
- BIO_printf(bio_err, "-extusage OID add extended key usage extension\n");
- BIO_printf(bio_err, "-extcrit make extended key usage extension critical\n");
- exit(1);
- }
-
- SSLeay_add_all_algorithms();
- X509v3_add_netscape_extensions();
- X509v3_add_standard_extensions();
-
- in = BIO_new(BIO_s_file());
- out = BIO_new(BIO_s_file());
-
- if (!infile)
- BIO_set_fp(in, stdin, BIO_NOCLOSE);
- else {
- if (!keyname)
- keyname = infile;
- if (BIO_read_filename(in, infile) <= 0) {
- perror(infile);
- exit(1);
- }
- }
-
- if (keyname) {
- inkey = BIO_new(BIO_s_file());
- if (BIO_read_filename(inkey, keyname) <= 0) {
- perror(keyname);
- exit(1);
- }
- }
-
- if (!outfile)
- BIO_set_fp(out, stdout, BIO_NOCLOSE);
- else {
- if (BIO_write_filename(out, outfile) <= 0) {
- perror(outfile);
- exit(1);
- }
- }
-
- cert = PEM_read_bio_X509(in, NULL, NULL);
- if (!cert) {
- ERR_print_errors(bio_err);
- exit(1);
- }
-
- if (sign || setkey) {
- pkey = PEM_read_bio_PrivateKey(inkey ? inkey : in, NULL, NULL);
- if (!pkey) {
- BIO_printf(bio_err, "Error loading private key\n");
- ERR_print_errors(bio_err);
- exit(1);
- }
- }
-
- /* OK we've got the certificate: now fix it up */
-
- /* Make it a V3 certificate */
- X509_set_version(cert, 2);
-
- if (setkey)
- X509_set_pubkey(cert, pkey);
-
- if (bconsadd || bconsdel) {
- int index;
- index = X509_get_ext_by_NID(cert, NID_basic_constraints, -1);
- if (index >= 0)
- X509_delete_ext(cert, index);
- }
- if (nset || nsclr) {
- int index;
- index = X509_get_ext_by_NID(cert, NID_netscape_cert_type, -1);
- if (index >= 0)
- X509_delete_ext(cert, index);
- }
-
- if (bconsadd) {
- ASN1_OCTET_STRING *bcons_ext;
- X509_EXTENSION *x;
- unsigned char *bcons_der, *p;
- int bcons_len;
-
- /* generate encoding of extension */
- bcons_len = i2d_BASIC_CONSTRAINTS(&bcons, NULL);
- bcons_der = malloc(bcons_len);
- p = bcons_der;
- i2d_BASIC_CONSTRAINTS(&bcons, &p);
-
- bcons_ext = ASN1_OCTET_STRING_new();
- ASN1_OCTET_STRING_set(bcons_ext, bcons_der, bcons_len);
- free(bcons_der);
- x = X509_EXTENSION_create_by_NID(NULL, NID_basic_constraints, bscrit,
- bcons_ext);
- ASN1_OCTET_STRING_free(bcons_ext);
- if (!x) {
- BIO_printf(bio_err, "Error creating extension\n");
- ERR_print_errors(bio_err);
- exit(1);
- }
- X509_add_ext(cert, x, -1);
- X509_EXTENSION_free(x);
- }
-
- if (nset) {
- X509_EXTENSION *x;
- ASN1_OCTET_STRING *str;
- int data_type;
- str = NULL;
- data_type = X509v3_data_type_by_NID(NID_netscape_cert_type);
- X509v3_pack_string(&str, data_type, &ntype, 1);
- x = X509_EXTENSION_create_by_NID(NULL, NID_netscape_cert_type,
- nscrit, str);
- X509_add_ext(cert, x, -1);
- X509_EXTENSION_free(x);
- /*ASN1_OCTET_STRING_free(str); */
- }
- /* Handle the generic extensions */
- if (exts) {
- while (sk_num(exts)) {
- EXT_ADD *tmpext;
- int ext_nid, index;
- char *ext_str;
- unsigned char ext_bit;
- ASN1_OCTET_STRING *str;
- X509_EXTENSION *x;
- ASN1_OBJECT *extobj;
- tmpext = (EXT_ADD *) sk_pop(exts);
- extobj = __OBJ_txt2obj(tmpext->name);
- if (!extobj) {
- fprintf(stderr, "Invalid object %s\n", tmpext->name);
- ERR_print_errors(bio_err);
- exit(1);
- }
- /* Delete extension if already present */
- index = X509_get_ext_by_OBJ(cert, extobj, -1);
- if (index >= 0)
- X509_delete_ext(cert, index);
- if (!tmpext->value)
- continue;
- ext_nid = OBJ_obj2nid(extobj);
- if (tmpext->flag & CERT_RAW) {
- /* Covert hex extension into an OCTET STRING */
- unsigned char *rawext, *p, *q, tmphex[3];
- long rawlen;
- rawlen = strlen(tmpext->value);
- if (rawlen & 1) {
- fprintf(stderr, "Invalid raw extension length\n");
- exit(1);
- }
- for (p = (unsigned char *)tmpext->value; *p; p++)
- if (!isxdigit(*p)) {
- fprintf(stderr, "Extension %s invalid hex digit %c\n",
- tmpext->value, *p);
- exit(1);
- }
- rawlen >>= 1;
- rawext = Malloc(rawlen);
- tmphex[2] = 0;
- for (p = (unsigned char *)tmpext->value, q = rawext; *p; p += 2, q++) {
- tmphex[0] = p[0];
- tmphex[1] = p[1];
- *q = (unsigned char)strtol((const char *)tmphex, NULL, 16);
- }
- str = ASN1_OCTET_STRING_new();
- ASN1_OCTET_STRING_set(str, rawext, rawlen);
- Free(rawext);
- }
- else if (tmpext->flag & CERT_RAW_FILE) {
- BIO *tmpin;
- int extlen;
- if (!(tmpin = BIO_new_file(tmpext->value, "rb"))) {
- BIO_printf(bio_err, "Error opening file %s\n", tmpext->value);
- ERR_print_errors(bio_err);
- }
- extlen = BIO_read(tmpin, (char *)extbuf, sizeof(extbuf));
- str = ASN1_STRING_new();
- ASN1_OCTET_STRING_set(str, extbuf, extlen);
- }
- else {
- /* Get extension type */
- switch (ext_nid) {
-
- case NID_key_usage:
- case NID_netscape_cert_type:
-
- ext_bit = (unsigned char) strtol(tmpext->value, NULL, 0);
- ext_str = NULL;
-
- break;
-
- case NID_netscape_base_url:
- case NID_netscape_revocation_url:
- case NID_netscape_ca_revocation_url:
- case NID_netscape_renewal_url:
- case NID_netscape_ca_policy_url:
- case NID_netscape_ssl_server_name:
- case NID_netscape_comment:
-
- ext_str = tmpext->value;
-
- break;
-
- default:
-
- fprintf(stderr, "Unsuported extension %s\n", tmpext->name);
- exit(1);
- break;
- }
-
- if (ext_str)
- str = X509v3_pack_string(NULL, V_ASN1_IA5STRING,
- (unsigned char *)tmpext->value,
- strlen(tmpext->value));
- else
- str = X509v3_pack_string(NULL, V_ASN1_BIT_STRING,
- &ext_bit, 1);
- }
- x = X509_EXTENSION_create_by_NID(NULL, ext_nid,
- tmpext->flag & CERT_CRIT, str);
- X509_add_ext(cert, x, -1);
- X509_EXTENSION_free(x);
- }
- }
-
- /* Handle extended key usage */
- if (extusage) {
- int extlen;
- unsigned char *extder, *p;
- ASN1_OCTET_STRING *extkey;
- X509_EXTENSION *x;
- ASN1_OBJECT *extobj;
-
-
- extobj = __OBJ_txt2obj("2.5.29.37");
- /* generate encoding of extension */
- extlen = i2d_ASN1_SET(extusage, NULL, i2d_ASN1_OBJECT, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
- extder = malloc(extlen);
- p = extder;
- i2d_ASN1_SET(extusage, &p, i2d_ASN1_OBJECT, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
- extkey = ASN1_OCTET_STRING_new();
- ASN1_OCTET_STRING_set(extkey, extder, extlen);
- free(extder);
- x = X509_EXTENSION_create_by_OBJ(NULL, extobj, keycrit,
- extkey);
- if (!x) {
- BIO_printf(bio_err, "Error creating extension\n");
- ERR_print_errors(bio_err);
- exit(1);
- }
- X509_add_ext(cert, x, -1);
- X509_EXTENSION_free(x);
- sk_pop_free(extusage, ASN1_OBJECT_free);
- ASN1_OBJECT_free(extobj);
- }
-
-
- /* OK we've modified the certificate so it will have to be re-signed */
- dgst = EVP_get_digestbyobj(cert->sig_alg->algorithm);
- if (sign)
- X509_sign(cert, pkey, dgst);
- if (print)
- X509_print(out, cert);
- if (extparse || exthex) {
- BIO_printf(out, "X509 V3 Extensions.\n");
- for (i = 0; i < X509_get_ext_count(cert); i++) {
- X509_EXTENSION *tmpext;
- ASN1_OCTET_STRING *octval;
- tmpext = X509_get_ext(cert, i);
- octval = X509_EXTENSION_get_data(tmpext);
- i2a_ASN1_OBJECT(out, X509_EXTENSION_get_object(tmpext));
- BIO_printf(out, ":\n");
- if (exthex) {
- int j;
- for (j = 0; j < octval->length; j++)
- BIO_printf(out, "%02X", octval->data[j]);
- BIO_printf(out, "\n");
- }
- if (extparse)
- ASN1_parse(out, octval->data, octval->length, 0);
- }
- }
- if (!noout)
- PEM_write_bio_X509(out, cert);
-
- return (0);
-
-}
-
-void add_ext(char *name, char *val, char flag)
-{
- EXT_ADD *tmpext;
- if (!exts)
- exts = sk_new(NULL);
- tmpext = (EXT_ADD *) Malloc(sizeof(EXT_ADD));
- tmpext->name = name;
- tmpext->value = val;
- tmpext->flag = flag;
- sk_push(exts, (char *) tmpext);
-}
-
-ASN1_OBJECT *__OBJ_txt2obj(char *name)
-{
- int obj_nid;
- ASN1_OBJECT *obj;
- obj_nid = OBJ_sn2nid(name);
- if (obj_nid != NID_undef)
- return OBJ_nid2obj(obj_nid);
- obj_nid = OBJ_create(name, name, name);
- if (obj_nid <= 0)
- return NULL;
- obj = OBJ_nid2obj(obj_nid);
- obj->flags &= ~ASN1_OBJECT_FLAG_DYNAMIC_DATA;
- return obj;
-}
-
diff --git a/usr.sbin/httpd/src/support/dbmmanage.1 b/usr.sbin/httpd/src/support/dbmmanage.1
index 67e5b60dfc4..06380ff0f59 100644
--- a/usr.sbin/httpd/src/support/dbmmanage.1
+++ b/usr.sbin/httpd/src/support/dbmmanage.1
@@ -6,7 +6,7 @@
.\" are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
+.\" notice, this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in
@@ -71,22 +71,23 @@ usernames and password for basic authentication of HTTP users.
Resources available from the
.B httpd
Apache web server can be restricted to just the users listed
-in the files created by
+in the files created by
.B dbmmanage.
This program can only be used
when the usernames are stored in a DBM file. To use a
-flat-file database see
+flat-file database see
\fBhtpasswd\fP.
.PP
This manual page only lists the command line arguments. For details of
-the directives necessary to configure user authentication in
-.B httpd
+the directives necessary to configure user authentication in
+.B httpd
see
the Apache manual, which is part of the Apache distribution or can be
found at http://www.apache.org/.
.SH OPTIONS
.IP \fB\fIfilename\fP
-The filename of the DBM format file. Usually without the extension .pag or .dir.
+The filename of the DBM format file. Usually without the
+extension .db, .pag, or .dir.
.IP \fB\fIcommand\fP
This selects the operation to perform:
.TP 12
@@ -99,7 +100,7 @@ Asks for a password and then adds an entry for \fIusername\fP to
\fIfilename\fP .
.TP 12
.B check
-Asks for a password and then checks if
+Asks for a password and then checks if
\fIusername\fP is in \fIfilename\fP and if it's password matches
the specified one.
.TP 12
@@ -119,6 +120,52 @@ Just displays the complete contents of the DBM file.
.IP \fB\fIusername\fP
The user for which the update operation is performed.
.PD
+.SH BUGS
+.PP
+One should be aware that there are a number of different DBM file
+formats in existance, and with all likelihood, libraries for more than
+one format may exist on your system. The three primary examples are
+NDBM, the GNU project's GDBM, and Berkeley DB 2. Unfortunately, all
+these libraries use different file formats, and you must make sure
+that the file format used by
+.I filename
+is the same format that
+.B dbmmanage
+expects to see.
+.B dbmmanage
+currently has no way of determining what type of DBM file it is
+looking at. If used against the wrong format,
+.dbmmanage
+will simply return nothing, or may create a different DBM file with a
+different name, or at worst, it may corrupt the DBM file if you were
+attempting to write to it.
+.PP
+.B dbmmanage
+has a list of DBM format preferences, defined by the
+.B @AnyDBM::ISA
+array near the beginning of the program. Since we prefer the Berkeley
+DB 2 file format, the order in which
+.B dbmmanage
+will look for system libraries is Berkeley DB 2, then NDBM, and then
+GDBM. The first library found will be the library
+.B dbmmanage
+will attempt to use for all DBM file transactions. This ordering is
+slightly different than the standard
+.B @AnyDBM::ISA
+ordering in perl, as well as the ordering used by the simple dbmopen()
+call in Perl, so if you use any other utilities to manage your DBM
+files, they must also follow this preference ordering. Similar care
+must be taken if using programs in other languages, like C, to
+access these files.
+.PP
+Apache's
+.B mod_auth_db.c
+module corresponds to Berkeley DB 2 library, while
+.B mod_auth_dbm.c
+corresponds to the NDBM library. Also, one can usually use the
+.B file
+program supplied with most Unix systems to see what format a DBM file is in.
+.PD
.SH SEE ALSO
.BR httpd(8)
.
diff --git a/usr.sbin/httpd/src/support/htdigest.1 b/usr.sbin/httpd/src/support/htdigest.1
index 2ab3aa5450d..c719e456ce9 100644
--- a/usr.sbin/httpd/src/support/htdigest.1
+++ b/usr.sbin/httpd/src/support/htdigest.1
@@ -6,7 +6,7 @@
.\" are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
+.\" notice, this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in
@@ -55,10 +55,10 @@
.SH NAME
htdigest \- Create and update user authentication files
.SH SYNOPSIS
-.B htdigest
+.B htdigest
[
.B \-c
-]
+]
.I passwdfile
.I realm
.I username
@@ -69,29 +69,29 @@ usernames, realm and password for digest authentication of HTTP users.
Resources available from the
.B httpd
Apache web server can be restricted to just the users listed
-in the files created by
+in the files created by
.B htdigest.
.PP
This manual page only lists the command line arguments. For details of
-the directives necessary to configure digest authentication in
-.B httpd
+the directives necessary to configure digest authentication in
+.B httpd
see
the Apache manual, which is part of the Apache distribution or can be
found at http://www.apache.org/.
.SH OPTIONS
-.IP \-c
+.IP \-c
Create the \fIpasswdfile\fP. If \fIpasswdfile\fP already exists, it
-is deleted first.
+is deleted first.
.IP \fB\fIpasswdfile\fP
Name of the file to contain the username, realm and password. If \-c
is given, this file is created if it does not already exist,
-or deleted and recreated if it does exist.
+or deleted and recreated if it does exist.
.IP \fB\fIrealm\fP
-The realm name to which the user name belongs to.
+The realm name to which the user name belongs to.
.IP \fB\fIusername\fP
The user name to create or update in \fBpasswdfile\fP. If
\fIusername\fP does not exist is this file, an entry is added. If it
does exist, the password is changed.
.SH SEE ALSO
-.BR httpd(8)
+.BR httpd(8)
.
diff --git a/usr.sbin/httpd/src/support/htdigest.c b/usr.sbin/httpd/src/support/htdigest.c
index 69c8e2d2c96..d1fc41800fd 100644
--- a/usr.sbin/httpd/src/support/htdigest.c
+++ b/usr.sbin/httpd/src/support/htdigest.c
@@ -1,3 +1,59 @@
+/* ====================================================================
+ * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
/******************************************************************************
******************************************************************************
* NOTE! This program is not safe as a setuid executable! Do not make it
@@ -12,31 +68,31 @@
#include "ap_config.h"
#include <sys/types.h>
-#ifdef MPE
+#include "ap.h"
+#include "ap_md5.h"
+#if defined(MPE) || defined(QNX) || defined(WIN32) || defined(__TANDEM)
#include <signal.h>
#else
#include <sys/signal.h>
#endif
-/* This is probably the easiest way to do it */
-#include "../main/md5c.c"
+#ifdef WIN32
+#include <conio.h>
+#define unlink _unlink
+#endif
+#ifdef CHARSET_EBCDIC
+#define LF '\n'
+#define CR '\r'
+#else
#define LF 10
#define CR 13
+#endif /* CHARSET_EBCDIC */
#define MAX_STRING_LEN 256
char *tn;
-static char *strd(char *s)
-{
- char *d;
-
- d = (char *) malloc(strlen(s) + 1);
- strcpy(d, s);
- return (d);
-}
-
static void getword(char *word, char *line, char stop)
{
int x = 0, y;
@@ -86,15 +142,23 @@ static void add_password(char *user, char *realm, FILE *f)
AP_MD5_CTX context;
unsigned char digest[16];
char string[MAX_STRING_LEN];
+ char pwin[MAX_STRING_LEN];
+ char pwv[MAX_STRING_LEN];
unsigned int i;
- pw = strd((char *) getpass("New password:"));
- if (strcmp(pw, (char *) getpass("Re-type new password:"))) {
+ if (ap_getpass("New password: ", pwin, sizeof(pwin)) != 0) {
+ fprintf(stderr, "password too long");
+ exit(5);
+ }
+ ap_getpass("Re-type new password: ", pwv, sizeof(pwv));
+ if (strcmp(pwin, pwv) != 0) {
fprintf(stderr, "They don't match, sorry.\n");
- if (tn)
+ if (tn) {
unlink(tn);
+ }
exit(1);
}
+ pw = pwin;
fprintf(f, "%s:%s:", user, realm);
/* Do MD5 stuff */
@@ -138,7 +202,7 @@ int main(int argc, char *argv[])
int found;
tn = NULL;
- signal(SIGINT, (void (*)()) interrupted);
+ signal(SIGINT, (void (*)(int)) interrupted);
if (argc == 5) {
if (strcmp(argv[1], "-c"))
usage();
@@ -203,5 +267,5 @@ int main(int argc, char *argv[])
#endif
system(command);
unlink(tn);
- exit(0);
+ return 0;
}
diff --git a/usr.sbin/httpd/src/support/htdigest.dsp b/usr.sbin/httpd/src/support/htdigest.dsp
new file mode 100644
index 00000000000..f00f87e7e74
--- /dev/null
+++ b/usr.sbin/httpd/src/support/htdigest.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="htdigest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=htdigest - 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 "htdigest.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 "htdigest.mak" CFG="htdigest - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "htdigest - Win32 Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "htdigest - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "htdigest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "htdigest"
+# PROP BASE Intermediate_Dir "htdigest"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"release/htdigest.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "htdigest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "htdiges0"
+# PROP BASE Intermediate_Dir "htdiges0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"debug/htdigest.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "htdigest - Win32 Release"
+# Name "htdigest - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\ap\ap_cpystrn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_getpass.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_md5c.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\htdigest.c
+# End Source File
+# End Target
+# End Project
diff --git a/usr.sbin/httpd/src/support/htdigest.mak b/usr.sbin/httpd/src/support/htdigest.mak
new file mode 100644
index 00000000000..0f048e7d397
--- /dev/null
+++ b/usr.sbin/httpd/src/support/htdigest.mak
@@ -0,0 +1,297 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on htdigest.dsp
+!IF "$(CFG)" == ""
+CFG=htdigest - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to htdigest - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "htdigest - Win32 Release" && "$(CFG)" !=\
+ "htdigest - 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 "htdigest.mak" CFG="htdigest - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "htdigest - Win32 Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "htdigest - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "htdigest - Win32 Release"
+
+OUTDIR=.
+INTDIR=.
+# Begin Custom Macros
+OutDir=.
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\release\htdigest.exe"
+
+!ELSE
+
+ALL : "$(OUTDIR)\release\htdigest.exe"
+
+!ENDIF
+
+CLEAN :
+ -@erase "$(INTDIR)\ap_cpystrn.obj"
+ -@erase "$(INTDIR)\ap_getpass.obj"
+ -@erase "$(INTDIR)\ap_md5c.obj"
+ -@erase "$(INTDIR)\htdigest.obj"
+ -@erase "$(INTDIR)\vc50.idb"
+ -@erase "$(OUTDIR)\release\htdigest.exe"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D\
+ "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\htdigest.pch" /YX /FD /c
+CPP_OBJS=.
+CPP_SBRS=.
+
+.c{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\htdigest.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:console /incremental:no\
+ /pdb:"$(OUTDIR)\htdigest.pdb" /machine:I386\
+ /out:"$(OUTDIR)\release\htdigest.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\ap_cpystrn.obj" \
+ "$(INTDIR)\ap_getpass.obj" \
+ "$(INTDIR)\ap_md5c.obj" \
+ "$(INTDIR)\htdigest.obj"
+
+"$(OUTDIR)\release\htdigest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "htdigest - Win32 Debug"
+
+OUTDIR=.
+INTDIR=.
+# Begin Custom Macros
+OutDir=.
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\debug\htdigest.exe"
+
+!ELSE
+
+ALL : "$(OUTDIR)\debug\htdigest.exe"
+
+!ENDIF
+
+CLEAN :
+ -@erase "$(INTDIR)\ap_cpystrn.obj"
+ -@erase "$(INTDIR)\ap_getpass.obj"
+ -@erase "$(INTDIR)\ap_md5c.obj"
+ -@erase "$(INTDIR)\htdigest.obj"
+ -@erase "$(INTDIR)\vc50.idb"
+ -@erase "$(INTDIR)\vc50.pdb"
+ -@erase "$(OUTDIR)\debug\htdigest.exe"
+ -@erase "$(OUTDIR)\debug\htdigest.ilk"
+ -@erase "$(OUTDIR)\htdigest.pdb"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /I "..\include" /D "WIN32" /D\
+ "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\htdigest.pch" /YX /FD /c
+CPP_OBJS=.
+CPP_SBRS=.
+
+.c{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\htdigest.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:console /incremental:yes\
+ /pdb:"$(OUTDIR)\htdigest.pdb" /debug /machine:I386\
+ /out:"$(OUTDIR)\debug\htdigest.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\ap_cpystrn.obj" \
+ "$(INTDIR)\ap_getpass.obj" \
+ "$(INTDIR)\ap_md5c.obj" \
+ "$(INTDIR)\htdigest.obj"
+
+"$(OUTDIR)\debug\htdigest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(CFG)" == "htdigest - Win32 Release" || "$(CFG)" ==\
+ "htdigest - Win32 Debug"
+SOURCE=..\ap\ap_cpystrn.c
+DEP_CPP_AP_CP=\
+ "..\include\alloc.h"\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_AP_CP=\
+ "..\include\ap_config_auto.h"\
+ "..\include\ebcdic.h"\
+ "..\include\os.h"\
+ "..\include\sfio.h"\
+
+
+"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) $(DEP_CPP_AP_CP) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\ap\ap_getpass.c
+DEP_CPP_AP_GE=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_AP_GE=\
+ "..\include\ap_config_auto.h"\
+ "..\include\os.h"\
+
+
+"$(INTDIR)\ap_getpass.obj" : $(SOURCE) $(DEP_CPP_AP_GE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\ap\ap_md5c.c
+DEP_CPP_AP_MD=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_AP_MD=\
+ "..\ap\ebcdic.h"\
+ "..\include\ap_config_auto.h"\
+ "..\include\os.h"\
+
+
+"$(INTDIR)\ap_md5c.obj" : $(SOURCE) $(DEP_CPP_AP_MD) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\htdigest.c
+DEP_CPP_HTDIG=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_HTDIG=\
+ "..\include\ap_config_auto.h"\
+ "..\include\os.h"\
+
+
+"$(INTDIR)\htdigest.obj" : $(SOURCE) $(DEP_CPP_HTDIG) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/usr.sbin/httpd/src/support/htpasswd.1 b/usr.sbin/httpd/src/support/htpasswd.1
index c2bf8cf8ab3..1687cde41c2 100644
--- a/usr.sbin/httpd/src/support/htpasswd.1
+++ b/usr.sbin/httpd/src/support/htpasswd.1
@@ -6,7 +6,7 @@
.\" are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
+.\" notice, this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in
@@ -55,44 +55,159 @@
.SH NAME
htpasswd \- Create and update user authentication files
.SH SYNOPSIS
+.B htpasswd
+[
+.B \-c
+]
+[
+.B \-m
+]
+.I passwdfile
+.I username
+.br
.B htpasswd
+.B \-b
[
.B \-c
-]
+]
+[
+.B \-m
+.B \-d
+.B \-p
+.B \-s
+]
.I passwdfile
.I username
+.I password
.SH DESCRIPTION
.B htpasswd
is used to create and update the flat-files used to store
usernames and password for basic authentication of HTTP users.
+If
+.B htpasswd
+cannot access a file, such as not being able to write to the output
+file or not being able to read the file in order to update it,
+it returns an error status and makes no changes.
+.PP
Resources available from the
.B httpd
Apache web server can be restricted to just the users listed
-in the files created by
+in the files created by
.B htpasswd.
This program can only be used
when the usernames are stored in a flat-file. To use a
-DBM database see
+DBM database see
\fBdbmmanage\fP.
.PP
+.B htpasswd
+encrypts passwords using either a version of MD5 modified for Apache,
+or the system's \fIcrypt()\fP routine. Files managed by
+.B htpasswd
+may contain both types of passwords; some user records may have
+MD5-encrypted passwords while others in the same file may have passwords
+encrypted with \fIcrypt()\fP.
+.PP
This manual page only lists the command line arguments. For details of
-the directives necessary to configure user authentication in
-.B httpd
+the directives necessary to configure user authentication in
+.B httpd
see
the Apache manual, which is part of the Apache distribution or can be
-found at http://www.apache.org/.
+found at <URL:http://www.apache.org/>.
.SH OPTIONS
-.IP \-c
+.IP \-b
+Use batch mode; \fIi.e.\fP, get the password from the command line
+rather than prompting for it. \fBThis option should be used with
+extreme care, since the password is clearly visible on the command
+line.\fP
+.IP \-c
Create the \fIpasswdfile\fP. If \fIpasswdfile\fP already exists, it
-is deleted first.
+is rewritten and truncated.
+.IP \-m
+Use MD5 encryption for passwords. On Windows and TPF, this is the default.
+.IP \-d
+Use crypt() encryption for passwords. The default on all platforms but
+Windows and TPF. Though possibly supported by
+.B htpasswd
+onm all platforms, it is not supported by the
+.B httpd
+server on Windows and TPF.
+.IP \-s
+Use SHA encryption for passwords. Faciliates migration from/to Netscape
+servers using the LDAP Directory Interchange Format (ldif).
+.IP \-p
+Use plaintext passwords. Though
+.B htpasswd
+will support creation on all platofrms, the
+.B httpd
+deamon will only accept plain text passwords on Windows and TPF.
.IP \fB\fIpasswdfile\fP
Name of the file to contain the user name and password. If \-c
is given, this file is created if it does not already exist,
-or deleted and recreated if it does exist.
+or rewritten and truncated if it does exist.
.IP \fB\fIusername\fP
The username to create or update in \fBpasswdfile\fP. If
-\fIusername\fP does not exist is this file, an entry is added. If it
+\fIusername\fP does not exist in this file, an entry is added. If it
does exist, the password is changed.
+.IP \fB\fIpassword\fP
+The plaintext password to be encrypted and stored in the file. Only used
+with the \fI-b\fP flag.
+.SH EXIT STATUS
+.B htpasswd
+returns a zero status ("true") if the username and password have
+been successfully added or updated in the \fIpasswdfile\fP.
+.B htpasswd
+returns 1 if it encounters some problem accessing files, 2 if there
+was a syntax problem with the command line, 3 if the password was
+entered interactively and the verification entry didn't match, 4 if
+its operation was interrupted, 5 if a value is too long (username,
+filename, password, or final computed record), and 6 if the username
+contains illegal characters (see the \fBRESTRICTIONS\fP section).
+.SH EXAMPLES
+\fBhtpasswd /usr/local/etc/apache/.htpasswd-users jsmith\fP
+.IP
+Adds or modifies the password for user \fIjsmith\fP.
+The user is prompted for the password. If executed
+on a Windows system, the password will be encrypted using the
+modified Apache MD5 algorithm; otherwise, the system's
+\fIcrypt()\fP routine will be used. If the file does not
+exist,
+.B htpasswd
+will do nothing except return an error.
+.LP
+\fBhtpasswd -c /home/doe/public_html/.htpasswd jane\fP
+.IP
+Creates a new file and stores a record in it for user \fIjane\fP.
+The user is prompted for the password.
+If the file exists and cannot be read, or cannot be written,
+it is not altered and
+.B htpasswd
+will display a message and return an error status.
+.LP
+\fBhtpasswd -mb /usr/web/.htpasswd-all jones Pwd4Steve\fP
+.IP
+Encrypts the password from the command line (\fIPwd4Steve\fP) using
+the MD5 algorithm, and stores it in the specified file.
+.LP
+.SH SECURITY CONSIDERATIONS
+Web password files such as those managed by
+.B htpasswd
+should \fBnot\fP be within the Web server's URI space -- that is,
+they should not be fetchable with a browser.
+.PP
+The use of the \fI-b\fP option is discouraged, since when it is
+used the unencrypted password appears on the command line.
+.SH RESTRICTIONS
+On the Windows and MPE platforms, passwords encrypted with
+.B htpasswd
+are limited to no more than 255 characters in length. Longer
+passwords will be truncated to 255 characters.
+.PP
+The MD5 algorithm used by
+.B htpasswd
+is specific to the Apache software; passwords encrypted using it will not be
+usable with other Web servers.
+.PP
+Usernames are limited to 255 bytes and may not include the character ':'.
.SH SEE ALSO
.BR httpd(8)
-.
+and the scripts in support/SHA1 which come with the distribution.
diff --git a/usr.sbin/httpd/src/support/htpasswd.c b/usr.sbin/httpd/src/support/htpasswd.c
index c4a0e7e2ba0..21a24e0c0a3 100644
--- a/usr.sbin/httpd/src/support/htpasswd.c
+++ b/usr.sbin/httpd/src/support/htpasswd.c
@@ -1,3 +1,60 @@
+/* ====================================================================
+ * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the Apache Group
+ * for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+
/******************************************************************************
******************************************************************************
* NOTE! This program is not safe as a setuid executable! Do not make it
@@ -5,14 +62,35 @@
******************************************************************************
*****************************************************************************/
/*
- * htpasswd.c: simple program for manipulating password file for NCSA httpd
+ * htpasswd.c: simple program for manipulating password file for
+ * the Apache HTTP server
*
- * Rob McCool
+ * Originally by Rob McCool
+ *
+ * Exit values:
+ * 0: Success
+ * 1: Failure; file access/permission problem
+ * 2: Failure; command line syntax problem (usage message issued)
+ * 3: Failure; password verification failure
+ * 4: Failure; operation interrupted (such as with CTRL/C)
+ * 5: Failure; buffer would overflow (username, filename, or computed
+ * record too long)
+ * 6: Failure; username contains illegal or reserved characters
*/
#include "ap_config.h"
#include <sys/types.h>
#include <signal.h>
+#include <errno.h>
+#include "ap.h"
+#include "ap_md5.h"
+#include "ap_sha1.h"
+
+#ifdef WIN32
+#include <conio.h>
+#include "../os/win32/getopt.h"
+#define unlink _unlink
+#endif
#ifndef CHARSET_EBCDIC
#define LF 10
@@ -23,33 +101,28 @@
#endif /*CHARSET_EBCDIC*/
#define MAX_STRING_LEN 256
+#define ALG_PLAIN 0
+#define ALG_CRYPT 1
+#define ALG_APMD5 2
+#define ALG_APSHA 3
+
+#define ERR_FILEPERM 1
+#define ERR_SYNTAX 2
+#define ERR_PWMISMATCH 3
+#define ERR_INTERRUPTED 4
+#define ERR_OVERFLOW 5
+#define ERR_BADUSER 6
-char *tn;
-
-static char *strd(char *s)
-{
- char *d;
-
- d = (char *) malloc(strlen(s) + 1);
- strcpy(d, s);
- return (d);
-}
-
-static void getword(char *word, char *line, char stop)
-{
- int x = 0, y;
-
- for (x = 0; ((line[x]) && (line[x] != stop)); x++)
- word[x] = line[x];
-
- word[x] = '\0';
- if (line[x])
- ++x;
- y = 0;
-
- while ((line[y++] = line[x++]));
-}
+/*
+ * This needs to be declared statically so the signal handler can
+ * access it.
+ */
+static char *tempfilename;
+/*
+ * Get a line of input from the user, not including any terminating
+ * newline.
+ */
static int getline(char *s, int n, FILE *f)
{
register int i = 0;
@@ -57,8 +130,9 @@ static int getline(char *s, int n, FILE *f)
while (1) {
s[i] = (char) fgetc(f);
- if (s[i] == CR)
+ if (s[i] == CR) {
s[i] = fgetc(f);
+ }
if ((s[i] == 0x4) || (s[i] == LF) || (i == (n - 1))) {
s[i] = '\0';
@@ -72,157 +146,432 @@ static void putline(FILE *f, char *l)
{
int x;
- for (x = 0; l[x]; x++)
+ for (x = 0; l[x]; x++) {
fputc(l[x], f);
+ }
fputc('\n', f);
}
+/*
+ * Make a password record from the given information. A zero return
+ * indicates success; failure means that the output buffer contains an
+ * error message instead.
+ */
+static int mkrecord(char *user, char *record, size_t rlen, char *passwd,
+ int alg)
+{
+ char *pw;
+ char cpw[120];
+ char pwin[MAX_STRING_LEN];
+ char pwv[MAX_STRING_LEN];
+ char salt[9];
+
+ if (passwd != NULL) {
+ pw = passwd;
+ }
+ else {
+ if (ap_getpass("New password: ", pwin, sizeof(pwin)) != 0) {
+ ap_snprintf(record, (rlen - 1), "password too long (>%d)",
+ sizeof(pwin) - 1);
+ return ERR_OVERFLOW;
+ }
+ ap_getpass("Re-type new password: ", pwv, sizeof(pwv));
+ if (strcmp(pwin, pwv) != 0) {
+ ap_cpystrn(record, "password verification error", (rlen - 1));
+ return ERR_PWMISMATCH;
+ }
+ pw = pwin;
+ memset(pwv, '\0', sizeof(pwin));
+ }
+ switch (alg) {
+
+ case ALG_APSHA:
+ /* XXX cpw >= 28 + strlen(sha1) chars - fixed len SHA */
+ ap_sha1_base64(pw,strlen(pw),cpw);
+ break;
+
+ case ALG_APMD5:
+ (void) srand((int) time((time_t *) NULL));
+ ap_to64(&salt[0], rand(), 8);
+ salt[8] = '\0';
+
+ ap_MD5Encode((const unsigned char *)pw, (const unsigned char *)salt,
+ cpw, sizeof(cpw));
+ break;
+
+ case ALG_PLAIN:
+ /* XXX this len limitation is not in sync with any HTTPd len. */
+ ap_cpystrn(cpw,pw,sizeof(cpw));
+ break;
+
+ case ALG_CRYPT:
+ default:
+ (void) srand((int) time((time_t *) NULL));
+ ap_to64(&salt[0], rand(), 8);
+ salt[8] = '\0';
+
+ ap_cpystrn(cpw, (char *)crypt(pw, salt), sizeof(cpw) - 1);
+ break;
+ }
+ memset(pw, '\0', strlen(pw));
+
+ /*
+ * Check to see if the buffer is large enough to hold the username,
+ * hash, and delimiters.
+ */
+ if ((strlen(user) + 1 + strlen(cpw)) > (rlen - 1)) {
+ ap_cpystrn(record, "resultant record too long", (rlen - 1));
+ return ERR_OVERFLOW;
+ }
+ strcpy(record, user);
+ strcat(record, ":");
+ strcat(record, cpw);
+ return 0;
+}
-/* From local_passwd.c (C) Regents of Univ. of California blah blah */
-static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
-"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+static int usage(void)
+{
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\thtpasswd [-cmdps] passwordfile username\n");
+ fprintf(stderr, "\thtpasswd -b[cmdps] passwordfile username password\n\n");
+ fprintf(stderr, " -c Create a new file.\n");
+ fprintf(stderr, " -m Force MD5 encryption of the password"
+#if defined(WIN32) || defined(TPF)
+ " (default)"
+#endif
+ ".\n");
+ fprintf(stderr, " -d Force CRYPT encryption of the password"
+#if (!(defined(WIN32) || defined(TPF)))
+ " (default)"
+#endif
+ ".\n");
+ fprintf(stderr, " -p Do not encrypt the password (plaintext).\n");
+ fprintf(stderr, " -s Force SHA encryption of the password.\n");
+ fprintf(stderr, " -b Use the password from the command line rather "
+ "than prompting for it.\n");
+ fprintf(stderr,
+ "On Windows and TPF systems the '-m' flag is used by default.\n");
+ fprintf(stderr,
+ "On all other systems, the '-p' flag will probably not work.\n");
+ return ERR_SYNTAX;
+}
-static void to64(register char *s, register long v, register int n)
+static void interrupted(void)
{
- while (--n >= 0) {
- *s++ = itoa64[v & 0x3f];
- v >>= 6;
+ fprintf(stderr, "Interrupted.\n");
+ if (tempfilename != NULL) {
+ unlink(tempfilename);
}
+ exit(ERR_INTERRUPTED);
}
-#ifdef MPE
-/* MPE lacks getpass() and a way to suppress stdin echo. So for now, just
- * issue the prompt and read the results with echo. (Ugh).
+/*
+ * Check to see if the specified file can be opened for the given
+ * access.
*/
-
-static char *getpass(const char *prompt)
+static int accessible(char *fname, char *mode)
{
+ FILE *s;
- static char password[81];
-
- fputs(prompt, stderr);
- gets((char *) &password);
-
- if (strlen((char *) &password) > 8) {
- password[8] = '\0';
+ s = fopen(fname, mode);
+ if (s == NULL) {
+ return 0;
}
-
- return (char *) &password;
+ fclose(s);
+ return 1;
}
-#endif
+/*
+ * Return true if a file is readable.
+ */
+static int readable(char *fname)
+{
+ return accessible(fname, "r");
+}
-static void add_password(char *user, FILE *f)
+/*
+ * Return true if the specified file can be opened for write access.
+ */
+static int writable(char *fname)
{
- char *pw, *cpw, salt[3];
-
- pw = strd((char *) getpass("New password:"));
- if (strcmp(pw, (char *) getpass("Re-type new password:"))) {
- fprintf(stderr, "They don't match, sorry.\n");
- if (tn)
- unlink(tn);
- exit(1);
- }
- (void) srand((int) time((time_t *) NULL));
- to64(&salt[0], rand(), 2);
- salt[2] = '\0';
- cpw = (char *)crypt(pw, salt);
- free(pw);
- fprintf(f, "%s:%s\n", user, cpw);
+ return accessible(fname, "a");
}
-static void usage(void)
+/*
+ * Return true if the named file exists, regardless of permissions.
+ */
+static int exists(char *fname)
{
- fprintf(stderr, "Usage: htpasswd [-c] passwordfile username\n");
- fprintf(stderr, "The -c flag creates a new file.\n");
- exit(1);
+#ifdef WIN32
+ struct _stat sbuf;
+#else
+ struct stat sbuf;
+#endif
+ int check;
+
+#ifdef WIN32
+ check = _stat(fname, &sbuf);
+#else
+ check = stat(fname, &sbuf);
+#endif
+ return ((check == -1) && (errno == ENOENT)) ? 0 : 1;
}
-static void interrupted(void)
+/*
+ * Copy from the current position of one file to the current position
+ * of another.
+ */
+static void copy_file(FILE *target, FILE *source)
{
- fprintf(stderr, "Interrupted.\n");
- if (tn)
- unlink(tn);
- exit(1);
+ static char line[MAX_STRING_LEN];
+
+ while (fgets(line, sizeof(line), source) != NULL) {
+ fputs(line, target);
+ }
}
+/*
+ * Let's do it. We end up doing a lot of file opening and closing,
+ * but what do we care? This application isn't run constantly.
+ */
int main(int argc, char *argv[])
{
- FILE *tfp, *f;
+ FILE *ftemp = NULL;
+ FILE *fpw = NULL;
char user[MAX_STRING_LEN];
+ char password[MAX_STRING_LEN];
+ char record[MAX_STRING_LEN];
char line[MAX_STRING_LEN];
- char l[MAX_STRING_LEN];
- char w[MAX_STRING_LEN];
- char command[MAX_STRING_LEN];
- int found;
-
- tn = NULL;
- signal(SIGINT, (void (*)()) interrupted);
- if (argc == 4) {
- if (strcmp(argv[1], "-c"))
- usage();
- if (!(tfp = fopen(argv[2], "w+"))) {
- fprintf(stderr, "Could not open passwd file %s for writing.\n",
- argv[2]);
- perror("fopen");
- exit(1);
+ char pwfilename[MAX_STRING_LEN];
+ char *arg;
+ int found = 0;
+ int alg = ALG_CRYPT;
+ int newfile = 0;
+ int noninteractive = 0;
+ int i;
+ int args_left = 2;
+
+ tempfilename = NULL;
+ signal(SIGINT, (void (*)(int)) interrupted);
+
+ /*
+ * Preliminary check to make sure they provided at least
+ * three arguments, we'll do better argument checking as
+ * we parse the command line.
+ */
+ if (argc < 3) {
+ return usage();
+ }
+
+ /*
+ * Go through the argument list and pick out any options. They
+ * have to precede any other arguments.
+ */
+ for (i = 1; i < argc; i++) {
+ arg = argv[i];
+ if (*arg != '-') {
+ break;
+ }
+ while (*++arg != '\0') {
+ if (*arg == 'c') {
+ newfile++;
+ }
+ else if (*arg == 'm') {
+ alg = ALG_APMD5;
+ }
+ else if (*arg == 's') {
+ alg = ALG_APSHA;
+ }
+ else if (*arg == 'p') {
+ alg = ALG_PLAIN;
+ }
+ else if (*arg == 'd') {
+ alg = ALG_CRYPT;
+ }
+ else if (*arg == 'b') {
+ noninteractive++;
+ args_left++;
+ }
+ else {
+ return usage();
+ }
}
- printf("Adding password for %s.\n", argv[3]);
- add_password(argv[3], tfp);
- fclose(tfp);
- exit(0);
}
- else if (argc != 3)
- usage();
- tn = tmpnam(NULL);
- if (!(tfp = fopen(tn, "w+"))) {
- fprintf(stderr, "Could not open temp file.\n");
- exit(1);
+ /*
+ * Make sure we still have exactly the right number of arguments left
+ * (the filename, the username, and possibly the password if -b was
+ * specified).
+ */
+ if ((argc - i) != args_left) {
+ return usage();
+ }
+ if (strlen(argv[i]) > (sizeof(pwfilename) - 1)) {
+ fprintf(stderr, "%s: filename too long\n", argv[0]);
+ return ERR_OVERFLOW;
+ }
+ strcpy(pwfilename, argv[i]);
+ if (strlen(argv[i + 1]) > (sizeof(user) - 1)) {
+ fprintf(stderr, "%s: username too long (>%d)\n", argv[0],
+ sizeof(user) - 1);
+ return ERR_OVERFLOW;
+ }
+ strcpy(user, argv[i + 1]);
+ if ((arg = strchr(user, ':')) != NULL) {
+ fprintf(stderr, "%s: username contains illegal character '%c'\n",
+ argv[0], *arg);
+ return ERR_BADUSER;
+ }
+ if (noninteractive) {
+ if (strlen(argv[i + 2]) > (sizeof(password) - 1)) {
+ fprintf(stderr, "%s: password too long (>%d)\n", argv[0],
+ sizeof(password) - 1);
+ return ERR_OVERFLOW;
+ }
+ strcpy(password, argv[i + 2]);
}
- if (!(f = fopen(argv[1], "r+"))) {
- fprintf(stderr,
- "Could not open passwd file %s for reading.\n", argv[1]);
- fprintf(stderr, "Use -c option to create new one.\n");
- exit(1);
+#ifdef WIN32
+ if (alg == ALG_CRYPT) {
+ alg = ALG_APMD5;
+ fprintf(stderr, "Automatically using MD5 format on Windows.\n");
}
- strcpy(user, argv[2]);
+#endif
- found = 0;
- while (!(getline(line, MAX_STRING_LEN, f))) {
- if (found || (line[0] == '#') || (!line[0])) {
- putline(tfp, line);
- continue;
- }
- strcpy(l, line);
- getword(w, l, ':');
- if (strcmp(user, w)) {
- putline(tfp, line);
- continue;
- }
- else {
- printf("Changing password for user %s\n", user);
- add_password(user, tfp);
- found = 1;
+#if (!(defined(WIN32) || defined(TPF)))
+ if (alg == ALG_PLAIN) {
+ fprintf(stderr,"Warning: storing passwords as plain text might "
+ "just not work on this platform.\n");
+ }
+#endif
+ /*
+ * Verify that the file exists if -c was omitted. We give a special
+ * message if it doesn't.
+ */
+ if ((! newfile) && (! exists(pwfilename))) {
+ fprintf(stderr, "%s: cannot modify file %s; use '-c' to create it\n",
+ argv[0], pwfilename);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+ /*
+ * Verify that we can read the existing file in the case of an update
+ * to it (rather than creation of a new one).
+ */
+ if ((! newfile) && (! readable(pwfilename))) {
+ fprintf(stderr, "%s: cannot open file %s for read access\n",
+ argv[0], pwfilename);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+ /*
+ * Now check to see if we can preserve an existing file in case
+ * of password verification errors on a -c operation.
+ */
+ if (newfile && exists(pwfilename) && (! readable(pwfilename))) {
+ fprintf(stderr, "%s: cannot open file %s for read access\n"
+ "%s: existing auth data would be lost on password mismatch",
+ argv[0], pwfilename, argv[0]);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+ /*
+ * Now verify that the file is writable!
+ */
+ if (! writable(pwfilename)) {
+ fprintf(stderr, "%s: cannot open file %s for write access\n",
+ argv[0], pwfilename);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+
+ /*
+ * All the file access checks have been made. Time to go to work;
+ * try to create the record for the username in question. If that
+ * fails, there's no need to waste any time on file manipulations.
+ * Any error message text is returned in the record buffer, since
+ * the mkrecord() routine doesn't have access to argv[].
+ */
+ i = mkrecord(user, record, sizeof(record) - 1,
+ noninteractive ? password : NULL,
+ alg);
+ if (i != 0) {
+ fprintf(stderr, "%s: %s\n", argv[0], record);
+ exit(i);
+ }
+
+ /*
+ * We can access the files the right way, and we have a record
+ * to add or update. Let's do it..
+ */
+ tempfilename = tmpnam(NULL);
+ ftemp = fopen(tempfilename, "w+");
+ if (ftemp == NULL) {
+ fprintf(stderr, "%s: unable to create temporary file\n", argv[0]);
+ perror("fopen");
+ exit(ERR_FILEPERM);
+ }
+ /*
+ * If we're not creating a new file, copy records from the existing
+ * one to the temporary file until we find the specified user.
+ */
+ if (! newfile) {
+ char scratch[MAX_STRING_LEN];
+
+ fpw = fopen(pwfilename, "r");
+ while (! (getline(line, sizeof(line), fpw))) {
+ char *colon;
+
+ if ((line[0] == '#') || (line[0] == '\0')) {
+ putline(ftemp, line);
+ continue;
+ }
+ strcpy(scratch, line);
+ /*
+ * See if this is our user.
+ */
+ colon = strchr(scratch, ':');
+ if (colon != NULL) {
+ *colon = '\0';
+ }
+ if (strcmp(user, scratch) != 0) {
+ putline(ftemp, line);
+ continue;
+ }
+ found++;
+ break;
}
}
- if (!found) {
- printf("Adding user %s\n", user);
- add_password(user, tfp);
+ if (found) {
+ fprintf(stderr, "Updating ");
}
-/*
-* make a copy from the tmp file to the actual file
-*/
- rewind(f);
- rewind(tfp);
- while ( fgets(command,MAX_STRING_LEN,tfp) != NULL)
- {
- fputs(command,f);
- }
-
- fclose(f);
- fclose(tfp);
- unlink(tn);
- exit(0);
+ else {
+ fprintf(stderr, "Adding ");
+ }
+ fprintf(stderr, "password for user %s\n", user);
+ /*
+ * Now add the user record we created.
+ */
+ putline(ftemp, record);
+ /*
+ * If we're updating an existing file, there may be additional
+ * records beyond the one we're updating, so copy them.
+ */
+ if (! newfile) {
+ copy_file(ftemp, fpw);
+ fclose(fpw);
+ }
+ /*
+ * The temporary file now contains the information that should be
+ * in the actual password file. Close the open files, re-open them
+ * in the appropriate mode, and copy them file to the real one.
+ */
+ fclose(ftemp);
+ fpw = fopen(pwfilename, "w+");
+ ftemp = fopen(tempfilename, "r");
+ copy_file(fpw, ftemp);
+ fclose(fpw);
+ fclose(ftemp);
+ unlink(tempfilename);
+ return 0;
}
diff --git a/usr.sbin/httpd/src/support/htpasswd.dsp b/usr.sbin/httpd/src/support/htpasswd.dsp
new file mode 100644
index 00000000000..7949d7f7e82
--- /dev/null
+++ b/usr.sbin/httpd/src/support/htpasswd.dsp
@@ -0,0 +1,119 @@
+# Microsoft Developer Studio Project File - Name="htpasswd" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=htpasswd - 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 "htpasswd.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 "htpasswd.mak" CFG="htpasswd - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "htpasswd - Win32 Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "htpasswd - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "htpasswd - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "htpasswd - 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 /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "htpasswd - Win32 Release"
+# Name "htpasswd - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\ap\ap_cpystrn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_getpass.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_md5c.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_snprintf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_sha1.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_checkpass.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ap\ap_base64.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\htpasswd.c
+# End Source File
+# End Target
+# End Project
diff --git a/usr.sbin/httpd/src/support/htpasswd.mak b/usr.sbin/httpd/src/support/htpasswd.mak
new file mode 100644
index 00000000000..fa69fcd3503
--- /dev/null
+++ b/usr.sbin/httpd/src/support/htpasswd.mak
@@ -0,0 +1,550 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on htpasswd.dsp
+!IF "$(CFG)" == ""
+CFG=htpasswd - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to htpasswd - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "htpasswd - Win32 Release" && "$(CFG)" !=\
+ "htpasswd - 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 "htpasswd.mak" CFG="htpasswd - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "htpasswd - Win32 Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "htpasswd - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "htpasswd - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\htpasswd.exe"
+
+!ELSE
+
+ALL : "$(OUTDIR)\htpasswd.exe"
+
+!ENDIF
+
+CLEAN :
+ -@erase "$(INTDIR)\ap_cpystrn.obj"
+ -@erase "$(INTDIR)\ap_getpass.obj"
+ -@erase "$(INTDIR)\ap_md5c.obj"
+ -@erase "$(INTDIR)\ap_snprintf.obj"
+ -@erase "$(INTDIR)\ap_sha1.obj"
+ -@erase "$(INTDIR)\ap_checkpass.obj"
+ -@erase "$(INTDIR)\ap_base64.obj"
+ -@erase "$(INTDIR)\htpasswd.obj"
+ -@erase "$(INTDIR)\vc50.idb"
+ -@erase "$(OUTDIR)\htpasswd.exe"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "..\include" /D "NDEBUG" /D "WIN32" /D\
+ "_CONSOLE" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /Fp"$(INTDIR)\htpasswd.pch" /YX\
+ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+CPP_OBJS=.\Release/
+CPP_SBRS=.
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\htpasswd.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:console /incremental:no\
+ /pdb:"$(OUTDIR)\htpasswd.pdb" /machine:I386 /out:"$(OUTDIR)\htpasswd.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\ap_cpystrn.obj" \
+ "$(INTDIR)\ap_getpass.obj" \
+ "$(INTDIR)\ap_md5c.obj" \
+ "$(INTDIR)\ap_snprintf.obj" \
+ "$(INTDIR)\ap_sha1.obj" \
+ "$(INTDIR)\ap_checkpass.obj" \
+ "$(INTDIR)\ap_base64.obj" \
+ "$(INTDIR)\htpasswd.obj"
+
+"$(OUTDIR)\htpasswd.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\htpasswd.exe"
+
+!ELSE
+
+ALL : "$(OUTDIR)\htpasswd.exe"
+
+!ENDIF
+
+CLEAN :
+ -@erase "$(INTDIR)\ap_cpystrn.obj"
+ -@erase "$(INTDIR)\ap_getpass.obj"
+ -@erase "$(INTDIR)\ap_md5c.obj"
+ -@erase "$(INTDIR)\ap_snprintf.obj"
+ -@erase "$(INTDIR)\ap_sha1.obj"
+ -@erase "$(INTDIR)\ap_checkpass.obj"
+ -@erase "$(INTDIR)\ap_base64.obj"
+ -@erase "$(INTDIR)\htpasswd.obj"
+ -@erase "$(INTDIR)\vc50.idb"
+ -@erase "$(INTDIR)\vc50.pdb"
+ -@erase "$(OUTDIR)\htpasswd.exe"
+ -@erase "$(OUTDIR)\htpasswd.ilk"
+ -@erase "$(OUTDIR)\htpasswd.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /I "..\include" /D "_DEBUG" /D\
+ "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN"\
+ /Fp"$(INTDIR)\htpasswd.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+CPP_OBJS=.\Debug/
+CPP_SBRS=.
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\htpasswd.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:console /incremental:yes\
+ /pdb:"$(OUTDIR)\htpasswd.pdb" /debug /machine:I386\
+ /out:"$(OUTDIR)\htpasswd.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\ap_cpystrn.obj" \
+ "$(INTDIR)\ap_getpass.obj" \
+ "$(INTDIR)\ap_md5c.obj" \
+ "$(INTDIR)\ap_snprintf.obj" \
+ "$(INTDIR)\ap_sha1.obj" \
+ "$(INTDIR)\ap_checkpass.obj" \
+ "$(INTDIR)\ap_base64.obj" \
+ "$(INTDIR)\htpasswd.obj"
+
+"$(OUTDIR)\htpasswd.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+.c{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_OBJS)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_SBRS)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(CFG)" == "htpasswd - Win32 Release" || "$(CFG)" ==\
+ "htpasswd - Win32 Debug"
+SOURCE=..\ap\ap_cpystrn.c
+
+!IF "$(CFG)" == "htpasswd - Win32 Release"
+
+DEP_CPP_AP_CP=\
+ "..\include\alloc.h"\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_AP_CP=\
+ "..\include\ap_config_auto.h"\
+ "..\include\ebcdic.h"\
+ "..\include\os.h"\
+ "..\include\sfio.h"\
+
+
+"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) $(DEP_CPP_AP_CP) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug"
+
+DEP_CPP_AP_CP=\
+ "..\include\alloc.h"\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+
+
+"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) $(DEP_CPP_AP_CP) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ap\ap_getpass.c
+
+!IF "$(CFG)" == "htpasswd - Win32 Release"
+
+DEP_CPP_AP_GE=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_AP_GE=\
+ "..\include\ap_config_auto.h"\
+ "..\include\os.h"\
+
+
+"$(INTDIR)\ap_getpass.obj" : $(SOURCE) $(DEP_CPP_AP_GE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug"
+
+DEP_CPP_AP_GE=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+"$(INTDIR)\ap_getpass.obj" : $(SOURCE) $(DEP_CPP_AP_GE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ap\ap_md5c.c
+
+!IF "$(CFG)" == "htpasswd - Win32 Release"
+
+DEP_CPP_AP_MD=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_AP_MD=\
+ "..\ap\ebcdic.h"\
+ "..\include\ap_config_auto.h"\
+ "..\include\os.h"\
+
+
+"$(INTDIR)\ap_md5c.obj" : $(SOURCE) $(DEP_CPP_AP_MD) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug"
+
+DEP_CPP_AP_MD=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+"$(INTDIR)\ap_md5c.obj" : $(SOURCE) $(DEP_CPP_AP_MD) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ap\ap_snprintf.c
+
+!IF "$(CFG)" == "htpasswd - Win32 Release"
+
+DEP_CPP_AP_SN=\
+ "..\include\alloc.h"\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_AP_SN=\
+ "..\include\ap_config_auto.h"\
+ "..\include\ebcdic.h"\
+ "..\include\os.h"\
+ "..\include\sfio.h"\
+
+
+"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) $(DEP_CPP_AP_SN) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug"
+
+DEP_CPP_AP_SN=\
+ "..\include\alloc.h"\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\buff.h"\
+ "..\include\hsregex.h"\
+ "..\include\httpd.h"\
+ "..\include\util_uri.h"\
+ "..\os\win32\os.h"\
+ "..\os\win32\readdir.h"\
+
+
+"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) $(DEP_CPP_AP_SN) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ap\ap_sha1.c
+
+!IF "$(CFG)" == "htpasswd - Win32 Release"
+
+DEP_CPP_AP_SH=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_sha1.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_AP_SH=\
+ "..\ap\ebcdic.h"\
+ "..\include\ap_config_auto.h"\
+ "..\include\os.h"\
+
+
+"$(INTDIR)\ap_sha1.obj" : $(SOURCE) $(DEP_CPP_AP_SH) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug"
+
+DEP_CPP_AP_SH=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_sha1.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+"$(INTDIR)\ap_sha1.obj" : $(SOURCE) $(DEP_CPP_AP_SH) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ap\ap_checkpass.c
+
+!IF "$(CFG)" == "htpasswd - Win32 Release"
+
+DEP_CPP_AP_CH=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_AP_CH=\
+ "..\ap\ebcdic.h"\
+ "..\include\ap_config_auto.h"\
+ "..\include\os.h"\
+
+
+"$(INTDIR)\ap_checkpass.obj" : $(SOURCE) $(DEP_CPP_AP_CH) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug"
+
+DEP_CPP_AP_CH=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+"$(INTDIR)\ap_checkpass.obj" : $(SOURCE) $(DEP_CPP_AP_CH) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ap\ap_base64.c
+
+!IF "$(CFG)" == "htpasswd - Win32 Release"
+
+DEP_CPP_AP_BA=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_AP_BA=\
+ "..\ap\ebcdic.h"\
+ "..\include\ap_config_auto.h"\
+ "..\include\os.h"\
+
+
+"$(INTDIR)\ap_base64.obj" : $(SOURCE) $(DEP_CPP_AP_BA) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug"
+
+DEP_CPP_AP_BA=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\os.h"\
+
+
+"$(INTDIR)\ap_base64.obj" : $(SOURCE) $(DEP_CPP_AP_BA) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\htpasswd.c
+
+!IF "$(CFG)" == "htpasswd - Win32 Release"
+
+DEP_CPP_HTPAS=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\getopt.h"\
+ "..\os\win32\os.h"\
+ {$(INCLUDE)}"sys\stat.h"\
+ {$(INCLUDE)}"sys\types.h"\
+
+NODEP_CPP_HTPAS=\
+ "..\include\ap_config_auto.h"\
+ "..\include\os.h"\
+
+
+"$(INTDIR)\htpasswd.obj" : $(SOURCE) $(DEP_CPP_HTPAS) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug"
+
+DEP_CPP_HTPAS=\
+ "..\include\ap.h"\
+ "..\include\ap_config.h"\
+ "..\include\ap_ctype.h"\
+ "..\include\ap_md5.h"\
+ "..\include\ap_mmn.h"\
+ "..\include\hsregex.h"\
+ "..\os\win32\getopt.h"\
+ "..\os\win32\os.h"\
+
+
+"$(INTDIR)\htpasswd.obj" : $(SOURCE) $(DEP_CPP_HTPAS) "$(INTDIR)"
+
+
+!ENDIF
+
+
+!ENDIF
+
diff --git a/usr.sbin/httpd/src/support/httpd.8 b/usr.sbin/httpd/src/support/httpd.8
index d5edaab9a21..ae320bad2ad 100644
--- a/usr.sbin/httpd/src/support/httpd.8
+++ b/usr.sbin/httpd/src/support/httpd.8
@@ -7,7 +7,7 @@
.\" are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
+.\" notice, this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in
@@ -56,7 +56,7 @@
.SH NAME
httpd \- Apache hypertext transfer protocol server
.SH SYNOPSIS
-.B httpd
+.B httpd
[
.B \-X
] [
@@ -73,51 +73,57 @@ httpd \- Apache hypertext transfer protocol server
.BI \-D " parameter"
]
-.B httpd
+.B httpd
[
.B \-h
-]
+]
[
.B \-l
-]
+]
[
.B \-L
-]
+]
[
.B \-v
-]
+]
[
.B \-V
-]
+]
[
.B \-S
+]
+[
+.B \-t
+]
+[
+.B \-T
]
.SH DESCRIPTION
.B httpd
is the Apache HyperText Transfer Protocol (HTTP) server program. It is
designed to be run as a standalone daemon process. When used like this
-is will create a pool of child processes to handle requests. To stop
+it will create a pool of child processes to handle requests. To stop
it, send a TERM signal to the initial (parent) process. The PID of
this process is written to a file as given in the configuration file.
-Alternatively
-.B httpd
+Alternatively
+.B httpd
may be invoked by the Internet daemon inetd(8) each
time a connection to the HTTP service is made.
.PP
This manual page only lists the command line arguments. For details
-of the directives necessary to configure
+of the directives necessary to configure
.B httpd
see the Apache manual,
which is part of the Apache distribution or can be found at
http://www.apache.org/. Paths in this manual may not reflect those
-compiled into
+compiled into
.B httpd.
.SH OPTIONS
.TP 12
.BI \-R " libexecdir"
This option is only available if Apache was built with
-the
+the
.I SHARED_CORE
rule enabled which forces the Apache core code to be
placed into a dynamic shared object (DSO) file. This file
@@ -164,18 +170,23 @@ Run syntax tests for configuration files only. The program immediately exits
after these syntax parsing with either a return code of 0 (Syntax OK) or
return code not equal to 0 (Syntax Error).
.TP
+.B \-T
+Same as option
+.B \-t
+but does not check the configured document roots.
+.TP
.B \-X
Run in single-process mode, for internal debugging purposes only; the daemon
does not detach from the terminal or fork any children. Do NOT use this mode
to provide ordinary web service.
.TP
.B \-v
-Print the version of
+Print the version of
.B httpd
, and then exit.
.TP
.B \-V
-Print the version and build parameters of
+Print the version and build parameters of
.B httpd
, and then exit.
.SH FILES
diff --git a/usr.sbin/httpd/src/support/httpd.exp b/usr.sbin/httpd/src/support/httpd.exp
index 63faaa3fbea..083d981a4a3 100644
--- a/usr.sbin/httpd/src/support/httpd.exp
+++ b/usr.sbin/httpd/src/support/httpd.exp
@@ -1,7 +1,12 @@
#!
+ap_MD5Encode
ap_MD5Final
ap_MD5Init
ap_MD5Update
+ap_SHA1Final
+ap_SHA1Init
+ap_SHA1Update_binary
+ap_SHA1Update
ap_add_cgi_vars
ap_add_common_vars
ap_add_module
@@ -16,6 +21,12 @@ ap_array_cat
ap_array_pstrcat
ap_auth_name
ap_auth_type
+ap_base64encode
+ap_base64encode_binary
+ap_base64encode_len
+ap_base64decode
+ap_base64decode_binary
+ap_base64decode_len
ap_basic_http_header
ap_bclose
ap_bcreate
@@ -99,12 +110,14 @@ ap_excess_requests_per_child
ap_exists_config_define
ap_exists_scoreboard_image
ap_extended_status
+ap_field_noparam
ap_finalize_request_protocol
ap_finalize_sub_req_protocol
ap_find_command
ap_find_command_in_modules
ap_find_last_token
ap_find_linked_module
+ap_find_list_item
ap_find_module_name
ap_find_path_info
ap_find_token
@@ -115,6 +128,7 @@ ap_force_library_loading
ap_get_basic_auth_pw
ap_get_client_block
ap_get_gmtoff
+ap_get_list_item
ap_get_local_host
ap_get_remote_host
ap_get_remote_logname
@@ -203,7 +217,6 @@ ap_null_cleanup
ap_open_logs
ap_open_piped_log
ap_os_escape_path
-ap_os_is_filename_valid
ap_os_is_path_absolute
ap_overlay_tables
ap_overlap_tables
@@ -214,6 +227,8 @@ ap_parse_htaccess
ap_parse_uri
ap_parse_uri_components
ap_parse_vhost_addrs
+ap_pbase64decode
+ap_pbase64encode
ap_pcalloc
ap_pcfg_open_custom
ap_pcfg_openfile
@@ -246,6 +261,8 @@ ap_pvsprintf
ap_rationalize_mtime
ap_read_config
ap_read_request
+ap_regerror
+ap_regexec
ap_register_cleanup
ap_register_other_child
ap_remove_module
@@ -283,6 +300,7 @@ ap_send_http_trace
ap_send_mmap
ap_send_size
ap_server_argv0
+ap_server_config_defines
ap_server_confname
ap_server_post_read_config
ap_server_pre_read_config
@@ -302,12 +320,13 @@ ap_set_string_slot_lower
ap_set_sub_req_protocol
ap_setup_client_block
ap_setup_prelinked_modules
+ap_sha1_base64
ap_should_client_block
ap_show_directives
ap_show_modules
ap_signal
ap_single_module_configure
-ap_single_module_init
+ap_size_list_item
ap_slack
ap_snprintf
ap_soft_timeout
@@ -322,6 +341,7 @@ ap_strcasecmp_match
ap_strcmp_match
ap_sub_req_lookup_file
ap_sub_req_lookup_uri
+ap_sub_req_method_uri
ap_suexec_enabled
ap_sync_scoreboard_image
ap_table_add
@@ -350,12 +370,48 @@ ap_user_name
ap_util_init
ap_util_uri_init
ap_uudecode
+ap_validate_password
ap_vbprintf
ap_vformatter
ap_vsnprintf
core_module
top_module
+XML_DefaultCurrent
+XML_ErrorString
+XML_ExternalEntityParserCreate
+XML_GetBase
+XML_GetBuffer
+XML_GetCurrentByteCount
+XML_GetCurrentByteIndex
+XML_GetCurrentColumnNumber
+XML_GetCurrentLineNumber
+XML_GetErrorCode
+XML_GetSpecifiedAttributeCount
+XML_Parse
+XML_ParseBuffer
+XML_ParserCreate
+XML_ParserCreateNS
+XML_ParserFree
+XML_SetBase
+XML_SetCdataSectionHandler
+XML_SetCharacterDataHandler
+XML_SetCommentHandler
+XML_SetDefaultHandler
+XML_SetDefaultHandlerExpand
+XML_SetElementHandler
+XML_SetEncoding
+XML_SetExternalEntityRefHandler
+XML_SetExternalEntityRefHandlerArg
+XML_SetNamespaceDeclHandler
+XML_SetNotStandaloneHandler
+XML_SetNotationDeclHandler
+XML_SetProcessingInstructionHandler
+XML_SetUnknownEncodingHandler
+XML_SetUnparsedEntityDeclHandler
+XML_SetUserData
+XML_UseParserAsHandlerArg
ap_add_config_define
+ap_make_shared_sub_pool
ap_global_ctx
ap_ctx_new
ap_ctx_get
@@ -368,3 +424,45 @@ ap_hook_unregister_I
ap_hook_status
ap_hook_use
ap_hook_call
+ap_mm_useable
+ap_MM_create
+ap_MM_permission
+ap_MM_destroy
+ap_MM_lock
+ap_MM_unlock
+ap_MM_malloc
+ap_MM_realloc
+ap_MM_free
+ap_MM_calloc
+ap_MM_strdup
+ap_MM_sizeof
+ap_MM_maxsize
+ap_MM_available
+ap_MM_error
+ap_mm_create
+ap_mm_permission
+ap_mm_destroy
+ap_mm_lock
+ap_mm_unlock
+ap_mm_malloc
+ap_mm_realloc
+ap_mm_free
+ap_mm_calloc
+ap_mm_strdup
+ap_mm_sizeof
+ap_mm_maxsize
+ap_mm_available
+ap_mm_error
+ap_mm_display_info
+ap_mm_core_create
+ap_mm_core_permission
+ap_mm_core_delete
+ap_mm_core_size
+ap_mm_core_lock
+ap_mm_core_unlock
+ap_mm_core_maxsegsize
+ap_mm_core_align2page
+ap_mm_core_align2word
+ap_mm_lib_error_set
+ap_mm_lib_error_get
+ap_mm_lib_version
diff --git a/usr.sbin/httpd/src/support/log_server_status b/usr.sbin/httpd/src/support/log_server_status
index 694247dd8b3..1eb2893edcd 100644
--- a/usr.sbin/httpd/src/support/log_server_status
+++ b/usr.sbin/httpd/src/support/log_server_status
@@ -67,7 +67,7 @@
#
require 'sys/socket.ph';
-$wherelog = "/var/log/graph/"; # Logs will be like "/var/log/graph/960312"
+$wherelog = "/var/log/graph/"; # Logs will be like "/var/log/graph/19960312"
$server = "localhost"; # Name of server, could be "www.foo.com"
$port = "80"; # Port on server
$request = "/status/?auto"; # Request to send
@@ -93,8 +93,11 @@ sub tcp_connect
### Main
{
- $date=`date +%y%m%d:%H%M%S`;
- chop($date);
+ $year=`date +%y`;
+ chomp($year);
+ $year += ($year < 70) ? 2000 : 1900;
+ $date = $year . `date +%m%d:%H%M%S`;
+ chomp($date);
($day,$time)=split(/:/,$date);
$res=&tcp_connect($server,$port);
open(OUT,">>$wherelog$day");
diff --git a/usr.sbin/httpd/src/support/logresolve.8 b/usr.sbin/httpd/src/support/logresolve.8
index 9f12271820f..4851269ad61 100644
--- a/usr.sbin/httpd/src/support/logresolve.8
+++ b/usr.sbin/httpd/src/support/logresolve.8
@@ -6,7 +6,7 @@
.\" are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
+.\" notice, this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in
@@ -59,7 +59,7 @@ logresolve \- resolve hostnames for IP-adresses in Apache logfiles
.BI \-s " filename"
] [
.B \-c
-] <
+] <
.I access_log
>
.I access_log.new
@@ -75,9 +75,9 @@ up the first time it is found in the log file.
.BI \-s " filename"
Specifies a filename to record statistics.
.TP 12
-.B \-c
-This causes
-.B logresolve
+.B \-c
+This causes
+.B logresolve
to apply some DNS checks: after finding the hostname from the IP address, it
looks up the IP addresses for the hostname and checks that one of these
matches the original address.
diff --git a/usr.sbin/httpd/src/support/mkcert.sh b/usr.sbin/httpd/src/support/mkcert.sh
index 26b4506e024..0008ddc702e 100644
--- a/usr.sbin/httpd/src/support/mkcert.sh
+++ b/usr.sbin/httpd/src/support/mkcert.sh
@@ -7,21 +7,23 @@
# parameters
make="$1"
mflags="$2"
-ssleay="$3"
+openssl="$3"
support="$4"
type="$5"
-crt="$6"
-key="$7"
+algo="$6"
+crt="$7"
+key="$8"
+view="$9"
# we can operate only inside the Apache 1.3 source
-# tree and only when mod_ssl+SSLeay is actually configured.
+# tree and only when mod_ssl+OpenSSL is actually configured.
if [ ! -f "../README.configure" ]; then
echo "mkcert.sh:Error: Cannot operate outside the Apache 1.3 source tree." 1>&2
echo "mkcert.sh:Hint: You have to stay inside apache_1.3.x/src." 1>&2
exit 1
fi
-if [ ".$ssleay" = . ]; then
- echo "mkcert.sh:Error: mod_ssl/SSLeay has to be configured before using this utility." 1>&2
+if [ ".$openssl" = . ]; then
+ echo "mkcert.sh:Error: mod_ssl/OpenSSL has to be configured before using this utility." 1>&2
echo "mkcert.sh:Hint: Configure mod_ssl with --enable-module=ssl in APACI, first." 1>&2
exit 1
fi
@@ -31,6 +33,7 @@ fi
sslcrtdir="../conf/ssl.crt"
sslcsrdir="../conf/ssl.csr"
sslkeydir="../conf/ssl.key"
+sslprmdir="../conf/ssl.prm"
# some optional terminal sequences
case $TERM in
@@ -50,12 +53,48 @@ esac
# display header
echo "${T_MD}SSL Certificate Generation Utility${T_ME} (mkcert.sh)"
-echo "Copyright (c) 1998 Ralf S. Engelschall, All Rights Reserved."
+echo "Copyright (c) 1998-1999 Ralf S. Engelschall, All Rights Reserved."
+
+# on request view certificates only
+if [ ".$view" != . ]; then
+ if [ -f "$sslcrtdir/ca.crt" -a -f "$sslkeydir/ca.key" ]; then
+ echo ""
+ echo "${T_MD}CA X.509 Certificate${T_ME} [ca.crt]"
+ echo "______________________________________________________________________"
+ $openssl x509 -noout -text -in $sslcrtdir/ca.crt
+ echo ""
+ if [ ".`$openssl x509 -noout -text -in $sslcrtdir/ca.crt | grep "Signature Algorithm" | grep -i RSA`" != . ]; then
+ echo "${T_MD}CA RSA Private Key${T_ME} [ca.key]"
+ echo "______________________________________________________________________"
+ $openssl rsa -noout -text -in $sslkeydir/ca.key
+ else
+ echo "${T_MD}CA DSA Private Key${T_ME} [ca.key]"
+ echo "______________________________________________________________________"
+ $openssl dsa -noout -text -in $sslkeydir/ca.key
+ fi
+ fi
+ if [ -f "$sslcrtdir/server.crt" -a -f "$sslkeydir/server.key" ]; then
+ echo ""
+ echo "${T_MD}Server X.509 Certificate${T_ME} [server.crt]"
+ echo "______________________________________________________________________"
+ $openssl x509 -noout -text -in $sslcrtdir/server.crt
+ echo ""
+ if [ ".`$openssl x509 -noout -text -in $sslcrtdir/server.crt | grep "Signature Algorithm" | grep -i RSA`" != . ]; then
+ echo "${T_MD}Server RSA Private Key${T_ME} [server.key]"
+ echo "______________________________________________________________________"
+ $openssl rsa -noout -text -in $sslkeydir/server.key
+ else
+ echo "${T_MD}Server DSA Private Key${T_ME} [server.key]"
+ echo "______________________________________________________________________"
+ $openssl dsa -noout -text -in $sslkeydir/server.key
+ fi
+ fi
+ exit 0
+fi
# find some random files
# (do not use /dev/random here, because this device
# doesn't work as expected on all platforms)
-echo " + finding random files on your platform"
randfiles=''
for file in /var/log/messages /var/adm/messages \
/kernel /vmunix /vmlinuz \
@@ -69,22 +108,23 @@ for file in /var/log/messages /var/adm/messages \
fi
done
-# on-demand compile the ca-fix only
-case $type in
- test|custom)
- cd $support
- if [ ! -f ca-fix ]; then
- echo " + building ca-fix auxiliary tool"
- $make $mflags ca-fix >/dev/null 2>&1
- if [ $? -ne 0 ]; then
- $make $mflags ca-fix
- echo "**FAILED"
- exit 1
- fi
- fi
- cd ..
- cafix="$support/ca-fix"
- ;;
+# canonicalize parameters
+case "x$type" in
+ x ) type=test ;;
+esac
+case "x$algo" in
+ xRSA|xrsa )
+ algo=RSA
+ ;;
+ xDSA|xdsa )
+ algo=DSA
+ ;;
+ x )
+ algo=choose
+ ;;
+ * ) echo "Unknown algorithm \'$algo' (use RSA or DSA!)" 1>&2
+ exit 1
+ ;;
esac
# processing
@@ -95,17 +135,25 @@ case $type in
echo "${T_MD}Generating self-signed Snake Oil certificate [DUMMY]${T_ME}"
echo "______________________________________________________________________"
echo ""
- cp $sslcrtdir/snakeoil.crt $sslcrtdir/server.crt
- cp $sslkeydir/snakeoil.key $sslkeydir/server.key
+ if [ ".$algo" = .choose ]; then
+ algo=RSA
+ fi
+ if [ ".$algo" = .RSA ]; then
+ cp $sslcrtdir/snakeoil-rsa.crt $sslcrtdir/server.crt
+ cp $sslkeydir/snakeoil-rsa.key $sslkeydir/server.key
+ else
+ cp $sslcrtdir/snakeoil-dsa.crt $sslcrtdir/server.crt
+ cp $sslkeydir/snakeoil-dsa.key $sslkeydir/server.key
+ fi
echo "${T_MD}RESULT: Server Certification Files${T_ME}"
echo ""
echo "o ${T_MD}conf/ssl.key/server.key${T_ME}"
- echo " The PEM-encoded RSA private certificate file which you configure"
+ echo " The PEM-encoded $algo private key file which you configure"
echo " with the 'SSLCertificateKeyFile' directive (automatically done"
echo " when you install via APACI). ${T_MD}KEEP THIS FILE PRIVATE!${T_ME}"
echo ""
echo "o ${T_MD}conf/ssl.crt/server.crt${T_ME}"
- echo " The PEM-encoded X.509 server certificate file which you configure"
+ echo " The PEM-encoded X.509 certificate file which you configure"
echo " with the 'SSLCertificateFile' directive (automatically done"
echo " when you install via APACI)."
echo ""
@@ -117,23 +165,58 @@ case $type in
echo ""
echo "${T_MD}Generating test certificate signed by Snake Oil CA [TEST]${T_ME}"
echo "WARNING: Do not use this for real-life/production systems"
+ if [ ".$algo" = .choose ]; then
+ echo "______________________________________________________________________"
+ echo ""
+ echo "${T_MD}STEP 0: Decide the signature algorithm used for certificate${T_ME}"
+ echo "The generated X.509 CA certificate can contain either"
+ echo "RSA or DSA based ingredients. Select the one you want to use."
+ def1=R def2=r def=RSA
+ prompt="Signature Algorithm ((R)SA or (D)SA) [$def1]:"
+ while [ 1 ]; do
+ echo dummy | awk '{ printf("%s", prompt); }' "prompt=$prompt"
+ read algo
+ if [ ".$algo" = ".$def1" -o ".$algo" = ".$def2" -o ".$algo" = . ]; then
+ algo=$def
+ break
+ elif [ ".$algo" = ".R" -o ".$algo" = ".r" ]; then
+ algo=RSA
+ break
+ elif [ ".$algo" = ".D" -o ".$algo" = ".d" ]; then
+ algo=DSA
+ break
+ else
+ echo "mkcert.sh:Warning: Invalid selection" 1>&2
+ fi
+ done
+ fi
echo "______________________________________________________________________"
echo ""
- echo "${T_MD}STEP 1: Generating RSA private key (1024 bit) [server.key]${T_ME}"
+ echo "${T_MD}STEP 1: Generating $algo private key (1024 bit) [server.key]${T_ME}"
if [ ! -f $HOME/.rnd ]; then
touch $HOME/.rnd
fi
- if [ ".$randfiles" != . ]; then
- $ssleay genrsa -rand $randfiles \
- -out $sslkeydir/server.key \
- 1024
+ if [ ".$algo" = .RSA ]; then
+ if [ ".$randfiles" != . ]; then
+ $openssl genrsa -rand $randfiles -out $sslkeydir/server.key 1024
+ else
+ $openssl genrsa -out $sslkeydir/server.key 1024
+ fi
+ if [ $? -ne 0 ]; then
+ echo "mkcert.sh:Error: Failed to generate RSA private key" 1>&2
+ exit 1
+ fi
else
- $ssleay genrsa -out $sslkeydir/server.key \
- 1024
- fi
- if [ $? -ne 0 ]; then
- echo "mkcert.sh:Error: Failed to generate RSA private key" 1>&2
- exit 1
+ echo "Generating DSA private key via SnakeOil CA DSA parameters"
+ if [ ".$randfiles" != . ]; then
+ $openssl gendsa -rand $randfiles -out $sslkeydir/server.key $sslprmdir/snakeoil-ca-dsa.prm
+ else
+ $openssl gendsa -out $sslkeydir/server.key $sslprmdir/snakeoil-ca-dsa.prm
+ fi
+ if [ $? -ne 0 ]; then
+ echo "mkcert.sh:Error: Failed to generate DSA private key" 1>&2
+ exit 1
+ fi
fi
echo "______________________________________________________________________"
echo ""
@@ -162,10 +245,10 @@ emailAddress = "7. Email Address (eg, name@FQDN)"
emailAddress_max = 40
emailAddress_default = www@snakeoil.dom
EOT
- $ssleay req -config .mkcert.cfg \
- -new \
- -key $sslkeydir/server.key \
- -out $sslcsrdir/server.csr
+ $openssl req -config .mkcert.cfg \
+ -new \
+ -key $sslkeydir/server.key \
+ -out $sslcsrdir/server.csr
if [ $? -ne 0 ]; then
echo "mkcert.sh:Error: Failed to generate certificate signing request" 1>&2
exit 1
@@ -176,64 +259,66 @@ EOT
echo "${T_MD}STEP 3: Generating X.509 certificate signed by Snake Oil CA [server.crt]${T_ME}"
echo dummy | awk '{ printf("%s", prompt); }' "prompt=Certificate Version (1 or 3) [3]:"
read certversion
+ extfile=""
if [ ".$certversion" = .3 -o ".$certversion" = . ]; then
- certversion=3
- else
- certversion=1
+ extfile="-extfile .mkcert.cfg"
+ cat >.mkcert.cfg <<EOT
+extensions = x509v3
+[ x509v3 ]
+subjectAltName = email:copy
+nsComment = "mod_ssl generated test server certificate"
+nsCertType = server
+EOT
fi
if [ ! -f .mkcert.serial ]; then
echo '01' >.mkcert.serial
fi
- $ssleay x509 -days 365 \
- -CAserial .mkcert.serial \
- -CA $sslcrtdir/snakeoil-ca.crt \
- -CAkey $sslkeydir/snakeoil-ca.key \
- -in $sslcsrdir/server.csr -req \
- -out $sslcrtdir/server.crt
+ if [ ".$algo" = .RSA ]; then
+ $openssl x509 $extfile \
+ -days 365 \
+ -CAserial .mkcert.serial \
+ -CA $sslcrtdir/snakeoil-ca-rsa.crt \
+ -CAkey $sslkeydir/snakeoil-ca-rsa.key \
+ -in $sslcsrdir/server.csr -req \
+ -out $sslcrtdir/server.crt
+ else
+ $openssl x509 $extfile \
+ -days 365 \
+ -CAserial .mkcert.serial \
+ -CA $sslcrtdir/snakeoil-ca-dsa.crt \
+ -CAkey $sslkeydir/snakeoil-ca-dsa.key \
+ -in $sslcsrdir/server.csr -req \
+ -out $sslcrtdir/server.crt
+ fi
if [ $? -ne 0 ]; then
echo "mkcert.sh:Error: Failed to generate X.509 certificate" 1>&2
exit 1
fi
- if [ ".$certversion" = .3 ]; then
- echo "Converting X.509 v1 to v3 certificate"
- $cafix -nscertype 0x40 \
- -nobscrit \
- -nosign \
- -in $sslcrtdir/server.crt \
- -inkey $sslkeydir/server.key \
- -out $sslcrtdir/server.crt.fixed
- if [ $? -ne 0 ]; then
- echo "mkcert.sh:Error: Failed to fixup X.509 certificate contents" 1>&2
- exit 1
- fi
- cp $sslcrtdir/server.crt.fixed $sslcrtdir/server.crt
- rm -f $sslcrtdir/server.crt.fixed
- $cafix -inkey $sslkeydir/snakeoil-ca.key \
- -in $sslcrtdir/server.crt \
- -out $sslcrtdir/server.crt.fixed
- if [ $? -ne 0 ]; then
- echo "mkcert.sh:Error: Failed to fixup X.509 certificate signature" 1>&2
- exit 1
- fi
- cp $sslcrtdir/server.crt.fixed $sslcrtdir/server.crt
- rm -f $sslcrtdir/server.crt.fixed
- fi
+ rm -f .mkcert.cfg
echo "Verify: matching certificate & key modulus"
- modcrt=`$ssleay x509 -noout -modulus -in $sslcrtdir/server.crt`
- modkey=`$ssleay rsa -noout -modulus -in $sslkeydir/server.key`
+ modcrt=`$openssl x509 -noout -modulus -in $sslcrtdir/server.crt | sed -e 's;.*Modulus=;;'`
+ if [ ".$algo" = .RSA ]; then
+ modkey=`$openssl rsa -noout -modulus -in $sslkeydir/server.key | sed -e 's;.*Modulus=;;'`
+ else
+ modkey=`$openssl dsa -noout -modulus -in $sslkeydir/server.key | sed -e 's;.*Key=;;'`
+ fi
if [ ".$modcrt" != ".$modkey" ]; then
echo "mkcert.sh:Error: Failed to verify modulus on resulting X.509 certificate" 1>&2
exit 1
fi
echo "Verify: matching certificate signature"
- $ssleay verify -CAfile $sslcrtdir/snakeoil-ca.crt $sslcrtdir/server.crt
+ if [ ".$algo" = .RSA ]; then
+ $openssl verify -CAfile $sslcrtdir/snakeoil-ca-rsa.crt $sslcrtdir/server.crt
+ else
+ $openssl verify -CAfile $sslcrtdir/snakeoil-ca-dsa.crt $sslcrtdir/server.crt
+ fi
if [ $? -ne 0 ]; then
echo "mkcert.sh:Error: Failed to verify signature on resulting X.509 certificate" 1>&2
exit 1
fi
echo "______________________________________________________________________"
echo ""
- echo "${T_MD}STEP 4: Enrypting RSA private key with a pass phrase for security [server.key]${T_ME}"
+ echo "${T_MD}STEP 4: Enrypting $algo private key with a pass phrase for security [server.key]${T_ME}"
echo "The contents of the server.key file (the generated private key) has to be"
echo "kept secret. So we strongly recommend you to encrypt the server.key file"
echo "with a Triple-DES cipher and a Pass Phrase."
@@ -250,18 +335,24 @@ EOT
fi
done
if [ ".$rc" = .y ]; then
- $ssleay rsa -des3 \
- -in $sslkeydir/server.key \
- -out $sslkeydir/server.key.crypt
+ if [ ".$algo" = .RSA ]; then
+ $openssl rsa -des3 \
+ -in $sslkeydir/server.key \
+ -out $sslkeydir/server.key.crypt
+ else
+ $openssl dsa -des3 \
+ -in $sslkeydir/server.key \
+ -out $sslkeydir/server.key.crypt
+ fi
if [ $? -ne 0 ]; then
- echo "mkcert.sh:Error: Failed to encrypt RSA private key" 1>&2
+ echo "mkcert.sh:Error: Failed to encrypt $algo private key" 1>&2
exit 1
fi
cp $sslkeydir/server.key.crypt $sslkeydir/server.key
rm -f $sslkeydir/server.key.crypt
- echo "Fine, you're using an encrypted private key."
+ echo "Fine, you're using an encrypted $algo private key."
else
- echo "Warning, you're using an unencrypted private key."
+ echo "Warning, you're using an unencrypted $algo private key."
echo "Please notice this fact and do this on your own risk."
fi
echo "______________________________________________________________________"
@@ -269,12 +360,12 @@ EOT
echo "${T_MD}RESULT: Server Certification Files${T_ME}"
echo ""
echo "o ${T_MD}conf/ssl.key/server.key${T_ME}"
- echo " The PEM-encoded RSA private certificate file which you configure"
+ echo " The PEM-encoded $algo private key file which you configure"
echo " with the 'SSLCertificateKeyFile' directive (automatically done"
echo " when you install via APACI). ${T_MD}KEEP THIS FILE PRIVATE!${T_ME}"
echo ""
echo "o ${T_MD}conf/ssl.crt/server.crt${T_ME}"
- echo " The PEM-encoded X.509 server certificate file which you configure"
+ echo " The PEM-encoded X.509 certificate file which you configure"
echo " with the 'SSLCertificateFile' directive (automatically done"
echo " when you install via APACI)."
echo ""
@@ -292,23 +383,61 @@ EOT
custom)
echo ""
echo "${T_MD}Generating custom certificate signed by own CA [CUSTOM]${T_ME}"
+ if [ ".$algo" = .choose ]; then
+ echo "______________________________________________________________________"
+ echo ""
+ echo "${T_MD}STEP 0: Decide the signature algorithm used for certificates${T_ME}"
+ echo "The generated X.509 certificates can contain either"
+ echo "RSA or DSA based ingredients. Select the one you want to use."
+ def1=R def2=r def=RSA
+ prompt="Signature Algorithm ((R)SA or (D)SA) [$def1]:"
+ while [ 1 ]; do
+ echo dummy | awk '{ printf("%s", prompt); }' "prompt=$prompt"
+ read algo
+ if [ ".$algo" = ".$def1" -o ".$algo" = ".$def2" -o ".$algo" = . ]; then
+ algo=$def
+ break
+ elif [ ".$algo" = ".R" -o ".$algo" = ".r" ]; then
+ algo=RSA
+ break
+ elif [ ".$algo" = ".D" -o ".$algo" = ".d" ]; then
+ algo=DSA
+ break
+ else
+ echo "mkcert.sh:Warning: Invalid selection" 1>&2
+ fi
+ done
+ fi
echo "______________________________________________________________________"
echo ""
- echo "${T_MD}STEP 1: Generating RSA private key for CA (1024 bit) [ca.key]${T_ME}"
+ echo "${T_MD}STEP 1: Generating $algo private key for CA (1024 bit) [ca.key]${T_ME}"
if [ ! -f $HOME/.rnd ]; then
touch $HOME/.rnd
fi
- if [ ".$randfiles" != . ]; then
- $ssleay genrsa -rand $randfiles \
- -out $sslkeydir/ca.key \
- 1024
+ if [ ".$algo" = .RSA ]; then
+ if [ ".$randfiles" != . ]; then
+ $openssl genrsa -rand $randfiles -out $sslkeydir/ca.key 1024
+ else
+ $openssl genrsa -out $sslkeydir/ca.key 1024
+ fi
+ if [ $? -ne 0 ]; then
+ echo "mkcert.sh:Error: Failed to generate RSA private key" 1>&2
+ exit 1
+ fi
else
- $ssleay genrsa -out $sslkeydir/ca.key \
- 1024
- fi
- if [ $? -ne 0 ]; then
- echo "mkcert.sh:Error: Failed to generate RSA private key" 1>&2
- exit 1
+ if [ ".$randfiles" != . ]; then
+ $openssl dsaparam -rand $randfiles -out $sslprmdir/ca.prm 1024
+ echo "Generating DSA private key:"
+ $openssl gendsa -rand $randfiles -out $sslkeydir/ca.key $sslprmdir/ca.prm
+ else
+ $openssl dsaparam -out $sslprmdir/ca.prm 1024
+ echo "Generating DSA private key:"
+ $openssl gendsa -out $sslkeydir/ca.key $sslprmdir/ca.prm
+ fi
+ if [ $? -ne 0 ]; then
+ echo "mkcert.sh:Error: Failed to generate DSA private key" 1>&2
+ exit 1
+ fi
fi
echo "______________________________________________________________________"
echo ""
@@ -337,10 +466,10 @@ emailAddress = "7. Email Address (eg, name@FQDN)"
emailAddress_max = 40
emailAddress_default = ca@snakeoil.dom
EOT
- $ssleay req -config .mkcert.cfg \
- -new \
- -key $sslkeydir/ca.key \
- -out $sslcsrdir/ca.csr
+ $openssl req -config .mkcert.cfg \
+ -new \
+ -key $sslkeydir/ca.key \
+ -out $sslcsrdir/ca.csr
if [ $? -ne 0 ]; then
echo "mkcert.sh:Error: Failed to generate certificate signing request" 1>&2
exit 1
@@ -351,64 +480,71 @@ EOT
echo "${T_MD}STEP 3: Generating X.509 certificate for CA signed by itself [ca.crt]${T_ME}"
echo dummy | awk '{ printf("%s", prompt); }' "prompt=Certificate Version (1 or 3) [3]:"
read certversion
+ extfile=""
if [ ".$certversion" = .3 -o ".$certversion" = . ]; then
- certversion=3
- else
- certversion=1
+ extfile="-extfile .mkcert.cfg"
+ cat >.mkcert.cfg <<EOT
+extensions = x509v3
+[ x509v3 ]
+subjectAltName = email:copy
+basicConstraints = CA:true,pathlen:0
+nsComment = "mod_ssl generated custom CA certificate"
+nsCertType = sslCA
+EOT
fi
- $ssleay x509 -days 365 \
- -signkey $sslkeydir/ca.key \
- -in $sslcsrdir/ca.csr -req \
- -out $sslcrtdir/ca.crt
+ $openssl x509 $extfile \
+ -days 365 \
+ -signkey $sslkeydir/ca.key \
+ -in $sslcsrdir/ca.csr -req \
+ -out $sslcrtdir/ca.crt
if [ $? -ne 0 ]; then
echo "mkcert.sh:Error: Failed to generate self-signed CA certificate" 1>&2
exit 1
fi
- if [ ".$certversion" = .3 ]; then
- $cafix -caset \
- -nscertype 0x07 \
- -pathlen 0 \
- -nobscrit \
- -in $sslcrtdir/ca.crt \
- -inkey $sslkeydir/ca.key \
- -out $sslcrtdir/ca.crt.fixed
- if [ $? -ne 0 ]; then
- echo "mkcert.sh:Error: Failed to fixup X.509 CA certificate" 1>&2
- exit 1
- fi
- cp $sslcrtdir/ca.crt.fixed $sslcrtdir/ca.crt
- rm -f $sslcrtdir/ca.crt.fixed
- fi
+ rm -f .mkcert.cfg
echo "Verify: matching certificate & key modulus"
- modcrt=`$ssleay x509 -noout -modulus -in $sslcrtdir/ca.crt`
- modkey=`$ssleay rsa -noout -modulus -in $sslkeydir/ca.key`
+ modcrt=`$openssl x509 -noout -modulus -in $sslcrtdir/ca.crt | sed -e 's;.*Modulus=;;'`
+ if [ ".$algo" = .RSA ]; then
+ modkey=`$openssl rsa -noout -modulus -in $sslkeydir/ca.key | sed -e 's;.*Modulus=;;'`
+ else
+ modkey=`$openssl dsa -noout -modulus -in $sslkeydir/ca.key | sed -e 's;.*Key=;;'`
+ fi
if [ ".$modcrt" != ".$modkey" ]; then
echo "mkcert.sh:Error: Failed to verify modulus on resulting X.509 certificate" 1>&2
exit 1
fi
echo "Verify: matching certificate signature"
- $ssleay verify $sslcrtdir/ca.crt
+ $openssl verify $sslcrtdir/ca.crt
if [ $? -ne 0 ]; then
echo "mkcert.sh:Error: Failed to verify signature on resulting X.509 certificate" 1>&2
exit 1
fi
echo "______________________________________________________________________"
echo ""
- echo "${T_MD}STEP 4: Generating RSA private key for SERVER (1024 bit) [server.key]${T_ME}"
+ echo "${T_MD}STEP 4: Generating $algo private key for SERVER (1024 bit) [server.key]${T_ME}"
if [ ! -f $HOME/.rnd ]; then
touch $HOME/.rnd
fi
- if [ ".$randfiles" != . ]; then
- $ssleay genrsa -rand $randfiles \
- -out $sslkeydir/server.key \
- 1024
+ if [ ".$algo" = .RSA ]; then
+ if [ ".$randfiles" != . ]; then
+ $openssl genrsa -rand $randfiles -out $sslkeydir/server.key 1024
+ else
+ $openssl genrsa -out $sslkeydir/server.key 1024
+ fi
+ if [ $? -ne 0 ]; then
+ echo "mkcert.sh:Error: Failed to generate RSA private key" 1>&2
+ exit 1
+ fi
else
- $ssleay genrsa -out $sslkeydir/server.key \
- 1024
- fi
- if [ $? -ne 0 ]; then
- echo "mkcert.sh:Error: Failed to generate RSA private key" 1>&2
- exit 1
+ if [ ".$randfiles" != . ]; then
+ $openssl gendsa -rand $randfiles -out $sslkeydir/server.key $sslprmdir/ca.prm
+ else
+ $openssl gendsa -out $sslkeydir/server.key $sslprmdir/ca.prm
+ fi
+ if [ $? -ne 0 ]; then
+ echo "mkcert.sh:Error: Failed to generate DSA private key" 1>&2
+ exit 1
+ fi
fi
echo "______________________________________________________________________"
echo ""
@@ -437,10 +573,10 @@ emailAddress = "7. Email Address (eg, name@fqdn)"
emailAddress_max = 40
emailAddress_default = www@snakeoil.dom
EOT
- $ssleay req -config .mkcert.cfg \
- -new \
- -key $sslkeydir/server.key \
- -out $sslcsrdir/server.csr
+ $openssl req -config .mkcert.cfg \
+ -new \
+ -key $sslkeydir/server.key \
+ -out $sslcsrdir/server.csr
if [ $? -ne 0 ]; then
echo "mkcert.sh:Error: Failed to generate certificate signing request" 1>&2
exit 1
@@ -451,63 +587,52 @@ EOT
echo "${T_MD}STEP 6: Generating X.509 certificate signed by own CA [server.crt]${T_ME}"
echo dummy | awk '{ printf("%s", prompt); }' "prompt=Certificate Version (1 or 3) [3]:"
read certversion
+ extfile=""
if [ ".$certversion" = .3 -o ".$certversion" = . ]; then
- certversion=3
- else
- certversion=1
+ extfile="-extfile .mkcert.cfg"
+ cat >.mkcert.cfg <<EOT
+extensions = x509v3
+[ x509v3 ]
+subjectAltName = email:copy
+nsComment = "mod_ssl generated custom server certificate"
+nsCertType = server
+EOT
fi
if [ ! -f .mkcert.serial ]; then
echo '01' >.mkcert.serial
fi
- $ssleay x509 -days 365 \
- -CAserial .mkcert.serial \
- -CA $sslcrtdir/ca.crt \
- -CAkey $sslkeydir/ca.key \
- -in $sslcsrdir/server.csr -req \
- -out $sslcrtdir/server.crt
+ $openssl x509 $extfile \
+ -days 365 \
+ -CAserial .mkcert.serial \
+ -CA $sslcrtdir/ca.crt \
+ -CAkey $sslkeydir/ca.key \
+ -in $sslcsrdir/server.csr -req \
+ -out $sslcrtdir/server.crt
if [ $? -ne 0 ]; then
echo "mkcert.sh:Error: Failed to generate X.509 certificate" 1>&2
exit 1
fi
- if [ ".$certversion" = .3 ]; then
- $cafix -nscertype 0x40 \
- -nobscrit \
- -nosign \
- -in $sslcrtdir/server.crt \
- -inkey $sslkeydir/server.key \
- -out $sslcrtdir/server.crt.fixed
- if [ $? -ne 0 ]; then
- echo "mkcert.sh:Error: Failed to fixup X.509 certificate contents" 1>&2
- exit 1
- fi
- cp $sslcrtdir/server.crt.fixed $sslcrtdir/server.crt
- rm -f $sslcrtdir/server.crt.fixed
- $cafix -inkey $sslkeydir/ca.key \
- -in $sslcrtdir/server.crt \
- -out $sslcrtdir/server.crt.fixed
- if [ $? -ne 0 ]; then
- echo "mkcert.sh:Error: Failed to fixup X.509 certificate signature" 1>&2
- exit 1
- fi
- cp $sslcrtdir/server.crt.fixed $sslcrtdir/server.crt
- rm -f $sslcrtdir/server.crt.fixed
- fi
+ rm -f .mkcert.cfg
echo "Verify: matching certificate & key modulus"
- modcrt=`$ssleay x509 -noout -modulus -in $sslcrtdir/server.crt`
- modkey=`$ssleay rsa -noout -modulus -in $sslkeydir/server.key`
+ modcrt=`$openssl x509 -noout -modulus -in $sslcrtdir/server.crt | sed -e 's;.*Modulus=;;'`
+ if [ ".$algo" = .RSA ]; then
+ modkey=`$openssl rsa -noout -modulus -in $sslkeydir/server.key | sed -e 's;.*Modulus=;;'`
+ else
+ modkey=`$openssl dsa -noout -modulus -in $sslkeydir/server.key | sed -e 's;.*Key=;;'`
+ fi
if [ ".$modcrt" != ".$modkey" ]; then
echo "mkcert.sh:Error: Failed to verify modulus on resulting X.509 certificate" 1>&2
exit 1
fi
echo "Verify: matching certificate signature"
- $ssleay verify -CAfile $sslcrtdir/ca.crt $sslcrtdir/server.crt
+ $openssl verify -CAfile $sslcrtdir/ca.crt $sslcrtdir/server.crt
if [ $? -ne 0 ]; then
echo "mkcert.sh:Error: Failed to verify signature on resulting X.509 certificate" 1>&2
exit 1
fi
echo "______________________________________________________________________"
echo ""
- echo "${T_MD}STEP 7: Enrypting RSA private key of CA with a pass phrase for security [ca.key]${T_ME}"
+ echo "${T_MD}STEP 7: Enrypting $algo private key of CA with a pass phrase for security [ca.key]${T_ME}"
echo "The contents of the ca.key file (the generated private key) has to be"
echo "kept secret. So we strongly recommend you to encrypt the server.key file"
echo "with a Triple-DES cipher and a Pass Phrase."
@@ -524,11 +649,17 @@ EOT
fi
done
if [ ".$rc" = .y ]; then
- $ssleay rsa -des3 \
- -in $sslkeydir/ca.key \
- -out $sslkeydir/ca.key.crypt
+ if [ ".$algo" = .RSA ]; then
+ $openssl rsa -des3 \
+ -in $sslkeydir/ca.key \
+ -out $sslkeydir/ca.key.crypt
+ else
+ $openssl dsa -des3 \
+ -in $sslkeydir/ca.key \
+ -out $sslkeydir/ca.key.crypt
+ fi
if [ $? -ne 0 ]; then
- echo "mkcert.sh:Error: Failed to encrypt RSA private key" 1>&2
+ echo "mkcert.sh:Error: Failed to encrypt $algo private key" 1>&2
exit 1
fi
cp $sslkeydir/ca.key.crypt $sslkeydir/ca.key
@@ -540,7 +671,7 @@ EOT
fi
echo "______________________________________________________________________"
echo ""
- echo "${T_MD}STEP 8: Enrypting RSA private key of SERVER with a pass phrase for security [server.key]${T_ME}"
+ echo "${T_MD}STEP 8: Enrypting $algo private key of SERVER with a pass phrase for security [server.key]${T_ME}"
echo "The contents of the server.key file (the generated private key) has to be"
echo "kept secret. So we strongly recommend you to encrypt the server.key file"
echo "with a Triple-DES cipher and a Pass Phrase."
@@ -557,46 +688,52 @@ EOT
fi
done
if [ ".$rc" = .y ]; then
- $ssleay rsa -des3 \
- -in $sslkeydir/server.key \
- -out $sslkeydir/server.key.crypt
+ if [ ".$algo" = .RSA ]; then
+ $openssl rsa -des3 \
+ -in $sslkeydir/server.key \
+ -out $sslkeydir/server.key.crypt
+ else
+ $openssl dsa -des3 \
+ -in $sslkeydir/server.key \
+ -out $sslkeydir/server.key.crypt
+ fi
if [ $? -ne 0 ]; then
- echo "mkcert.sh:Error: Failed to encrypt RSA private key" 1>&2
+ echo "mkcert.sh:Error: Failed to encrypt $algo private key" 1>&2
exit 1
fi
cp $sslkeydir/server.key.crypt $sslkeydir/server.key
rm -f $sslkeydir/server.key.crypt
- echo "Fine, you're using an encrypted private key."
+ echo "Fine, you're using an encrypted $algo private key."
else
- echo "Warning, you're using an unencrypted private key."
+ echo "Warning, you're using an unencrypted $algo private key."
echo "Please notice this fact and do this on your own risk."
fi
echo "______________________________________________________________________"
echo ""
- echo "${T_MD}RESULT: Server and CA Certification Files${T_ME}"
+ echo "${T_MD}RESULT: CA and Server Certification Files${T_ME}"
echo ""
echo "o ${T_MD}conf/ssl.key/ca.key${T_ME}"
- echo " The PEM-encoded RSA private certificate file of the CA which you can"
+ echo " The PEM-encoded $algo private key file of the CA which you can"
echo " use to sign other servers or clients. ${T_MD}KEEP THIS FILE PRIVATE!${T_ME}"
echo ""
echo "o ${T_MD}conf/ssl.crt/ca.crt${T_ME}"
- echo " The PEM-encoded X.509 CA server certificate file which you use to"
+ echo " The PEM-encoded X.509 certificate file of the CA which you use to"
echo " sign other servers or clients. When you sign clients with it (for"
echo " SSL client authentication) you can configure this file with the"
echo " 'SSLCACertificateFile' directive."
echo ""
echo "o ${T_MD}conf/ssl.key/server.key${T_ME}"
- echo " The PEM-encoded RSA private certificate file which you configure"
+ echo " The PEM-encoded $algo private key file of the server which you configure"
echo " with the 'SSLCertificateKeyFile' directive (automatically done"
echo " when you install via APACI). ${T_MD}KEEP THIS FILE PRIVATE!${T_ME}"
echo ""
echo "o ${T_MD}conf/ssl.crt/server.crt${T_ME}"
- echo " The PEM-encoded X.509 server certificate file which you configure"
+ echo " The PEM-encoded X.509 certificate file of the server which you configure"
echo " with the 'SSLCertificateFile' directive (automatically done"
echo " when you install via APACI)."
echo ""
echo "o ${T_MD}conf/ssl.csr/server.csr${T_ME}"
- echo " The PEM-encoded X.509 certificate signing request file which"
+ echo " The PEM-encoded X.509 certificate signing request of the server file which"
echo " you can send to an official Certificate Authority (CA) in order"
echo " to request a real server certificate (signed by this CA instead"
echo " of our own CA) which later can replace the conf/ssl.crt/server.crt"
@@ -630,23 +767,28 @@ EOT
key=$crt
sed -e '/-----BEGIN CERTIFICATE/,/-----END CERTIFICATE/p' -e '/.*/d' \
<$crt >$sslcrtdir/server.crt
- sed -e '/-----BEGIN RSA PRIVATE KEY/,/-----END RSA PRIVATE KEY/p' -e '/.*/d' \
+ sed -e '/-----BEGIN ... PRIVATE KEY/,/-----END ... PRIVATE KEY/p' -e '/.*/d' \
<$key >$sslkeydir/server.key
fi
- $ssleay x509 -noout -in $sslcrtdir/server.crt
+ $openssl x509 -noout -in $sslcrtdir/server.crt
if [ $? -ne 0 ]; then
echo "mkcert.sh:Error: Failed to check certificate contents: $crt" 1>&2
exit 1
fi
+ if [ ".`grep 'PRIVATE KEY' $sslkeydir/server.key | grep RSA`" != . ]; then
+ algo=RSA
+ else
+ algo=DSA
+ fi
echo "${T_MD}RESULT: Server Certification Files${T_ME}"
echo ""
echo "o ${T_MD}conf/ssl.key/server.key${T_ME}"
- echo " The PEM-encoded RSA private certificate file which you configure"
+ echo " The PEM-encoded $algo private key file which you configure"
echo " with the 'SSLCertificateKeyFile' directive (automatically done"
echo " when you install via APACI). ${T_MD}KEEP THIS FILE PRIVATE!${T_ME}"
echo ""
echo "o ${T_MD}conf/ssl.crt/server.crt${T_ME}"
- echo " The PEM-encoded X.509 server certificate file which you configure"
+ echo " The PEM-encoded X.509 certificate file which you configure"
echo " with the 'SSLCertificateFile' directive (automatically done"
echo " when you install via APACI)."
echo ""
diff --git a/usr.sbin/httpd/src/support/rotatelogs.8 b/usr.sbin/httpd/src/support/rotatelogs.8
index 2f08ce62cf4..aee02e11ecd 100644
--- a/usr.sbin/httpd/src/support/rotatelogs.8
+++ b/usr.sbin/httpd/src/support/rotatelogs.8
@@ -6,7 +6,7 @@
.\" are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
+.\" notice, this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in
diff --git a/usr.sbin/httpd/src/support/suexec.8 b/usr.sbin/httpd/src/support/suexec.8
index cc5a8db585b..801d7abce91 100644
--- a/usr.sbin/httpd/src/support/suexec.8
+++ b/usr.sbin/httpd/src/support/suexec.8
@@ -6,7 +6,7 @@
.\" are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
+.\" notice, this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in
@@ -55,7 +55,7 @@
suexec \- Switch User For Exec
.SH SYNOPSIS
No synopsis for usage, because this program
-is used internally by Apache only.
+is used internally by Apache only.
.PP
.SH DESCRIPTION
.B suexec
diff --git a/usr.sbin/httpd/src/support/suexec.c b/usr.sbin/httpd/src/support/suexec.c
index 45fdf0d021b..2ab326321f7 100644
--- a/usr.sbin/httpd/src/support/suexec.c
+++ b/usr.sbin/httpd/src/support/suexec.c
@@ -145,6 +145,7 @@ char *safe_env_lst[] =
"SCRIPT_URL",
"SERVER_ADMIN",
"SERVER_NAME",
+ "SERVER_ADDR",
"SERVER_PORT",
"SERVER_PROTOCOL",
"SERVER_SOFTWARE",
@@ -347,6 +348,33 @@ int main(int argc, char *argv[])
actual_gname = strdup(target_gname);
}
+#ifdef _OSD_POSIX
+ /*
+ * Initialize BS2000 user environment
+ */
+ {
+ pid_t pid;
+ int status;
+
+ switch (pid = ufork(target_uname))
+ {
+ case -1: /* Error */
+ log_err("failed to setup bs2000 environment for user %s: %s\n",
+ target_uname, strerror(errno));
+ exit(150);
+ case 0: /* Child */
+ break;
+ default: /* Father */
+ while (pid != waitpid(pid, &status, 0))
+ ;
+ /* @@@ FIXME: should we deal with STOP signals as well? */
+ if (WIFSIGNALED(status))
+ kill (getpid(), WTERMSIG(status));
+ exit(WEXITSTATUS(status));
+ }
+ }
+#endif /*_OSD_POSIX*/
+
/*
* Save these for later since initgroups will hose the struct
*/
@@ -520,7 +548,16 @@ int main(int argc, char *argv[])
/*
* Execute the command, replacing our image with its own.
*/
+#ifdef NEED_HASHBANG_EMUL
+ /* We need the #! emulation when we want to execute scripts */
+ {
+ extern char **environ;
+
+ ap_execve(cmd, &argv[3], environ);
+ }
+#else /*NEED_HASHBANG_EMUL*/
execv(cmd, &argv[3]);
+#endif /*NEED_HASHBANG_EMUL*/
/*
* (I can't help myself...sorry.)