diff options
Diffstat (limited to 'usr.sbin/httpd/src')
55 files changed, 2378 insertions, 1646 deletions
diff --git a/usr.sbin/httpd/src/ApacheCore.def b/usr.sbin/httpd/src/ApacheCore.def index 8b15418d123..7e878c4466d 100644 --- a/usr.sbin/httpd/src/ApacheCore.def +++ b/usr.sbin/httpd/src/ApacheCore.def @@ -444,6 +444,9 @@ EXPORTS ap_recvwithtimeout @436 ap_caret_escape_args @437 ap_double_quotes @438 + ap_getline @439 + ap_get_chunk_size @440 + ap_escape_logitem @441 ; EAPI extended symbols ; note; no ID's, so these all bind by name rather than ordinal since diff --git a/usr.sbin/httpd/src/ApacheCoreOS2.def b/usr.sbin/httpd/src/ApacheCoreOS2.def index cc765613a48..a2b6139cce7 100644 --- a/usr.sbin/httpd/src/ApacheCoreOS2.def +++ b/usr.sbin/httpd/src/ApacheCoreOS2.def @@ -371,3 +371,60 @@ EXPORTS ap_is_rdirectory @365 ap_stripprefix @366 ap_child_terminate @367 + ap_getline @368 + ap_get_chunk_size @369 + ap_os_dso_load @381 + ap_os_dso_error @382 + ap_update_vhost_from_headers @383 + ap_update_vhost_given_ip @384 + ap_set_name_virtual_host @385 + ap_parse_vhost_addrs @386 + ap_fini_vhost_config @387 + ap_init_vhost_config @388 + ap_check_access @389 + ap_check_auth @390 + ap_check_user_id @391 + ap_translate_name @392 + ap_run_fixups @394 + ap_invoke_handler @395 + ap_log_transaction @396 + ap_header_parse @397 + ap_run_post_read_request @398 + ap_init_modules @400 + ap_child_init_modules @401 + ap_child_exit_modules @402 + ap_setup_prelinked_modules @403 + ap_show_directives @404 + ap_show_modules @405 + ap_parse_htaccess @406 + ap_process_resource_config @407 + ap_create_request_config @408 + ap_merge_per_dir_configs @409 + ap_bind_address @410 + ap_core_reorder_directories @411 + ap_coredump_dir @412 + ap_finalize_sub_req_protocol @413 + ap_force_library_loading @414 + ap_get_local_host @415 + ap_get_virthost_addr @416 + ap_init_alloc @417 + ap_keepalive_timeout @418 + ap_listenbacklog @419 + ap_lock_fname @420 + ap_log_pid @421 + ap_open_logs @422 + ap_process_request @423 + ap_read_config @424 + ap_read_request @425 + ap_response_code_string @426 + ap_rfc1413 @427 + ap_send_http_options @428 + ap_server_config_defines @429 + ap_server_post_read_config @430 + ap_server_pre_read_config @431 + ap_set_callback_and_alarm @432 + ap_set_sub_req_protocol @433 + ap_update_child_status @434 + ap_caret_escape_args @437 + ap_double_quotes @438 + ap_escape_logitem @441 diff --git a/usr.sbin/httpd/src/CHANGES b/usr.sbin/httpd/src/CHANGES index 3b6063e03da..962f0aa5d5f 100644 --- a/usr.sbin/httpd/src/CHANGES +++ b/usr.sbin/httpd/src/CHANGES @@ -1,12 +1,122 @@ +Changes with Apache 1.3.26 + + *) Potential NULL referencing fixed in the CGI module. It had + been there for 5 years. [Justin Erenkrantz] + + *) Ensure that we set the result value in ap_strtol before + we return it. [The whole gang again] + +Changes with Apache 1.3.25 + + *) Code changes required to address and close the security + issues in CAN-2002-0392 (mitre.org) [CERT VU#944335]. + To support this, we utilize the ANSI functionality of + strtol, and provide ap_strtol for completeness. + [The whole gang] + + *) PORT: With OpenBSD 3.1 and up, allow modules to work on their + ELF-based architectures. [Brad <brad@openbsd.org>] + + *) Add X-Forwarded-Host and X-Forwarded-Server to X-Forwarded-For + to the proxy. [Thomas Eibner <thomas@stderr.net>] + + *) Fix a problem in mod_proxy: it would not set the number of bytes + transferred, so other modules could not access the value from + the request_rec->bytes_sent field. + [Anthony Howe <achowe at snert.com>] PR#6841 + + *) Fix a problem in mod_rewrite which would lead to 400 Bad Request + responses for rewriting rules which resulted in a local path. + Note: This will also reject invalid requests like + "HEAD /roaming/martin/IMAP localhost HTTP/1.0" as issued by + Netscape-4.x Roaming Profiles (on a DAV-enabled server) + [Martin Kraemer] + + *) Disallow anything but whitespace on the request line after the + HTTP/x.y protocol string. That prevents arbitrary user input + from ending up in the access_log and error_log. Also, special + characters (especially control characters) are escaped in the + log file now, to make a clear distinction between client-supplied + strings (with special characters) and server-side strings. + [Martin Kraemer] + + *) Get rid of DEFAULT_XFERLOG as it is not used anywhere. It was + preserved by the build system, printed with "httpd -V", but + apart from that completely ignored: the default transfer log + is to not produce any transfer log. + [Martin Kraemer] + + *) Fixed sending of binary files under Cygwin. PR 9185. + [Cliff Woolley] + + *) Added Cygwin directory layout to config.layout file. + [Stipe Tolj, <tolj@wapme-systems.de>] + + *) Added a '-F' flag; which causes the mother/supervisor process to + no longer fork down and detach. But instead stays attached to + the tty - thus making live for automatic restart and exit checking + code easier. [ Contributed by Michael Handler <handler@grendel.net>, + Jos Backus <jos@catnook.com> [ Dirk-Willem van Gulik ]]. + + *) Make apxs.pl more flexible (file extensions like .so or .dll are + no longer hardcoded). [Stipe Tolj <tolj@wapme-systems.de>] + + *) Add an intelligent error message should no proxy submodules be + valid to handle a request. PR 8407 [Graham Leggett] + + *) Allow child processes sufficient time for cleanups but making + ap_select in reclaim_child_processes more "resistant" to + signal interupts. Bugz# 8176 + [David Winterbourne <davidw@financenter.com>, Jim Jagielski] + + *) Recognize platform specific root directories (other than + leading slash) in mod_rewrite for filename rewrite rules. + Bugz# 7492 [William Rowe] + + *) For supported versions of Darwin, place dynamically loaded + Apache extensions' public symbols into the global symbol + table. This allows dynamically loaded PHP extensions. + [Marko Karppinen <markonen@php.net>] + + *) Correct proxy to be able to handle the unexpected 100-continue + reponses sent during PUT or POST requests. [Graham Leggett] + + *) Correct a timeout problem within proxy which would force long + or slow POST requests to close after 300 seconds. + [Martin Lichtin <martin@lichtin.net>, Brian Bothwell + <brian.bothwell@wisdomtools.com>] + + *) Add support for dechunking chunked responses in proxy. + [Graham Leggett] + + *) Made AB's use of the Host: header rfc2616 compliant + by Taisuke Yamada <tai@iij.ad.jp> [Dirl-Willem van Gulik]. + + *) Update the Red Hat Layout to match Red Hat Linux version 7. + PR BZ-7422 [Joe Orton] + + *) Add some popular types to the mime magic file. PR 7730. + [Linus Walleij <triad@df.lth.se>, Justin Erenkrantz] + + *) Tighten up the overridden-Server-header bugfix in the proxy, by + only overriding if the request is a proxy request. It has been + pointed out that the previous fix allows CGIs and modules to + override the Server header, which is change to previous behavior. + [Graham Leggett, Joshua Slive] + + *) Another fix for the multiple-cookie header bug in proxy. With some + luck this bug is actually now dead. [Graham Leggett] + Changes with Apache 1.3.24 *) Fixed a segfault in mod_include when #if, #elif, #else, or #endif directives were improperly terminated. [Cliff Woolley] - *) Introduce proper escaping of command.com and cmd.exe for Win32. + *) Win32 Security: CAN-2002-0061 + Introduce proper escaping of command.com and cmd.exe for Win32. These patches close vulnerability CAN-2002-0061, identified and reported by Ory Segal <ory.segal@sanctuminc>, by which any CGI - invocation of .bat or .cmd files could comprimize the system + invocation of .bat or .cmd files could compromise the system when the .bat or .cmd was parsed the query args as an argument to either cmd.exe /c or command.com /c. [William Rowe] @@ -574,7 +684,7 @@ Changes with Apache 1.3.21 to make results more true to what is measured. The upshot of this it turns out that 'ab' has often underreported the true performance of apache. Often by a order of magnitude :-) See talk/paper of Sander - Temme <sctemme@covalent.net> at April ApacheCon 2001 for details. + Temme at April ApacheCon 2001 for details. [Dirk-Willem van Gulik] Changes with Apache 1.3.20 @@ -582,7 +692,7 @@ Changes with Apache 1.3.20 *) Autodetect if platforms have isnan() and/or isinf() for use in ap_snprintf.c. [Jim Jagielski] - *) Correct a vulnerability in the Win32 and OS2 ports, by which a + *) Security/DoS: Correct a vulnerability in the Win32 and OS2 ports, by which a client submitting a carefully constructed URI could cause a GP (segment) fault in the child process, which would have to be cleared by the operator to resume operation. This vulnerability @@ -722,7 +832,7 @@ Changes with Apache 1.3.18 [not released] *) SECURITY: The default installation could lead to mod_negotiation and mod_dir/mod_autoindex displaying a directory listing instead of the index.html.* files, if a very long path was created artificially - by using many slashes. Now a 403 FORBIDDEN is returned. + by using many slashes. Now a 403 FORBIDDEN is returned. CAN-2001-0925. [Martin Kraemer] *) Trailing slashes (if they exist) are now removed from ServerRoot, @@ -991,7 +1101,7 @@ Changes with Apache 1.3.13 [not released] tree, and other minor MPE tweaks. [Mark Bixby <mark_bixby@hp.com>] - *) Tighten up the syntax checking of Host: headers to fix a + *) Security: Tighten up the syntax checking of Host: headers to fix a security bug in some mass virtual hosting configurations that can allow a remote attacker to retrieve some files on the system that should be inaccessible. [Tony Finch] @@ -1004,7 +1114,8 @@ Changes with Apache 1.3.13 [not released] SHA1 and plaintext password encodings. Make feature tests a bit more flexible. [William Rowe] - *) Fix a security problem that affects some configurations of + *) Security: CVE-2000-0913 + Fix a security problem that affects some configurations of mod_rewrite. If the result of a RewriteRule is a filename that contains expansion specifiers, especially regexp backreferences $0..$9 and %0..%9, then it may have been possible for an attacker @@ -1239,7 +1350,7 @@ Changes with Apache 1.3.13 [not released] *) [EBCDIC] Update mod_mmap_static so that an ebcdic box can use MMapFile for files that shouldn't be converted from ebcdic->ascii. - [Greg Ames <gregames@us.ibm.com>] + [Greg Ames] *) Revamp the Win32 make environment. Apache.dsw created to bring together all the pieces. Create new file os/win32/BaseAddr.ref @@ -4323,7 +4434,7 @@ Changes with Apache 1.3b7 *) Just having APACI's localstatedir is too general and not enough for most of the systems. 1.3b6 again required manual APACI patches by package - maintainers from RedHat and FreeBSD because for their filesystem layout a + maintainers from Red Hat and FreeBSD because for their filesystem layout a little bit more flexibility in configuring the paths is needed. Hence we provide three additional configure options (--runtimedir, --logfiledir, --proxycachedir) which now can be used for more granular adjustments if @@ -4333,7 +4444,7 @@ Changes with Apache 1.3b7 *) Make the install root for "make install" in APACI's Makefile overrideable by package authors. This way we are even more friendly to package - maintainers (especially Debian and RedHat) who build for the real prefix + maintainers (especially Debian and Red Hat) who build for the real prefix via "configure --prefix=/<real>" but use a different local prefix via "make root=/tmp/apache install" for rolling the package without bristling the target location on their system. diff --git a/usr.sbin/httpd/src/CHANGES.SSL b/usr.sbin/httpd/src/CHANGES.SSL index d84b96b9f4b..da9c699b186 100644 --- a/usr.sbin/httpd/src/CHANGES.SSL +++ b/usr.sbin/httpd/src/CHANGES.SSL @@ -23,6 +23,35 @@ / __/ | (_) | __ |_____(_)___/ ___________________________________________ + Changes with mod_ssl 2.8.10 (19-Jun-2002 to 24-Jun-2002) + + *) Fixed off-by-one buffer overflow bug in the compatibility + functionality (mapping of old directives to new ones). + + *) Fixed memory leak in processing of CA certificates. + + *) In case there is actually a certificate chain in the session cache, + we now use the value of SSL_get_peer_certificate(ssl) to verify as + it will have been removed from the chain before it was put in the + cache. + + *) Seed the PRNG with a maximum of 1K from the internal scoreboard. + + Changes with mod_ssl 2.8.9 (27-Mar-2002 to 19-Jun-2002) + + *) Upgraded to Apache 1.3.26. + + *) Support for OpenSSL 0.9.7. + + *) Open random files in binary mode under Win32 to not + stop on EOS characters. + + *) Additional internal consistency check on vhost sanity checking + in case no DNS entries are found for virtual hosts. + + *) Fixed detection of a faked "Faked Basic Auth" situation for + internal redirection situations. + Changes with mod_ssl 2.8.8 (23-Feb-2002 to 27-Mar-2002) *) Upgraded to Apache 1.3.24 diff --git a/usr.sbin/httpd/src/Configure b/usr.sbin/httpd/src/Configure index 0b53ca5819a..9bee3519645 100644 --- a/usr.sbin/httpd/src/Configure +++ b/usr.sbin/httpd/src/Configure @@ -1,5 +1,5 @@ #!/bin/sh -# $OpenBSD: Configure,v 1.19 2002/03/29 02:08:05 beck Exp $ +# $OpenBSD: Configure,v 1.20 2002/07/19 21:31:15 henning Exp $ ## ==================================================================== ## The Apache Software License, Version 1.1 ## @@ -2005,7 +2005,7 @@ 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=24 + V=1 R=3 P=26 if [ "x$SHLIB_SUFFIX_DEPTH" = "x0" ]; then SHLIB_SUFFIX_LIST="" fi @@ -2546,8 +2546,8 @@ all clean distclean depend :: if [ "x\$\$i" != "x" ]; then \\ echo "===> \$(SDP)modules/\$\$i"; \\ case "x\$(OS)" in \\ - xOS390 | xTPF) (cd \$\$i && \$(MAKE) SDP='\$(SDP)' \$@) || exit 1;; \\ - *) (cd \$\$i && \$(MAKE) \$(MFLAGS_STATIC) SDP='\$(SDP)' CC='\$(CC)' AUX_CFLAGS='\$(CFLAGS)' RANLIB='\$(RANLIB)' \$@) || exit 1;; \\ + xOS390 | xTPF) (cd \$\$i && \$(MAKE) SDP='\$(SDP)' OPTIM='\$(OPTIM)' \$@) || exit 1;; \\ + *) (cd \$\$i && \$(MAKE) \$(MFLAGS_STATIC) SDP='\$(SDP)' CC='\$(CC)' AUX_CFLAGS='\$(CFLAGS)' RANLIB='\$(RANLIB)' OPTIM='\$(OPTIM)' \$@) || exit 1;; \\ esac; \\ echo "<=== \$(SDP)modules/\$\$i"; \\ fi; \\ diff --git a/usr.sbin/httpd/src/Makefile.tmpl b/usr.sbin/httpd/src/Makefile.tmpl index c06d17ca176..60ff88b1ce7 100644 --- a/usr.sbin/httpd/src/Makefile.tmpl +++ b/usr.sbin/httpd/src/Makefile.tmpl @@ -77,8 +77,8 @@ subdirs: @for i in $(SUBDIRS); do \ echo "===> $(SDP)$$i"; \ case ".$(OS)" in \ - .OS390 | .TPF) ( cd $$i && $(MAKE) SDP='$(SDP)' ) || exit 1;; \ - *) ( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)') || exit 1;; \ + .OS390 | .TPF) ( cd $$i && $(MAKE) SDP='$(SDP)' OPTIM='$(OPTIM)') || exit 1;; \ + *) ( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)' OPTIM='$(OPTIM)') || exit 1;; \ esac; \ echo "<=== $(SDP)$$i"; \ done @@ -87,14 +87,14 @@ support: support-dir support-dir: @echo "===> $(SDP)support"; \ - cd support; $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)' || exit 1; \ + cd support; $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)' OPTIM='$(OPTIM)' || exit 1; \ echo "<=== $(SDP)support" clean: -rm -f $(TARGET) lib$(TARGET).* *.o @for i in $(SUBDIRS); do \ echo "===> $(SDP)$$i"; \ - ( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' $@ ) || exit 1; \ + ( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' OPTIM='$(OPTIM)' $@ ) || exit 1; \ echo "<=== $(SDP)$$i"; \ done @@ -129,7 +129,7 @@ depend: > Makefile.tmpl \ && rm Makefile.new for i in $(SUBDIRS); do \ - ( cd $$i && $(MAKE) CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)' depend ) || exit 1; \ + ( cd $$i && $(MAKE) CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)' OPTIM='$(OPTIM)' depend ) || exit 1; \ done #Dependencies diff --git a/usr.sbin/httpd/src/ap/Makefile.tmpl b/usr.sbin/httpd/src/ap/Makefile.tmpl index 4514d702845..9945f17d25b 100644 --- a/usr.sbin/httpd/src/ap/Makefile.tmpl +++ b/usr.sbin/httpd/src/ap/Makefile.tmpl @@ -7,7 +7,7 @@ LIB=libap.a 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_ebcdic.o \ - ap_hook.o ap_ctx.o ap_mm.o + ap_strtol.o ap_hook.o ap_ctx.o ap_mm.o .c.o: $(CC) -c $(INCLUDES) $(CFLAGS) $< @@ -77,3 +77,8 @@ ap_snprintf.o: ap_snprintf.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \ $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \ $(INCDIR)/util_uri.h +ap_strtol.o: ap_strtol.c $(INCDIR)/httpd.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)/hsregex.h \ + $(INCDIR)/ap_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 f47b5155ce2..d4ccb941e49 100644 --- a/usr.sbin/httpd/src/ap/ap.dsp +++ b/usr.sbin/httpd/src/ap/ap.dsp @@ -26,6 +26,7 @@ CFG=ap - Win32 Debug # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe +RSC=rc.exe !IF "$(CFG)" == "ap - Win32 Release" @@ -39,9 +40,10 @@ CPP=cl.exe # PROP Output_Dir "LibR" # PROP Intermediate_Dir "LibR" # PROP Target_Dir "" -RSC=rc.exe # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c # ADD CPP /nologo /MD /W3 /O2 /I "..\include" /I "..\os\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fd"LibR\ap" /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo @@ -61,9 +63,10 @@ LIB32=link.exe -lib # PROP Output_Dir "LibD" # PROP Intermediate_Dir "LibD" # PROP Target_Dir "" -RSC=rc.exe # ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c # ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\include" /I "..\os\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Fd"LibD\ap" /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo diff --git a/usr.sbin/httpd/src/helpers/binbuild.sh b/usr.sbin/httpd/src/helpers/binbuild.sh index 8b22a9a58b2..616aa5b224c 100644 --- a/usr.sbin/httpd/src/helpers/binbuild.sh +++ b/usr.sbin/httpd/src/helpers/binbuild.sh @@ -8,7 +8,7 @@ OS=`src/helpers/GuessOS` case "x$OS" in - x*390*) CONFIGPARAM="--with-layout=BinaryDistribution --enable-module=most";; + x*OS390*) CONFIGPARAM="--with-layout=BinaryDistribution --enable-module=most";; *cygwin*) CONFIGPARAM="--with-layout=BinaryDistribution --enable-module=most \ --enable-rule=SHARED_CORE --libexecdir=bin";; *) CONFIGPARAM="--with-layout=BinaryDistribution --enable-module=most --enable-shared=max";; @@ -274,7 +274,7 @@ else if [ "x$TAR" != "x" ] then case "x$OS" in - x*390*) $TAR -cfU ../apache_$VER-$OS.tar -C .. apache_$VER;; + x*OS390*) $TAR -cfU ../apache_$VER-$OS.tar -C .. apache_$VER;; *) (cd .. && $TAR -cf apache_$VER-$OS.tar apache_$VER);; esac if [ "x$GZIP" != "x" ] diff --git a/usr.sbin/httpd/src/include/ap.h b/usr.sbin/httpd/src/include/ap.h index 6e2e488c5ae..4eee68b4851 100644 --- a/usr.sbin/httpd/src/include/ap.h +++ b/usr.sbin/httpd/src/include/ap.h @@ -75,6 +75,10 @@ int ap_execle(const char *, const char *, ...); int ap_execve(const char *, char * const argv[], char * const envp[]); API_EXPORT(int) ap_getpass(const char *prompt, char *pwbuf, size_t bufsiz); +#ifndef ap_strtol +API_EXPORT(long) ap_strtol(const char *nptr, char **endptr, int base); +#endif + /* small utility macros to make things easier to read */ #ifdef WIN32 diff --git a/usr.sbin/httpd/src/include/ap_config.h b/usr.sbin/httpd/src/include/ap_config.h index c9d6b2aef54..d9c2a9ce6b9 100644 --- a/usr.sbin/httpd/src/include/ap_config.h +++ b/usr.sbin/httpd/src/include/ap_config.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ap_config.h,v 1.12 2002/07/17 13:11:02 henning Exp $ */ +/* $OpenBSD: ap_config.h,v 1.13 2002/07/19 21:31:15 henning Exp $ */ /* ==================================================================== * The Apache Software License, Version 1.1 @@ -1009,8 +1009,10 @@ typedef int rlim_t; #define NEED_HASHBANG_EMUL #elif defined(CYGWIN) /* Cygwin 1.x POSIX layer for Win32 */ +#define SYSTEM_UID 18 #define JMP_BUF jmp_buf #define NO_KILLPG +#define NO_SETSID #define USE_LONGJMP #define GDBM_STATIC #define HAVE_MMAP 1 diff --git a/usr.sbin/httpd/src/include/ap_mmn.h b/usr.sbin/httpd/src/include/ap_mmn.h index 93304da3d7e..b299003e52d 100644 --- a/usr.sbin/httpd/src/include/ap_mmn.h +++ b/usr.sbin/httpd/src/include/ap_mmn.h @@ -235,6 +235,8 @@ * filter_callback to the end of buff.h * 19990320.11 - Add some fields to the end of the core_dir_config * structure + * 19990320.12 - add ap_getline(), ap_get_chunk_size() + * 19990320.13 - add ap_strtol() */ /* @@ -258,7 +260,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 19990320 #endif -#define MODULE_MAGIC_NUMBER_MINOR 11 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 13 /* 0...n */ /* Useful for testing for features. */ #define AP_MODULE_MAGIC_AT_LEAST(major,minor) \ diff --git a/usr.sbin/httpd/src/include/http_protocol.h b/usr.sbin/httpd/src/include/http_protocol.h index 948790a09f6..ab0562d2559 100644 --- a/usr.sbin/httpd/src/include/http_protocol.h +++ b/usr.sbin/httpd/src/include/http_protocol.h @@ -217,6 +217,11 @@ CORE_EXPORT(void) ap_parse_uri(request_rec *r, const char *uri); */ API_EXPORT(int) ap_method_number_of(const char *method); +API_EXPORT(int) ap_getline(char *s, int n, BUFF *in, int fold); + +API_EXPORT(long) ap_get_chunk_size(char *b); + + #ifdef __cplusplus } #endif diff --git a/usr.sbin/httpd/src/include/httpd.h b/usr.sbin/httpd/src/include/httpd.h index fa5060628a1..d68c52e4f98 100644 --- a/usr.sbin/httpd/src/include/httpd.h +++ b/usr.sbin/httpd/src/include/httpd.h @@ -175,15 +175,6 @@ extern "C" { #define DEFAULT_GROUP "#-1" #endif -/* The name of the log files */ -#ifndef DEFAULT_XFERLOG -#if defined(OS2) || defined(WIN32) -#define DEFAULT_XFERLOG "logs/access.log" -#else -#define DEFAULT_XFERLOG "logs/access_log" -#endif -#endif /* DEFAULT_XFERLOG */ - #ifndef DEFAULT_ERRORLOG #if defined(OS2) || defined(WIN32) #define DEFAULT_ERRORLOG "logs/error.log" @@ -466,7 +457,7 @@ extern "C" { #define SERVER_BASEVENDOR "Apache Group" #define SERVER_BASEPRODUCT "Apache" -#define SERVER_BASEREVISION "1.3.24" +#define SERVER_BASEREVISION "1.3.26" #define SERVER_BASEVERSION SERVER_BASEPRODUCT "/" SERVER_BASEREVISION #define SERVER_PRODUCT SERVER_BASEPRODUCT @@ -490,7 +481,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 10324100 +#define APACHE_RELEASE 10326100 #define SERVER_PROTOCOL "HTTP/1.1" #ifndef SERVER_SUPPORT @@ -1076,6 +1067,7 @@ API_EXPORT(char *) ap_os_escape_path(pool *p, const char *path, int partial); API_EXPORT(char *) ap_escape_html(pool *p, const char *s); API_EXPORT(char *) ap_construct_server(pool *p, const char *hostname, unsigned port, const request_rec *r); +API_EXPORT(char *) ap_escape_logitem(pool *p, const char *str); API_EXPORT(char *) ap_escape_shell_cmd(pool *p, const char *s); API_EXPORT(int) ap_count_dirs(const char *path); diff --git a/usr.sbin/httpd/src/main/gen_test_char.c b/usr.sbin/httpd/src/main/gen_test_char.c index fae84664442..d310dc55624 100644 --- a/usr.sbin/httpd/src/main/gen_test_char.c +++ b/usr.sbin/httpd/src/main/gen_test_char.c @@ -8,6 +8,7 @@ #define T_ESCAPE_PATH_SEGMENT (0x02) #define T_OS_ESCAPE_PATH (0x04) #define T_HTTP_TOKEN_STOP (0x08) +#define T_ESCAPE_LOGITEM (0x10) int main(int argc, char *argv[]) { @@ -16,25 +17,27 @@ int main(int argc, char *argv[]) printf( "/* this file is automatically generated by gen_test_char, do not edit */\n" -"#define T_ESCAPE_SHELL_CMD (%u)\n" -"#define T_ESCAPE_PATH_SEGMENT (%u)\n" -"#define T_OS_ESCAPE_PATH (%u)\n" -"#define T_HTTP_TOKEN_STOP (%u)\n" -"\n" -"static const unsigned char test_char_table[256] = {\n" -" 0,", +"#define T_ESCAPE_SHELL_CMD 0x%02x /* chars with special meaning in the shell */\n" +"#define T_ESCAPE_PATH_SEGMENT 0x%02x /* find path segment, as defined in RFC1808 */\n" +"#define T_OS_ESCAPE_PATH 0x%02x /* escape characters in a path or uri */\n" +"#define T_HTTP_TOKEN_STOP 0x%02x /* find http tokens, as defined in RFC2616 */\n" +"#define T_ESCAPE_LOGITEM 0x%02x /* filter what should go in the log file */\n" +"\n", T_ESCAPE_SHELL_CMD, T_ESCAPE_PATH_SEGMENT, T_OS_ESCAPE_PATH, - T_HTTP_TOKEN_STOP); + T_HTTP_TOKEN_STOP, + T_ESCAPE_LOGITEM + ); /* we explicitly dealt with NUL above * in case some strchr() do bogosity with it */ + printf("static const unsigned char test_char_table[256] = {\n" + " 0x00, "); /* print initial item */ + for (c = 1; c < 256; ++c) { flags = 0; - if (c % 20 == 0) - printf("\n "); /* escape_shell_cmd */ #if defined(WIN32) || defined(OS2) @@ -67,8 +70,19 @@ int main(int argc, char *argv[]) if (ap_iscntrl(c) || strchr(" \t()<>@,;:\\/[]?={}", c)) { flags |= T_HTTP_TOKEN_STOP; } - printf("%u%c", flags, (c < 255) ? ',' : ' '); + /* For logging, escape all control characters, + * double quotes (because they delimit the request in the log file) + * backslashes (because we use backslash for escaping) + * and 8-bit chars with the high bit set + */ + if (!ap_isprint(c) || c == '"' || c == '\\' || ap_iscntrl(c)) { + flags |= T_ESCAPE_LOGITEM; + } + printf("0x%02x%s", flags, (c < 255) ? ", " : " "); + + if ((c % 8) == 7) + printf(" /*0x%02x...0x%02x*/\n ", c-7, c); } printf("\n};\n"); diff --git a/usr.sbin/httpd/src/main/http_core.c b/usr.sbin/httpd/src/main/http_core.c index 0b09e4f646a..49bc03ee222 100644 --- a/usr.sbin/httpd/src/main/http_core.c +++ b/usr.sbin/httpd/src/main/http_core.c @@ -1,4 +1,4 @@ -/* $OpenBSD: http_core.c,v 1.11 2002/07/15 09:40:49 henning Exp $ */ +/* $OpenBSD: http_core.c,v 1.12 2002/07/19 21:31:15 henning Exp $ */ /* ==================================================================== * The Apache Software License, Version 1.1 @@ -2939,7 +2939,7 @@ static const char *set_limit_req_body(cmd_parms *cmd, core_dir_config *conf, * Instead we have an idiotic define in httpd.h that prevents * it from being used even when it is available. Sheesh. */ - conf->limit_req_body = (unsigned long)strtol(arg, (char **)NULL, 10); + conf->limit_req_body = (unsigned long)ap_strtol(arg, (char **)NULL, 10); return NULL; } @@ -3882,7 +3882,7 @@ static int default_handler(request_rec *r) return METHOD_NOT_ALLOWED; } -#if defined(OS2) || defined(WIN32) || defined(NETWARE) +#if defined(OS2) || defined(WIN32) || defined(NETWARE) || defined(CYGWIN) /* Need binary mode for OS/2 */ f = ap_pfopen(r->pool, r->filename, "rb"); #else diff --git a/usr.sbin/httpd/src/main/http_log.c b/usr.sbin/httpd/src/main/http_log.c index 78ef1bbf7b1..ee1afe87688 100644 --- a/usr.sbin/httpd/src/main/http_log.c +++ b/usr.sbin/httpd/src/main/http_log.c @@ -339,18 +339,6 @@ 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 diff --git a/usr.sbin/httpd/src/main/http_main.c b/usr.sbin/httpd/src/main/http_main.c index f2fd92d826f..37bfc24d212 100644 --- a/usr.sbin/httpd/src/main/http_main.c +++ b/usr.sbin/httpd/src/main/http_main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: http_main.c,v 1.17 2002/07/17 11:19:10 henning Exp $ */ +/* $OpenBSD: http_main.c,v 1.18 2002/07/19 21:31:15 henning Exp $ */ /* ==================================================================== * The Apache Software License, Version 1.1 @@ -349,6 +349,8 @@ static pid_t pgrp; static int one_process = 0; +static int do_detach = 1; + /* set if timeouts are to be handled by the children and not by the parent. * i.e. child_timeouts = !standalone || one_process. */ @@ -1390,7 +1392,7 @@ static void usage(char *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] [-T] [-u]\n", pad); + fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t] [-T] [-F] [-u]\n", pad); fprintf(stderr, "Options:\n"); #ifdef SHARED_CORE fprintf(stderr, " -R directory : specify an alternate location for shared object files\n"); @@ -1413,6 +1415,9 @@ static void usage(char *bin) #endif 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"); +#ifndef WIN32 + fprintf(stderr, " -F : run main process in foreground, for process supervisors\n"); +#endif #ifdef WIN32 fprintf(stderr, " -n name : name the Apache service for -k options below;\n"); fprintf(stderr, " -k stop|shutdown : tell running Apache to shutdown\n"); @@ -2776,6 +2781,7 @@ static void reclaim_child_processes(int terminate) struct timeval tv; int waitret, tries; int not_dead_yet; + int ret; #ifndef NO_OTHER_CHILD other_child_rec *ocr, *nocr; #endif @@ -2785,12 +2791,15 @@ static void reclaim_child_processes(int terminate) for (tries = terminate ? 4 : 1; tries <= 12; ++tries) { /* don't want to hold up progress any more than * necessary, but we need to allow children a few moments to exit. - * Set delay with an exponential backoff. + * Set delay with an exponential backoff. NOTE: if we get + * interupted, we'll wait longer than expected... */ tv.tv_sec = waittime / 1000000; tv.tv_usec = waittime % 1000000; waittime = waittime * 4; - ap_select(0, NULL, NULL, NULL, &tv); + do { + ret = ap_select(0, NULL, NULL, NULL, &tv); + } while (ret == -1 && errno == EINTR); /* now see who is done */ not_dead_yet = 0; @@ -3424,19 +3433,24 @@ static void detach(void) !defined(BONE) /* Don't detach for MPE because child processes can't survive the death of the parent. */ - if ((x = fork()) > 0) - exit(0); - else if (x == -1) { - perror("fork"); - fprintf(stderr, "%s: unable to fork new process\n", ap_server_argv0); - exit(1); + if (do_detach) { + if ((x = fork()) > 0) + exit(0); + else if (x == -1) { + perror("fork"); + fprintf(stderr, "%s: unable to fork new process\n", ap_server_argv0); + exit(1); + } + RAISE_SIGSTOP(DETACH); } - RAISE_SIGSTOP(DETACH); #endif #ifndef NO_SETSID if ((pgrp = setsid()) == -1) { perror("setsid"); fprintf(stderr, "%s: setsid failed\n", ap_server_argv0); + if (!do_detach) + fprintf(stderr, "setsid() failed probably because you aren't " + "running under a process management tool like daemontools\n"); exit(1); } #elif defined(NEXT) || defined(NEWSOS) @@ -3451,6 +3465,13 @@ static void detach(void) #elif defined(MPE) /* MPE uses negative pid for process group */ pgrp = -getpid(); +#elif defined(CYGWIN) + /* Cygwin does not take any argument for setpgrp() */ + if ((pgrp = setpgrp()) == -1) { + perror("setpgrp"); + fprintf(stderr, "%s: setpgrp failed\n", ap_server_argv0); + exit(1); + } #else if ((pgrp = setpgrp(getpid(), 0)) == -1) { perror("setpgrp"); @@ -4181,9 +4202,6 @@ static void show_compile_settings(void) #ifdef DEFAULT_LOCKFILE printf(" -D DEFAULT_LOCKFILE=\"" DEFAULT_LOCKFILE "\"\n"); #endif -#ifdef DEFAULT_XFERLOG - printf(" -D DEFAULT_XFERLOG=\"" DEFAULT_XFERLOG "\"\n"); -#endif #ifdef DEFAULT_ERRORLOG printf(" -D DEFAULT_ERRORLOG=\"" DEFAULT_ERRORLOG "\"\n"); #endif @@ -4315,8 +4333,15 @@ static void child_main(int child_num_arg) } GETUSERMODE(); #else - /* Only try to switch if we're running as root */ + /* + * Only try to switch if we're running as root + * In case of Cygwin we have the special super-user named SYSTEM + */ +#ifdef CYGWIN + if (getuid() == SYSTEM_UID && ( +#else if (!geteuid() && ( +#endif #ifdef _OSD_POSIX os_init_job_environment(server_conf, ap_user_name, one_process) != 0 || #endif @@ -4899,13 +4924,16 @@ static int hold_off_on_exponential_spawning; * is greater then ap_daemons_max_free. Usually we will use SIGUSR1 * to gracefully shutdown, but unfortunatly some OS will need other * signals to ensure that the child process is terminated and the - * scoreboard pool is not growing to infinity. This effect has been - * seen at least on Cygwin 1.x. -- Stipe Tolj <tolj@wapme-systems.de> + * scoreboard pool is not growing to infinity. Also set the signal we + * use to kill of childs that exceed timeout. This effect has been +* seen at least on Cygwin 1.x. -- Stipe Tolj <tolj@wapme-systems.de> */ #if defined(CYGWIN) #define SIG_IDLE_KILL SIGKILL +#define SIG_TIMEOUT_KILL SIGUSR2 #else #define SIG_IDLE_KILL SIGUSR1 +#define SIG_TIMEOUT_KILL SIGALRM #endif static void perform_idle_server_maintenance(void) @@ -4977,7 +5005,7 @@ static void perform_idle_server_maintenance(void) else if (ps->last_rtime + ss->timeout_len < now) { /* no progress, and the timeout length has been exceeded */ ss->timeout_len = 0; - kill(ps->pid, SIGALRM); + kill(ps->pid, SIG_TIMEOUT_KILL); } } #endif @@ -5466,7 +5494,7 @@ int REALMAIN(int argc, char *argv[]) ap_setup_prelinked_modules(); while ((c = getopt(argc, argv, - "D:C:c:xXd:f:vVlLR:StThu" + "D:C:c:xXd:Ff:vVlLR:StThu" #ifdef DEBUG_SIGSTOP "Z:" #endif @@ -5488,6 +5516,9 @@ int REALMAIN(int argc, char *argv[]) case 'd': ap_cpystrn(ap_server_root, optarg, sizeof(ap_server_root)); break; + case 'F': + do_detach = 0; + break; case 'f': ap_cpystrn(ap_server_confname, optarg, sizeof(ap_server_confname)); break; @@ -5599,15 +5630,23 @@ int REALMAIN(int argc, char *argv[]) tpf_server_name[INETD_SERVNAME_LENGTH + 1] = '\0'; ap_open_logs(server_conf, plog); ap_tpf_zinet_checks(ap_standalone, tpf_server_name, server_conf); + ap_tpf_save_argv(argc, argv); /* save argv parms for children */ } if (ap_standalone) { ap_set_version(); ap_init_modules(pconf, server_conf); version_locked++; if(tpf_child) { + server_conf->error_log = stderr; +#ifdef HAVE_SYSLOG + /* if ErrorLog is syslog call ap_open_logs from the child since + syslog isn't redirected to stderr by the Apache parent */ + if (strncasecmp(server_conf->error_fname, "syslog", 6) == 0) { + ap_open_logs(server_conf, plog); + } +#endif /* HAVE_SYSLOG */ copy_listeners(pconf); reset_tpf_listeners(&input_parms.child); - server_conf->error_log = NULL; #ifdef SCOREBOARD_FILE scoreboard_fd = input_parms.child.scoreboard_fd; ap_scoreboard_image = &_scoreboard_image; @@ -5648,8 +5687,16 @@ int REALMAIN(int argc, char *argv[]) } GETUSERMODE(); #else - /* Only try to switch if we're running as root */ + /* + * Only try to switch if we're running as root + * In case of Cygwin we have the special super-user named SYSTEM + * with a pre-defined uid. + */ +#ifdef CYGWIN + if ((getuid() == SYSTEM_UID) && setuid(ap_user_id) == -1) { +#else if (!geteuid() && setuid(ap_user_id) == -1) { +#endif ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf, "setuid: unable to change to uid: %ld", (long) ap_user_id); @@ -7399,7 +7446,7 @@ int REALMAIN(int argc, char *argv[]) while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLz:Z:wiuStThk:n:W:")) != -1) { #else /* !WIN32 */ - while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLesStTh")) != -1) { + while ((c = getopt(argc, argv, "D:C:c:Xd:fF:vVlLesStTh")) != -1) { #endif char **new; switch (c) { @@ -7521,6 +7568,11 @@ int REALMAIN(int argc, char *argv[]) && ap_server_root[strlen(ap_server_root) - 1] == '/') ap_server_root[strlen(ap_server_root) - 1] = '\0'; break; +#ifndef WIN32 + case 'F': + do_detach = 0; + break; +#endif case 'f': ap_cpystrn(ap_server_confname, ap_os_canonical_filename(pcommands, optarg), @@ -7856,7 +7908,7 @@ __declspec(dllimport) #endif -int ap_main(int argc, char *argv[]); /* Load time linked from libhttpd.dll */ +int ap_main(int argc, char *argv[]); /* Load time linked from cyghttpd.dll */ int main(int argc, char *argv[]) { @@ -7922,13 +7974,14 @@ 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:tTh")) != -1) { + while ((c = getopt(argc, argv, "D:C:c:Xd:Ff:vVlLR:SZ:tTh")) != -1) { switch (c) { case 'D': case 'C': case 'c': case 'X': case 'd': + case 'F': case 'f': case 'v': case 'V': diff --git a/usr.sbin/httpd/src/main/http_protocol.c b/usr.sbin/httpd/src/main/http_protocol.c index b373c76ea83..df87e217b20 100644 --- a/usr.sbin/httpd/src/main/http_protocol.c +++ b/usr.sbin/httpd/src/main/http_protocol.c @@ -171,7 +171,7 @@ static enum byterange_token } if (ap_isdigit(*r->range)) - *start = strtol(r->range, (char **)&r->range, 10); + *start = ap_strtol(r->range, (char **)&r->range, 10); else *start = -1; @@ -186,7 +186,7 @@ static enum byterange_token ++r->range; if (ap_isdigit(*r->range)) - *end = strtol(r->range, (char **)&r->range, 10); + *end = ap_strtol(r->range, (char **)&r->range, 10); else *end = -1; @@ -857,13 +857,13 @@ API_EXPORT(int) ap_method_number_of(const char *method) * then the actual input line exceeded the buffer length, * and it would be a good idea for the caller to puke 400 or 414. */ -static int getline(char *s, int n, BUFF *in, int fold) +API_EXPORT(int) ap_getline(char *s, int n, BUFF *in, int fold) { char *pos, next; int retval; int total = 0; #ifdef CHARSET_EBCDIC - /* When getline() is called, the HTTP protocol is in a state + /* When ap_getline() is called, the HTTP protocol is in a state * where we MUST be reading "plain text" protocol stuff, * (Request line, MIME headers, Chunk sizes) regardless of * the MIME type and conversion setting of the document itself. @@ -978,12 +978,12 @@ CORE_EXPORT(void) ap_parse_uri(request_rec *r, const char *uri) static int read_request_line(request_rec *r) { - char l[DEFAULT_LIMIT_REQUEST_LINE + 2]; /* getline's two extra for \n\0 */ + char l[DEFAULT_LIMIT_REQUEST_LINE + 2]; /* ap_getline's two extra for \n\0 */ const char *ll = l; const char *uri; conn_rec *conn = r->connection; unsigned int major = 1, minor = 0; /* Assume HTTP/1.0 if non-"HTTP" protocol */ - int len; + int len, n; /* Read past empty lines until we get a real request line, * a read error, the connection closes (EOF), or we timeout. @@ -1000,7 +1000,7 @@ static int read_request_line(request_rec *r) * have to block during a read. */ ap_bsetflag(conn->client, B_SAFEREAD, 1); - while ((len = getline(l, sizeof(l), conn->client, 0)) <= 0) { + while ((len = ap_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, @@ -1031,7 +1031,7 @@ static int read_request_line(request_rec *r) ap_parse_uri(r, uri); - /* getline returns (size of max buffer - 1) if it fills up the + /* ap_getline returns (size of max buffer - 1) if it fills up the * buffer before finding the end-of-line. This is only going to * happen if it exceeds the configured limit for a request-line. */ @@ -1045,18 +1045,34 @@ static int read_request_line(request_rec *r) r->assbackwards = (ll[0] == '\0'); r->protocol = ap_pstrdup(r->pool, ll[0] ? ll : "HTTP/0.9"); - if (2 == sscanf(r->protocol, "HTTP/%u.%u", &major, &minor) + if (2 == sscanf(r->protocol, "HTTP/%u.%u%n", &major, &minor, &n) && minor < HTTP_VERSION(1,0)) /* don't allow HTTP/0.1000 */ r->proto_num = HTTP_VERSION(major, minor); - else + else { r->proto_num = HTTP_VERSION(1,0); + n = 0; + } + + /* Check for a valid protocol, and disallow everything but whitespace + * after the protocol string */ + while (ap_isspace(r->protocol[n])) + ++n; + if (r->protocol[n] != '\0') { + r->status = HTTP_BAD_REQUEST; + r->proto_num = HTTP_VERSION(1,0); + r->protocol = ap_pstrdup(r->pool, "HTTP/1.0"); + ap_table_setn(r->notes, "error-notes", + "The request line contained invalid characters " + "following the protocol string.<P>\n"); + return 0; + } return 1; } static void get_mime_headers(request_rec *r) { - char field[DEFAULT_LIMIT_REQUEST_FIELDSIZE + 2]; /* getline's two extra */ + char field[DEFAULT_LIMIT_REQUEST_FIELDSIZE + 2]; /* ap_getline's two extra */ conn_rec *c = r->connection; char *value; char *copy; @@ -1071,7 +1087,7 @@ static void get_mime_headers(request_rec *r) * Read header lines until we get the empty separator line, a read error, * the connection closes (EOF), reach the server limit, or we timeout. */ - while ((len = getline(field, sizeof(field), c->client, 1)) > 0) { + while ((len = ap_getline(field, sizeof(field), c->client, 1)) > 0) { if (r->server->limit_req_fields && (++fields_read > r->server->limit_req_fields)) { @@ -1081,7 +1097,7 @@ static void get_mime_headers(request_rec *r) "this server's limit.<P>\n"); return; } - /* getline returns (size of max buffer - 1) if it fills up the + /* ap_getline returns (size of max buffer - 1) if it fills up the * buffer before finding the end-of-line. This is only going to * happen if it exceeds the configured limit for a field size. */ @@ -1173,6 +1189,14 @@ API_EXPORT(request_rec *) ap_read_request(conn_rec *conn) ap_log_transaction(r); return r; } + else if (r->status == HTTP_BAD_REQUEST) { + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, + "request failed: erroneous characters after protocol string: %s", + ap_escape_logitem(r->pool, r->the_request)); + ap_send_error_response(r, 0); + ap_log_transaction(r); + return r; + } return NULL; } if (!r->assbackwards) { @@ -1522,7 +1546,6 @@ API_EXPORT_NONSTD(int) ap_send_header_field(request_rec *r, API_EXPORT(void) ap_basic_http_header(request_rec *r) { char *protocol; - const char *server; if (r->assbackwards) return; @@ -1551,10 +1574,13 @@ API_EXPORT(void) ap_basic_http_header(request_rec *r) /* output the date header */ ap_send_header_field(r, "Date", ap_gm_timestr_822(r->pool, r->request_time)); - /* keep a previously set server header (possible from proxy), otherwise + /* keep the set-by-proxy server header, otherwise * generate a new server header */ - if (server = ap_table_get(r->headers_out, "Server")) { - ap_send_header_field(r, "Server", server); + if (r->proxyreq) { + const char *server = ap_table_get(r->headers_out, "Server"); + if (server) { + ap_send_header_field(r, "Server", server); + } } else { ap_send_header_field(r, "Server", ap_get_server_version()); @@ -1967,16 +1993,25 @@ API_EXPORT(int) ap_setup_client_block(request_rec *r, int read_policy) } else if (lenp) { const char *pos = lenp; + int conversion_error = 0; while (ap_isdigit(*pos) || ap_isspace(*pos)) ++pos; - if (*pos != '\0') { + + if (*pos == '\0') { + char *endstr; + errno = 0; + r->remaining = ap_strtol(lenp, &endstr, 10); + if (errno || (endstr && *endstr)) { + conversion_error = 1; + } + } + + if (*pos != '\0' || conversion_error) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "Invalid Content-Length %s", lenp); + "Invalid Content-Length"); return HTTP_BAD_REQUEST; } - - r->remaining = atol(lenp); } if ((r->read_body == REQUEST_NO_BODY) && @@ -2025,7 +2060,7 @@ API_EXPORT(int) ap_should_client_block(request_rec *r) return 1; } -static long get_chunk_size(char *b) +API_EXPORT(long) ap_get_chunk_size(char *b) { long chunksize = 0; long chunkbits = sizeof(long) * 8; @@ -2120,14 +2155,14 @@ API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz) if (r->remaining == 0) { /* Start of new chunk */ - chunk_start = getline(buffer, bufsiz, r->connection->client, 0); + chunk_start = ap_getline(buffer, bufsiz, r->connection->client, 0); if ((chunk_start <= 0) || (chunk_start >= (bufsiz - 1)) || !ap_isxdigit(*buffer)) { r->connection->keepalive = -1; return -1; } - len_to_read = get_chunk_size(buffer); + len_to_read = ap_get_chunk_size(buffer); if (len_to_read == 0) { /* Last chunk indicated, get footers */ if (r->read_body == REQUEST_CHUNKED_DECHUNK) { @@ -2165,7 +2200,7 @@ API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz) len_read = chunk_start; while ((bufsiz > 1) && ((len_read = - getline(buffer, bufsiz, r->connection->client, 1)) > 0)) { + ap_getline(buffer, bufsiz, r->connection->client, 1)) > 0)) { if (len_read != (bufsiz - 1)) { buffer[len_read++] = CR; /* Restore footer line end */ diff --git a/usr.sbin/httpd/src/main/http_request.c b/usr.sbin/httpd/src/main/http_request.c index fae2d26d3fd..9fbaaacc963 100644 --- a/usr.sbin/httpd/src/main/http_request.c +++ b/usr.sbin/httpd/src/main/http_request.c @@ -925,7 +925,7 @@ API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file, */ if (errno == ENAMETOOLONG) { ap_log_rerror(APLOG_MARK, APLOG_CRIT, r, - "Possible DoS attempt? URL=%s", r->filename); + "Possible DoS attempt? Path=%s", r->filename); rnew->status = HTTP_FORBIDDEN; return rnew; } diff --git a/usr.sbin/httpd/src/main/util.c b/usr.sbin/httpd/src/main/util.c index 05622c197cf..ba2836e117b 100644 --- a/usr.sbin/httpd/src/main/util.c +++ b/usr.sbin/httpd/src/main/util.c @@ -1446,6 +1446,81 @@ API_EXPORT(int) ap_find_last_token(pool *p, const char *line, const char *tok) return (strncasecmp(&line[lidx], tok, tlen) == 0); } +/* c2x takes an unsigned, and expects the caller has guaranteed that + * 0 <= what < 256... which usually means that you have to cast to + * unsigned char first, because (unsigned)(char)(x) first goes through + * signed extension to an int before the unsigned cast. + * + * The reason for this assumption is to assist gcc code generation -- + * the unsigned char -> unsigned extension is already done earlier in + * both uses of this code, so there's no need to waste time doing it + * again. + */ +static const char c2x_table[] = "0123456789abcdef"; + +static ap_inline unsigned char *c2x(unsigned what, unsigned char *where) +{ +#ifdef CHARSET_EBCDIC + what = os_toascii[what]; +#endif /*CHARSET_EBCDIC*/ + *where++ = '%'; + *where++ = c2x_table[what >> 4]; + *where++ = c2x_table[what & 0xf]; + return where; +} + +/* escape a string for logging */ +API_EXPORT(char *) ap_escape_logitem(pool *p, const char *str) +{ + char *ret; + unsigned char *d; + const unsigned char *s; + + if (str == NULL) + return NULL; + + ret = ap_palloc(p, 4 * strlen(str) + 1); /* Be safe */ + d = (unsigned char *)ret; + s = (const unsigned char *)str; + for (; *s; ++s) { + + if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) { + *d++ = '\\'; + switch(*s) { + case '\b': + *d++ = 'b'; + break; + case '\n': + *d++ = 'n'; + break; + case '\r': + *d++ = 'r'; + break; + case '\t': + *d++ = 't'; + break; + case '\v': + *d++ = 'v'; + break; + case '\\': + case '"': + *d++ = *s; + break; + default: + c2x(*s, d); + *d = 'x'; + d += 3; + } + } + else + *d++ = *s; + } + *d = '\0'; + + return ret; +} + + API_EXPORT(char *) ap_escape_shell_cmd(pool *p, const char *str) { char *cmd; @@ -1494,7 +1569,7 @@ static char x2c(const char *what) xstr[2]=what[0]; xstr[3]=what[1]; xstr[4]='\0'; - digit = os_toebcdic[0xFF & strtol(xstr, NULL, 16)]; + digit = os_toebcdic[0xFF & ap_strtol(xstr, NULL, 16)]; #endif /*CHARSET_EBCDIC*/ return (digit); } @@ -1550,29 +1625,6 @@ API_EXPORT(char *) ap_construct_server(pool *p, const char *hostname, } } -/* c2x takes an unsigned, and expects the caller has guaranteed that - * 0 <= what < 256... which usually means that you have to cast to - * unsigned char first, because (unsigned)(char)(x) first goes through - * signed extension to an int before the unsigned cast. - * - * The reason for this assumption is to assist gcc code generation -- - * the unsigned char -> unsigned extension is already done earlier in - * both uses of this code, so there's no need to waste time doing it - * again. - */ -static const char c2x_table[] = "0123456789abcdef"; - -static ap_inline unsigned char *c2x(unsigned what, unsigned char *where) -{ -#ifdef CHARSET_EBCDIC - what = os_toascii[what]; -#endif /*CHARSET_EBCDIC*/ - *where++ = '%'; - *where++ = c2x_table[what >> 4]; - *where++ = c2x_table[what & 0xf]; - return where; -} - /* * escape_path_segment() escapes a path segment, as defined in RFC 1808. This * routine is (should be) OS independent. diff --git a/usr.sbin/httpd/src/main/util_uri.c b/usr.sbin/httpd/src/main/util_uri.c index e61b7ba52ba..802790aa829 100644 --- a/usr.sbin/httpd/src/main/util_uri.c +++ b/usr.sbin/httpd/src/main/util_uri.c @@ -428,7 +428,7 @@ API_EXPORT(int) ap_parse_uri_components(pool *p, const char *uri, ++s; uptr->port_str = ap_pstrndup(p, s, uri - s); if (uri != s) { - port = strtol(uptr->port_str, &endstr, 10); + port = ap_strtol(uptr->port_str, &endstr, 10); uptr->port = port; if (*endstr == '\0') { goto deal_with_path; @@ -483,7 +483,7 @@ API_EXPORT(int) ap_parse_hostinfo_components(pool *p, const char *hostinfo, ++s; uptr->port_str = ap_pstrdup(p, s); if (*s != '\0') { - uptr->port = (unsigned short)strtol(uptr->port_str, &endstr, 10); + uptr->port = (unsigned short)ap_strtol(uptr->port_str, &endstr, 10); if (*endstr == '\0') { return HTTP_OK; } diff --git a/usr.sbin/httpd/src/modules/experimental/mod_auth_digest.c b/usr.sbin/httpd/src/modules/experimental/mod_auth_digest.c index 6cae1f3533e..956b5f5faa3 100644 --- a/usr.sbin/httpd/src/modules/experimental/mod_auth_digest.c +++ b/usr.sbin/httpd/src/modules/experimental/mod_auth_digest.c @@ -594,7 +594,7 @@ static const char *set_nonce_lifetime(cmd_parms *cmd, void *config, char *endptr; long lifetime; - lifetime = strtol(t, &endptr, 10); + lifetime = ap_strtol(t, &endptr, 10); if (endptr < (t+strlen(t)) && !ap_isspace(*endptr)) return ap_pstrcat(cmd->pool, "Invalid time in AuthDigestNonceLifetime: ", t, NULL); @@ -954,7 +954,7 @@ static int get_digest_rec(request_rec *r, digest_header_rec *resp) } if (resp->opaque) - resp->opaque_num = (unsigned long) strtol(resp->opaque, NULL, 16); + resp->opaque_num = (unsigned long) ap_strtol(resp->opaque, NULL, 16); resp->auth_hdr_sts = VALID; return OK; @@ -1396,7 +1396,7 @@ static int check_nc(const request_rec *r, const digest_header_rec *resp, if (!conf->check_nc || !client_mm) return OK; - nc = strtol(snc, &endptr, 16); + nc = ap_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); diff --git a/usr.sbin/httpd/src/modules/proxy/mod_proxy.c b/usr.sbin/httpd/src/modules/proxy/mod_proxy.c index 99dc72e32d5..3c0d0d0241f 100644 --- a/usr.sbin/httpd/src/modules/proxy/mod_proxy.c +++ b/usr.sbin/httpd/src/modules/proxy/mod_proxy.c @@ -99,8 +99,9 @@ static int alias_match(const char *uri, const char *alias_fakename) while (aliasp < end_fakename) { if (*aliasp == '/') { - /* any number of '/' in the alias matches any number in - * the supplied URI, but there must be at least one... + /* + * any number of '/' in the alias matches any number in the + * supplied URI, but there must be at least one... */ if (*urip != '/') return 0; @@ -122,9 +123,9 @@ static int alias_match(const char *uri, const char *alias_fakename) if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/') return 0; - /* Return number of characters from URI which matched (may be - * greater than length of alias, since we may have matched - * doubled slashes) + /* + * Return number of characters from URI which matched (may be greater + * than length of alias, since we may have matched doubled slashes) */ return urip - uri; @@ -146,14 +147,14 @@ static int proxy_detect(request_rec *r) void *sconf = r->server->module_config; proxy_server_conf *conf; - conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); if (conf->req && r->parsed_uri.scheme) { /* but it might be something vhosted */ - if (!(r->parsed_uri.hostname - && !strcasecmp(r->parsed_uri.scheme, ap_http_method(r)) - && ap_matches_request_vhost(r, r->parsed_uri.hostname, - r->parsed_uri.port_str ? r->parsed_uri.port : ap_default_port(r)))) { + if (!(r->parsed_uri.hostname + && !strcasecmp(r->parsed_uri.scheme, ap_http_method(r)) + && ap_matches_request_vhost(r, r->parsed_uri.hostname, + r->parsed_uri.port_str ? r->parsed_uri.port : ap_default_port(r)))) { r->proxyreq = STD_PROXY; r->uri = r->unparsed_uri; r->filename = ap_pstrcat(r->pool, "proxy:", r->uri, NULL); @@ -164,10 +165,10 @@ static int proxy_detect(request_rec *r) else if (conf->req && r->method_number == M_CONNECT && r->parsed_uri.hostname && r->parsed_uri.port_str) { - r->proxyreq = STD_PROXY; - r->uri = r->unparsed_uri; - r->filename = ap_pstrcat(r->pool, "proxy:", r->uri, NULL); - r->handler = "proxy-server"; + r->proxyreq = STD_PROXY; + r->uri = r->unparsed_uri; + r->filename = ap_pstrcat(r->pool, "proxy:", r->uri, NULL); + r->handler = "proxy-server"; } return DECLINED; } @@ -176,31 +177,33 @@ static int proxy_trans(request_rec *r) { void *sconf = r->server->module_config; proxy_server_conf *conf = - (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); int i, len; - struct proxy_alias *ent = (struct proxy_alias *) conf->aliases->elts; + struct proxy_alias *ent = (struct proxy_alias *)conf->aliases->elts; if (r->proxyreq != NOT_PROXY) { - /* someone has already set up the proxy, it was possibly ourselves - * in proxy_detect + /* + * someone has already set up the proxy, it was possibly ourselves in + * proxy_detect */ return OK; } - /* XXX: since r->uri has been manipulated already we're not really - * compliant with RFC1945 at this point. But this probably isn't - * an issue because this is a hybrid proxy/origin server. + /* + * XXX: since r->uri has been manipulated already we're not really + * compliant with RFC1945 at this point. But this probably isn't an + * issue because this is a hybrid proxy/origin server. */ for (i = 0; i < conf->aliases->nelts; i++) { len = alias_match(r->uri, ent[i].fake); - - if (len > 0) { - r->filename = ap_pstrcat(r->pool, "proxy:", ent[i].real, - r->uri + len, NULL); - r->handler = "proxy-server"; - r->proxyreq = PROXY_PASS; - return OK; + + if (len > 0) { + r->filename = ap_pstrcat(r->pool, "proxy:", ent[i].real, + r->uri + len, NULL); + r->handler = "proxy-server"; + r->proxyreq = PROXY_PASS; + return OK; } } return DECLINED; @@ -242,7 +245,7 @@ static int proxy_fixup(request_rec *r) if (p == NULL || p == url) return HTTP_BAD_REQUEST; - return OK; /* otherwise; we've done the best we can */ + return OK; /* otherwise; we've done the best we can */ } static void proxy_init(server_rec *r, pool *p) @@ -304,7 +307,7 @@ static int proxy_needsdomain(request_rec *r, const char *url, const char *domain /* If host does contain a dot already, or it is "localhost", decline */ if (strchr(r->parsed_uri.hostname, '.') != NULL - || strcasecmp(r->parsed_uri.hostname, "localhost") == 0) + || strcasecmp(r->parsed_uri.hostname, "localhost") == 0) return DECLINED; /* host name has a dot already */ ref = ap_table_get(r->headers_in, "Referer"); @@ -312,17 +315,17 @@ static int proxy_needsdomain(request_rec *r, const char *url, const char *domain /* Reassemble the request, but insert the domain after the host name */ /* Note that the domain name always starts with a dot */ r->parsed_uri.hostname = ap_pstrcat(r->pool, r->parsed_uri.hostname, - domain, NULL); + domain, NULL); nuri = ap_unparse_uri_components(r->pool, - &r->parsed_uri, - UNP_REVEALPASSWORD); + &r->parsed_uri, + UNP_REVEALPASSWORD); ap_table_set(r->headers_out, "Location", nuri); - ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, r, - "Domain missing: %s sent to %s%s%s", r->uri, - ap_unparse_uri_components(r->pool, &r->parsed_uri, - UNP_OMITUSERINFO), - ref ? " from " : "", ref ? ref : ""); + ap_log_rerror(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, r, + "Domain missing: %s sent to %s%s%s", r->uri, + ap_unparse_uri_components(r->pool, &r->parsed_uri, + UNP_OMITUSERINFO), + ref ? " from " : "", ref ? ref : ""); return HTTP_MOVED_PERMANENTLY; } @@ -335,7 +338,7 @@ static int proxy_handler(request_rec *r) char *url, *scheme, *p; void *sconf = r->server->module_config; proxy_server_conf *conf = - (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); array_header *proxies = conf->proxies; struct proxy_remote *ents = (struct proxy_remote *) proxies->elts; int i, rc; @@ -348,7 +351,7 @@ static int proxy_handler(request_rec *r) if (r->method_number == M_TRACE && (maxfwd_str = ap_table_get(r->headers_in, "Max-Forwards")) != NULL) { - long maxfwd = strtol(maxfwd_str, NULL, 10); + long maxfwd = ap_strtol(maxfwd_str, NULL, 10); if (maxfwd < 1) { int access_status; r->proxyreq = NOT_PROXY; @@ -358,8 +361,8 @@ static int proxy_handler(request_rec *r) ap_finalize_request_protocol(r); return OK; } - ap_table_setn(r->headers_in, "Max-Forwards", - ap_psprintf(r->pool, "%ld", (maxfwd > 0) ? maxfwd-1 : 0)); + ap_table_setn(r->headers_in, "Max-Forwards", + ap_psprintf(r->pool, "%ld", (maxfwd > 0) ? maxfwd - 1 : 0)); } if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) @@ -389,18 +392,18 @@ static int proxy_handler(request_rec *r) /* Check URI's destination host against NoProxy hosts */ /* Bypass ProxyRemote server lookup if configured as NoProxy */ /* we only know how to handle communication to a proxy via http */ - /*if (strcasecmp(scheme, "http") == 0) */ + /* if (strcasecmp(scheme, "http") == 0) */ { int ii; - struct dirconn_entry *list = (struct dirconn_entry *) conf->dirconn->elts; + struct dirconn_entry *list = (struct dirconn_entry *)conf->dirconn->elts; for (direct_connect = ii = 0; ii < conf->dirconn->nelts && !direct_connect; ii++) { direct_connect = list[ii].matcher(&list[ii], r); } #if DEBUGGING - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r, - (direct_connect) ? "NoProxy for %s" : "UseProxy for %s", - r->uri); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r, + (direct_connect) ? "NoProxy for %s" : "UseProxy for %s", + r->uri); #endif } @@ -412,9 +415,10 @@ static int proxy_handler(request_rec *r) if (strcmp(ents[i].scheme, "*") == 0 || (p == NULL && strcasecmp(scheme, ents[i].scheme) == 0) || (p != NULL && - strncasecmp(url, ents[i].scheme, strlen(ents[i].scheme)) == 0)) { - /* CONNECT is a special method that bypasses the normal - * proxy code. + strncasecmp(url, ents[i].scheme, strlen(ents[i].scheme)) == 0)) { + /* + * CONNECT is a special method that bypasses the normal proxy + * code. */ #ifdef EAPI if (!ap_hook_use("ap::mod_proxy::handler", @@ -426,11 +430,11 @@ static int proxy_handler(request_rec *r) #endif /* EAPI */ if (r->method_number == M_CONNECT) rc = ap_proxy_connect_handler(r, cr, url, ents[i].hostname, - ents[i].port); + ents[i].port); /* we only know how to handle communication to a proxy via http */ else if (strcasecmp(ents[i].protocol, "http") == 0) rc = ap_proxy_http_handler(r, cr, url, ents[i].hostname, - ents[i].port); + ents[i].port); else rc = DECLINED; #ifdef EAPI @@ -444,10 +448,11 @@ static int proxy_handler(request_rec *r) } } -/* otherwise, try it direct */ -/* N.B. what if we're behind a firewall, where we must use a proxy or - * give up?? - */ + /* otherwise, try it direct */ + /* N.B. what if we're behind a firewall, where we must use a proxy or + * give up?? + */ + /* handle the scheme */ #ifdef EAPI if (ap_hook_use("ap::mod_proxy::handler", @@ -457,14 +462,23 @@ static int proxy_handler(request_rec *r) NULL, 0, scheme) && rc != DECLINED) return rc; #endif /* EAPI */ - if (r->method_number == M_CONNECT) + if (r->method_number == M_CONNECT) { return ap_proxy_connect_handler(r, cr, url, NULL, 0); - if (strcasecmp(scheme, "http") == 0) + } + if (strcasecmp(scheme, "http") == 0) { return ap_proxy_http_handler(r, cr, url, NULL, 0); - if (strcasecmp(scheme, "ftp") == 0) + } + if (strcasecmp(scheme, "ftp") == 0) { return ap_proxy_ftp_handler(r, cr, url); - else + } + else { + ap_log_rerror(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, r, + "proxy: No protocol handler was valid for the URL %s. " + "If you are using a DSO version of mod_proxy, make sure " + "the proxy submodules are included in the configuration " + "using LoadModule.", r->uri); return HTTP_FORBIDDEN; + } } /* -------------------------------------------------------------- */ @@ -483,11 +497,12 @@ static void * ps->nocaches = ap_make_array(p, 10, sizeof(struct nocache_entry)); ps->allowed_connect_ports = ap_make_array(p, 10, sizeof(int)); ps->domain = NULL; - ps->viaopt = via_off; /* initially backward compatible with 1.3.1 */ - ps->viaopt_set = 0; /* 0 means default */ + ps->viaopt = via_off; /* initially backward compatible with 1.3.1 */ + ps->viaopt_set = 0; /* 0 means default */ ps->req = 0; ps->req_set = 0; - ps->recv_buffer_size = 0; /* this default was left unset for some reason */ + ps->recv_buffer_size = 0; /* this default was left unset for some + * reason */ ps->recv_buffer_size_set = 0; ps->io_buffer_size = IOBUFSIZE; ps->io_buffer_size_set = 0; @@ -516,11 +531,11 @@ static void * static void * merge_proxy_config(pool *p, void *basev, - void *overridesv) + void *overridesv) { proxy_server_conf *ps = ap_pcalloc(p, sizeof(proxy_server_conf)); - proxy_server_conf *base = (proxy_server_conf *) basev; - proxy_server_conf *overrides = (proxy_server_conf *) overridesv; + proxy_server_conf *base = (proxy_server_conf *)basev; + proxy_server_conf *overrides = (proxy_server_conf *)overridesv; ps->proxies = ap_append_arrays(p, base->proxies, overrides->proxies); ps->aliases = ap_append_arrays(p, base->aliases, overrides->aliases); @@ -555,7 +570,7 @@ static const char * { server_rec *s = cmd->server; proxy_server_conf *conf = - (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module); + (proxy_server_conf *)ap_get_module_config(s->module_config, &proxy_module); struct proxy_remote *new; char *p, *q; int port; @@ -573,8 +588,8 @@ static const char * port = -1; *p = '\0'; if (strchr(f, ':') == NULL) - ap_str_tolower(f); /* lowercase scheme */ - ap_str_tolower(p + 3); /* lowercase hostname */ + ap_str_tolower(f); /* lowercase scheme */ + ap_str_tolower(p + 3); /* lowercase hostname */ if (port == -1) { int i; @@ -597,7 +612,7 @@ static const char * { server_rec *s = cmd->server; proxy_server_conf *conf = - (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module); + (proxy_server_conf *)ap_get_module_config(s->module_config, &proxy_module); struct proxy_alias *new; new = ap_push_array(conf->aliases); @@ -607,14 +622,14 @@ static const char * } static const char * - add_pass_reverse(cmd_parms *cmd, void *dummy, char *f, char *r) + add_pass_reverse(cmd_parms *cmd, void *dummy, char *f, char *r) { server_rec *s = cmd->server; proxy_server_conf *conf; struct proxy_alias *new; - conf = (proxy_server_conf *)ap_get_module_config(s->module_config, - &proxy_module); + conf = (proxy_server_conf *)ap_get_module_config(s->module_config, + &proxy_module); new = ap_push_array(conf->raliases); new->fake = f; new->real = r; @@ -644,7 +659,10 @@ static const char * new->name = arg; /* Don't do name lookups on things that aren't dotted */ if (strchr(arg, '.') != NULL && ap_proxy_host2addr(new->name, &hp) == NULL) - /*@@@FIXME: This copies only the first of (possibly many) IP addrs */ + /* + * @@@FIXME: This copies only the first of (possibly many) IP + * addrs + */ memcpy(&new->addr, hp.h_addr, sizeof(struct in_addr)); else new->addr.s_addr = 0; @@ -656,11 +674,11 @@ static const char * * Set the ports CONNECT can use */ static const char * - set_allowed_ports(cmd_parms *parms, void *dummy, char *arg) + set_allowed_ports(cmd_parms *parms, void *dummy, char *arg) { server_rec *s = parms->server; proxy_server_conf *conf = - ap_get_module_config(s->module_config, &proxy_module); + ap_get_module_config(s->module_config, &proxy_module); int *New; if (!ap_isdigit(arg[0])) @@ -681,7 +699,7 @@ static const char * proxy_server_conf *conf = ap_get_module_config(s->module_config, &proxy_module); struct dirconn_entry *New; - struct dirconn_entry *list = (struct dirconn_entry *) conf->dirconn->elts; + struct dirconn_entry *list = (struct dirconn_entry *)conf->dirconn->elts; int found = 0; int i; @@ -798,7 +816,7 @@ static const char * if (sscanf(arg, "%lg", &val) != 1) return "CacheMaxExpire value must be a float"; - psf->cache.maxexpire = (int) (val * (double) SEC_ONE_HR); + psf->cache.maxexpire = (int)(val * (double)SEC_ONE_HR); psf->cache.maxexpire_set = 1; return NULL; } @@ -812,7 +830,7 @@ static const char * if (sscanf(arg, "%lg", &val) != 1) return "CacheDefaultExpire value must be a float"; - psf->cache.defaultexpire = (int) (val * (double) SEC_ONE_HR); + psf->cache.defaultexpire = (int)(val * (double)SEC_ONE_HR); psf->cache.defaultexpire_set = 1; return NULL; } @@ -826,7 +844,7 @@ static const char * if (sscanf(arg, "%lg", &val) != 1) return "CacheGcInterval value must be a float"; - psf->cache.gcinterval = (int) (val * (double) SEC_ONE_HR); + psf->cache.gcinterval = (int)(val * (double)SEC_ONE_HR); psf->cache.gcinterval_set = 1; return NULL; } @@ -888,7 +906,10 @@ static const char * new->name = arg; /* Don't do name lookups on things that aren't dotted */ if (strchr(arg, '.') != NULL && ap_proxy_host2addr(new->name, &hp) == NULL) - /*@@@FIXME: This copies only the first of (possibly many) IP addrs */ + /* + * @@@FIXME: This copies only the first of (possibly many) IP + * addrs + */ memcpy(&new->addr, hp.h_addr, sizeof(struct in_addr)); else new->addr.s_addr = 0; @@ -923,26 +944,26 @@ static const char * return NULL; } -static const char* - set_cache_completion(cmd_parms *parms, void *dummy, char *arg) +static const char * + set_cache_completion(cmd_parms *parms, void *dummy, char *arg) { proxy_server_conf *psf = ap_get_module_config(parms->server->module_config, &proxy_module); int s = atoi(arg); if (s > 100 || s < 0) { return "CacheForceCompletion must be <= 100 percent, " - "or 0 for system default."; + "or 0 for system default."; } if (s > 0) - psf->cache.cache_completion = ((float)s / 100); + psf->cache.cache_completion = ((float)s / 100); psf->cache.cache_completion_set = 1; - return NULL; + return NULL; } -static const char* - set_via_opt(cmd_parms *parms, void *dummy, char *arg) +static const char * + set_via_opt(cmd_parms *parms, void *dummy, char *arg) { proxy_server_conf *psf = ap_get_module_config(parms->server->module_config, &proxy_module); @@ -957,11 +978,11 @@ static const char* psf->viaopt = via_full; else { return "ProxyVia must be one of: " - "off | on | full | block"; + "off | on | full | block"; } psf->viaopt_set = 1; - return NULL; + return NULL; } static const handler_rec proxy_handlers[] = @@ -973,47 +994,47 @@ static const handler_rec proxy_handlers[] = static const command_rec proxy_cmds[] = { {"ProxyRequests", set_proxy_req, NULL, RSRC_CONF, FLAG, - "on if the true proxy requests should be accepted"}, + "on if the true proxy requests should be accepted"}, {"ProxyRemote", add_proxy, NULL, RSRC_CONF, TAKE2, - "a scheme, partial URL or '*' and a proxy server"}, + "a scheme, partial URL or '*' and a proxy server"}, {"ProxyPass", add_pass, NULL, RSRC_CONF, TAKE2, - "a virtual path and a URL"}, + "a virtual path and a URL"}, {"ProxyPassReverse", add_pass_reverse, NULL, RSRC_CONF, TAKE2, - "a virtual path and a URL for reverse proxy behaviour"}, + "a virtual path and a URL for reverse proxy behaviour"}, {"ProxyBlock", set_proxy_exclude, NULL, RSRC_CONF, ITERATE, - "A list of names, hosts or domains to which the proxy will not connect"}, + "A list of names, hosts or domains to which the proxy will not connect"}, {"ProxyReceiveBufferSize", set_recv_buffer_size, NULL, RSRC_CONF, TAKE1, - "Receive buffer size for outgoing HTTP and FTP connections in bytes"}, + "Receive buffer size for outgoing HTTP and FTP connections in bytes"}, {"ProxyIOBufferSize", set_io_buffer_size, NULL, RSRC_CONF, TAKE1, - "IO buffer size for outgoing HTTP and FTP connections in bytes"}, + "IO buffer size for outgoing HTTP and FTP connections in bytes"}, {"NoProxy", set_proxy_dirconn, NULL, RSRC_CONF, ITERATE, - "A list of domains, hosts, or subnets to which the proxy will connect directly"}, + "A list of domains, hosts, or subnets to which the proxy will connect directly"}, {"ProxyDomain", set_proxy_domain, NULL, RSRC_CONF, TAKE1, - "The default intranet domain name (in absence of a domain in the URL)"}, + "The default intranet domain name (in absence of a domain in the URL)"}, {"AllowCONNECT", set_allowed_ports, NULL, RSRC_CONF, ITERATE, - "A list of ports which CONNECT may connect to"}, + "A list of ports which CONNECT may connect to"}, {"CacheRoot", set_cache_root, NULL, RSRC_CONF, TAKE1, - "The directory to store cache files"}, + "The directory to store cache files"}, {"CacheSize", set_cache_size, NULL, RSRC_CONF, TAKE1, - "The maximum disk space used by the cache in Kb"}, + "The maximum disk space used by the cache in Kb"}, {"CacheMaxExpire", set_cache_maxex, NULL, RSRC_CONF, TAKE1, - "The maximum time in hours to cache a document"}, + "The maximum time in hours to cache a document"}, {"CacheDefaultExpire", set_cache_defex, NULL, RSRC_CONF, TAKE1, - "The default time in hours to cache a document"}, + "The default time in hours to cache a document"}, {"CacheLastModifiedFactor", set_cache_factor, NULL, RSRC_CONF, TAKE1, - "The factor used to estimate Expires date from LastModified date"}, + "The factor used to estimate Expires date from LastModified date"}, {"CacheGcInterval", set_cache_gcint, NULL, RSRC_CONF, TAKE1, - "The interval between garbage collections, in hours"}, + "The interval between garbage collections, in hours"}, {"CacheDirLevels", set_cache_dirlevels, NULL, RSRC_CONF, TAKE1, - "The number of levels of subdirectories in the cache"}, + "The number of levels of subdirectories in the cache"}, {"CacheDirLength", set_cache_dirlength, NULL, RSRC_CONF, TAKE1, - "The number of characters in subdirectory names"}, + "The number of characters in subdirectory names"}, {"NoCache", set_cache_exclude, NULL, RSRC_CONF, ITERATE, - "A list of names, hosts or domains for which caching is *not* provided"}, + "A list of names, hosts or domains for which caching is *not* provided"}, {"CacheForceCompletion", set_cache_completion, NULL, RSRC_CONF, TAKE1, - "Force a http cache completion after this percentage is loaded"}, + "Force a http cache completion after this percentage is loaded"}, {"ProxyVia", set_via_opt, NULL, RSRC_CONF, TAKE1, - "Configure Via: proxy header header to one of: on | off | block | full"}, + "Configure Via: proxy header header to one of: on | off | block | full"}, {NULL} }; @@ -1045,5 +1066,3 @@ module MODULE_VAR_EXPORT proxy_module = NULL /* EAPI: new_connection */ #endif }; - - diff --git a/usr.sbin/httpd/src/modules/proxy/mod_proxy.h b/usr.sbin/httpd/src/modules/proxy/mod_proxy.h index 94178e5da3d..79d1ed8998b 100644 --- a/usr.sbin/httpd/src/modules/proxy/mod_proxy.h +++ b/usr.sbin/httpd/src/modules/proxy/mod_proxy.h @@ -297,7 +297,7 @@ char *ap_proxy_canon_netloc(pool *p, char **const urlp, char **userp, char **passwordp, char **hostp, int *port); const char *ap_proxy_date_canon(pool *p, const char *x); 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, off_t len, int nowrite, size_t recv_buffer_size); +long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int nowrite, int chunked, size_t recv_buffer_size); void ap_proxy_write_headers(cache_req *c, const char *respline, table *t); int ap_proxy_liststr(const char *list, const char *key, char **val); void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength); @@ -321,6 +321,7 @@ BUFF *ap_proxy_create_cachefile(request_rec *r, char *filename); void ap_proxy_clear_connection(pool *p, table *headers); int ap_proxy_table_replace(table *base, table *overlay); void ap_proxy_table_unmerge(pool *p, table *t, char *key); +int ap_proxy_read_response_line(BUFF *f, request_rec *r, char *buffer, int size, int *backasswards, int *major, int *minor); /* WARNING - PRIVATE DEFINITION BELOW */ diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_cache.c b/usr.sbin/httpd/src/modules/proxy/proxy_cache.c index 41d619e6b23..ff2bb0681f2 100644 --- a/usr.sbin/httpd/src/modules/proxy/proxy_cache.c +++ b/usr.sbin/httpd/src/modules/proxy/proxy_cache.c @@ -68,7 +68,7 @@ #include <sys/utime.h> #else #include <utime.h> -#endif /* WIN32 */ +#endif /* WIN32 */ #include "multithread.h" #include "ap_md5.h" #ifdef __TANDEM @@ -87,8 +87,8 @@ struct gc_ent { /* Poor man's 61 bit arithmetic */ typedef struct { - long lower; /* lower 30 bits of result */ - long upper; /* upper 31 bits of result */ + long lower; /* lower 30 bits of result */ + long upper; /* upper 31 bits of result */ } long61_t; /* FIXME: The block size can be different on a `per file system' base. @@ -123,7 +123,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); + 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) && !defined(NETWARE) && !defined(TPF) @@ -135,14 +135,14 @@ void ap_proxy_garbage_coll(request_rec *r) { static int inside = 0; - (void) ap_acquire_mutex(garbage_mutex); + (void)ap_acquire_mutex(garbage_mutex); if (inside == 1) { - (void) ap_release_mutex(garbage_mutex); + (void)ap_release_mutex(garbage_mutex); return; } else inside = 1; - (void) ap_release_mutex(garbage_mutex); + (void)ap_release_mutex(garbage_mutex); ap_block_alarms(); /* avoid SIGALRM on big cache cleanup */ if (should_proxy_garbage_coll(r)) @@ -153,14 +153,13 @@ void ap_proxy_garbage_coll(request_rec *r) #endif ap_unblock_alarms(); - (void) ap_acquire_mutex(garbage_mutex); + (void)ap_acquire_mutex(garbage_mutex); inside = 0; - (void) ap_release_mutex(garbage_mutex); + (void)ap_release_mutex(garbage_mutex); } -static void -add_long61 (long61_t *accu, long val) +static void add_long61(long61_t *accu, long val) { /* Add in lower 30 bits */ accu->lower += (val & 0x3FFFFFFFL); @@ -170,8 +169,7 @@ add_long61 (long61_t *accu, long val) accu->lower &= 0x3FFFFFFFL; } -static void -sub_long61 (long61_t *accu, long val) +static void sub_long61(long61_t *accu, long val) { int carry = (val & 0x3FFFFFFFL) > accu->lower; /* Subtract lower 30 bits */ @@ -185,11 +183,10 @@ sub_long61 (long61_t *accu, long val) * return 0 when left == right * return >0 when left > right */ -static long -cmp_long61 (long61_t *left, long61_t *right) +static long cmp_long61(long61_t *left, long61_t *right) { return (left->upper == right->upper) ? (left->lower - right->lower) - : (left->upper - right->upper); + : (left->upper - right->upper); } /* Compare two gc_ent's, sort them by expiration date */ @@ -215,66 +212,74 @@ static void detached_proxy_garbage_coll(request_rec *r) #if 0 ap_log_error(APLOG_MARK, APLOG_DEBUG, r->server, - "proxy: Guess what; we fork() again..."); + "proxy: Guess what; we fork() again..."); #endif switch (pid = fork()) { - case -1: - ap_log_error(APLOG_MARK, APLOG_ERR, r->server, - "proxy: fork() for cache cleanup failed"); - return; + case -1: + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "proxy: fork() for cache cleanup failed"); + return; - case 0: /* Child */ + case 0: /* Child */ - /* close all sorts of things, including the socket fd */ - ap_cleanup_for_exec(); + /* close all sorts of things, including the socket fd */ + ap_cleanup_for_exec(); - /* Fork twice to disassociate from the child */ - switch (pid = fork()) { - case -1: - ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + /* Fork twice to disassociate from the child */ + switch (pid = fork()) { + case -1: + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy: fork(2nd) for cache cleanup failed"); - exit(1); + exit(1); - case 0: /* Child */ - /* The setpgrp() stuff was snarfed from http_main.c */ + case 0: /* Child */ + /* The setpgrp() stuff was snarfed from http_main.c */ #ifndef NO_SETSID - if ((pgrp = setsid()) == -1) { - perror("setsid"); - fprintf(stderr, "%s: setsid failed\n", - ap_server_argv0); - exit(1); - } + if ((pgrp = setsid()) == -1) { + perror("setsid"); + fprintf(stderr, "%s: setsid failed\n", + ap_server_argv0); + exit(1); + } #elif defined(NEXT) || defined(NEWSOS) - if (setpgrp(0, getpid()) == -1 || (pgrp = getpgrp(0)) == -1) { - perror("setpgrp"); - fprintf(stderr, "%S: setpgrp or getpgrp failed\n", - ap_server_argv0); - exit(1); - } + if (setpgrp(0, getpid()) == -1 || (pgrp = getpgrp(0)) == -1) { + perror("setpgrp"); + fprintf(stderr, "%S: setpgrp or getpgrp failed\n", + ap_server_argv0); + exit(1); + } +#elif defined(CYGWIN) + /* Cygwin does not take any argument for setpgrp() */ + if ((pgrp = setpgrp()) == -1) { + perror("setpgrp"); + fprintf(stderr, "%S: setpgrp failed\n", + ap_server_argv0); + exit(1); + } #else - if ((pgrp = setpgrp(getpid(), 0)) == -1) { - perror("setpgrp"); - fprintf(stderr, "%s: setpgrp failed\n", - ap_server_argv0); - exit(1); - } + if ((pgrp = setpgrp(getpid(), 0)) == -1) { + perror("setpgrp"); + fprintf(stderr, "%s: setpgrp failed\n", + ap_server_argv0); + exit(1); + } #endif - help_proxy_garbage_coll(r); - exit(0); + help_proxy_garbage_coll(r); + exit(0); - default: /* Father */ - /* After grandson has been forked off, */ - /* there's nothing else to do. */ - exit(0); - } - default: - /* Wait until grandson has been forked off */ - /* (without wait we'd leave a zombie) */ - waitpid(pid, &status, 0); - return; + default: /* Father */ + /* After grandson has been forked off, */ + /* there's nothing else to do. */ + exit(0); + } + default: + /* Wait until grandson has been forked off */ + /* (without wait we'd leave a zombie) */ + waitpid(pid, &status, 0); + return; } } -#endif /* ndef WIN32 */ +#endif /* ndef WIN32 */ #define DOT_TIME "/.time" /* marker */ @@ -282,7 +287,7 @@ static int should_proxy_garbage_coll(request_rec *r) { void *sconf = r->server->module_config; proxy_server_conf *pconf = - (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); const struct cache_conf *conf = &pconf->cache; const char *cachedir = conf->root; @@ -290,34 +295,36 @@ static int should_proxy_garbage_coll(request_rec *r) struct stat buf; int timefd; time_t every = conf->gcinterval; - static time_t lastcheck = BAD_DATE; /* static (per-process) data!!! */ + static time_t lastcheck = BAD_DATE; /* static (per-process) data!!! */ if (cachedir == NULL || every == -1) return 0; - filename = ap_palloc(r->pool, strlen(cachedir) + strlen( DOT_TIME ) +1); + 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. + /* + * Usually, the modification time of <cachedir>/.time can only increase. * Thus, even with several child processes having their own copy of - * lastcheck, if time(NULL) still < lastcheck then it's not time - * for GC yet. + * lastcheck, if time(NULL) still < lastcheck then it's not time for GC + * yet. */ if (garbage_now != -1 && lastcheck != BAD_DATE && garbage_now < lastcheck + every) return 0; - strcpy(filename,cachedir); - strcat(filename,DOT_TIME); + 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. + /* + * 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 (stat(filename, &buf) == -1) { /* does not exist */ if (errno != ENOENT) { ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy: stat(%s)", filename); @@ -351,7 +358,7 @@ 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); + (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); const struct cache_conf *conf = &pconf->cache; array_header *files; struct gc_ent *fent; @@ -372,9 +379,9 @@ static void help_proxy_garbage_coll(request_rec *r) sub_garbage_coll(r, files, cachedir, "/"); if (cmp_long61(&curbytes, &cachesize) < 0L) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, - "proxy GC: Cache is %ld%% full (nothing deleted)", - (long)(((curbytes.upper<<20)|(curbytes.lower>>10))*100/conf->space)); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "proxy GC: Cache is %ld%% full (nothing deleted)", + (long)(((curbytes.upper << 20) | (curbytes.lower >> 10)) * 100 / conf->space)); ap_unblock_alarms(); return; } @@ -385,7 +392,7 @@ static void help_proxy_garbage_coll(request_rec *r) for (i = 0; i < files->nelts; i++) { fent = &((struct gc_ent *) files->elts)[i]; sprintf(filename, "%s%s", cachedir, fent->file); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "GC Unlinking %s (expiry %ld, garbage_now %ld)", filename, (long)fent->expire, (long)garbage_now); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "GC Unlinking %s (expiry %ld, garbage_now %ld)", filename, (long)fent->expire, (long)garbage_now); #if TESTING fprintf(stderr, "Would unlink %s\n", filename); #else @@ -403,16 +410,16 @@ static void help_proxy_garbage_coll(request_rec *r) } } - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, - "proxy GC: Cache is %ld%% full (%d deleted)", - (long)(((curbytes.upper<<20)|(curbytes.lower>>10))*100/conf->space), i); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "proxy GC: Cache is %ld%% full (%d deleted)", + (long)(((curbytes.upper << 20) | (curbytes.lower >> 10)) * 100 / conf->space), i); ap_unblock_alarms(); } static int sub_garbage_coll(request_rec *r, array_header *files, const char *cachebasedir, const char *cachesubdir) { - char line[17*(3)]; + char line[17 * (3)]; char cachedir[HUGE_STRING_LEN]; struct stat buf; int fd, i; @@ -428,7 +435,7 @@ static int sub_garbage_coll(request_rec *r, array_header *files, ap_snprintf(cachedir, sizeof(cachedir), "%s%s", cachebasedir, cachesubdir); filename = ap_palloc(r->pool, strlen(cachedir) + HASH_LEN + 2); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "GC Examining directory %s", cachedir); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "GC Examining directory %s", cachedir); dir = opendir(cachedir); if (dir == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, r->server, @@ -440,7 +447,7 @@ static int sub_garbage_coll(request_rec *r, array_header *files, if (ent->d_name[0] == '.') continue; sprintf(filename, "%s%s", cachedir, ent->d_name); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "GC Examining file %s", filename); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "GC Examining file %s", filename); /* is it a temporary file? */ if (strncmp(ent->d_name, "tmp", 3) == 0) { /* then stat it to see how old it is; delete temporary files > 1 day old */ @@ -451,9 +458,9 @@ static int sub_garbage_coll(request_rec *r, array_header *files, } else if (garbage_now != -1 && buf.st_atime < garbage_now - SEC_ONE_DAY && buf.st_mtime < garbage_now - SEC_ONE_DAY) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "GC unlink %s", filename); - ap_log_error(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, r->server, - "proxy gc: deleting orphaned cache file %s", filename); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "GC unlink %s", filename); + ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, r->server, + "proxy gc: deleting orphaned cache file %s", filename); #if TESTING fprintf(stderr, "Would unlink %s\n", filename); #else @@ -465,22 +472,23 @@ static int sub_garbage_coll(request_rec *r, array_header *files, ++nfiles; /* is it another file? */ /* FIXME: Shouldn't any unexpected files be deleted? */ - /* if (strlen(ent->d_name) != HASH_LEN) continue; */ + /* if (strlen(ent->d_name) != HASH_LEN) continue; */ /* under OS/2 use dirent's d_attr to identify a diretory */ /* under TPF use stat to identify a directory */ #if defined(OS2) || defined(TPF) /* is it a directory? */ #ifdef OS2 - if (ent->d_attr & A_DIR) { + if (ent->d_attr & A_DIR) #elif defined(TPF) - if (stat(filename, &buf) == -1) { - if (errno != ENOENT) - ap_log_error(APLOG_MARK, APLOG_ERR, r->server, - "proxy gc: stat(%s)", filename); - } - if (S_ISDIR(buf.st_mode)) { + if (stat(filename, &buf) == -1) { + if (errno != ENOENT) + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "proxy gc: stat(%s)", filename); + } + if (S_ISDIR(buf.st_mode)) #endif + { char newcachedir[HUGE_STRING_LEN]; ap_snprintf(newcachedir, sizeof(newcachedir), "%s%s/", cachesubdir, ent->d_name); @@ -500,9 +508,9 @@ static int sub_garbage_coll(request_rec *r, array_header *files, /* read the file */ #if defined(WIN32) - /* On WIN32 open does not work for directories, - * so we us stat instead of fstat to determine - * if the file is a directory + /* + * On WIN32 open does not work for directories, so we us stat instead + * of fstat to determine if the file is a directory */ if (stat(filename, &buf) == -1) { ap_log_error(APLOG_MARK, APLOG_ERR, r->server, @@ -545,7 +553,8 @@ static int sub_garbage_coll(request_rec *r, array_header *files, rmdir(newcachedir); #endif --nfiles; - } else { + } + else { /* Directory is not empty. Account for its size: */ add_long61(&curbytes, ROUNDUP2BLOCKS(buf.st_size)); } @@ -554,8 +563,9 @@ static int sub_garbage_coll(request_rec *r, array_header *files, #endif #if defined(WIN32) - /* Since we have determined above that the file is not a directory, - * it should be safe to open it now + /* + * Since we have determined above that the file is not a directory, + * it should be safe to open it now */ fd = open(filename, O_RDONLY | O_BINARY); if (fd == -1) { @@ -565,8 +575,8 @@ static int sub_garbage_coll(request_rec *r, array_header *files, continue; } #endif - - i = read(fd, line, 17*(3)-1); + + i = read(fd, line, 17 * (3) - 1); close(fd); if (i == -1) { ap_log_error(APLOG_MARK, APLOG_ERR, r->server, @@ -574,13 +584,13 @@ static int sub_garbage_coll(request_rec *r, array_header *files, continue; } line[i] = '\0'; - garbage_expire = ap_proxy_hex2sec(line + 17*(2)); + garbage_expire = ap_proxy_hex2sec(line + 17 * (2)); if (!ap_checkmask(line, "&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&") || garbage_expire == BAD_DATE) { /* bad file */ if (garbage_now != -1 && buf.st_atime > garbage_now + SEC_ONE_DAY && buf.st_mtime > garbage_now + SEC_ONE_DAY) { - ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, r->server, + ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, r->server, "proxy: deleting bad cache file with future date: %s", filename); #if TESTING fprintf(stderr, "Would unlink bad file %s\n", filename); @@ -632,49 +642,51 @@ static int rdcache(request_rec *r, BUFF *cachefp, cache_req *c) /* read the data from the cache file */ - /* Format: - * - * The cache needs to keep track of the following information: - * - Date, LastMod, Version, ReqTime, RespTime, ContentLength - * - The original request headers (for Vary) - * - The original response headers (for returning with a cached response) - * - The body of the message - * - * date SP lastmod SP expire SP count SP request-time SP response-time SP content-lengthCRLF - * (dates are stored as hex seconds since 1970) - * Original URLCRLF - * Original Request Headers - * CRLF - * Original Response Headers - * CRLF - * Body + /* + * Format: + * + * The cache needs to keep track of the following information: - Date, + * LastMod, Version, ReqTime, RespTime, ContentLength - The original + * request headers (for Vary) - The original response headers (for + * returning with a cached response) - The body of the message + * + * date SP lastmod SP expire SP count SP request-time SP response-time SP + * content-lengthCRLF (dates are stored as hex seconds since 1970) + * Original URLCRLF Original Request Headers CRLF Original Response + * Headers CRLF Body * */ /* retrieve cachefile information values */ len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); - if (len == -1) + if (len == -1) { + /* Delete broken cache file */ + unlink(c->filename); return -1; + } if (len == 0 || urlbuff[len - 1] != '\n') return 0; urlbuff[len - 1] = '\0'; if (!ap_checkmask(urlbuff, - "&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&")) + "&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&")) return 0; - c->date = ap_proxy_hex2sec(urlbuff + 17*(0)); - c->lmod = ap_proxy_hex2sec(urlbuff + 17*(1)); - c->expire = ap_proxy_hex2sec(urlbuff + 17*(2)); - c->version = ap_proxy_hex2sec(urlbuff + 17*(3)); - c->req_time = ap_proxy_hex2sec(urlbuff + 17*(4)); - c->resp_time = ap_proxy_hex2sec(urlbuff + 17*(5)); - c->len = ap_proxy_hex2sec(urlbuff + 17*(6)); + c->date = ap_proxy_hex2sec(urlbuff + 17 * (0)); + c->lmod = ap_proxy_hex2sec(urlbuff + 17 * (1)); + c->expire = ap_proxy_hex2sec(urlbuff + 17 * (2)); + c->version = ap_proxy_hex2sec(urlbuff + 17 * (3)); + c->req_time = ap_proxy_hex2sec(urlbuff + 17 * (4)); + c->resp_time = ap_proxy_hex2sec(urlbuff + 17 * (5)); + c->len = ap_proxy_hex2sec(urlbuff + 17 * (6)); /* check that we have the same URL */ len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); - if (len == -1) + if (len == -1) { + /* Delete broken cache file */ + unlink(c->filename); return -1; + } if (len == 0 || strncmp(urlbuff, "X-URL: ", 7) != 0 || urlbuff[len - 1] != '\n') return 0; @@ -684,13 +696,19 @@ static int rdcache(request_rec *r, BUFF *cachefp, cache_req *c) /* then the original request headers */ c->req_hdrs = ap_proxy_read_headers(r, urlbuff, sizeof urlbuff, cachefp); - if (c->req_hdrs == NULL) + if (c->req_hdrs == NULL) { + /* Delete broken cache file */ + unlink(c->filename); return -1; + } /* then the original response headers */ len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); - if (len == -1) + if (len == -1) { + /* Delete broken cache file */ + unlink(c->filename); return -1; + } if (len == 0 || urlbuff[len - 1] != '\n') return 0; urlbuff[--len] = '\0'; @@ -702,15 +720,18 @@ static int rdcache(request_rec *r, BUFF *cachefp, cache_req *c) c->status = atoi(strp); c->hdrs = ap_proxy_read_headers(r, urlbuff, sizeof urlbuff, cachefp); - if (c->hdrs == NULL) + if (c->hdrs == NULL) { + /* Delete broken cache file */ + unlink(c->filename); return -1; - if (c->len != -1) /* add a content-length header */ + } + if (c->len != -1) /* add a content-length header */ if (ap_table_get(c->hdrs, "Content-Length") == NULL) { ap_table_set(c->hdrs, "Content-Length", ap_psprintf(r->pool, "%lu", (unsigned long)c->len)); } - + return 1; } @@ -735,52 +756,53 @@ int ap_proxy_cache_conditional(request_rec *r, cache_req *c, BUFF *cachefp) /* check for If-Match, If-Unmodified-Since */ while (1) { - /* check If-Match and If-Unmodified-Since exist - * - * If neither of these exist, the request is not conditional, and - * we serve it normally + /* + * check If-Match and If-Unmodified-Since exist + * + * If neither of these exist, the request is not conditional, and we + * serve it normally */ if (!c->im && BAD_DATE == c->ius) { break; } - /* check If-Match - * - * we check if the Etag on the cached file is in the list of Etags - * in the If-Match field. The comparison must be a strong comparison, - * so the Etag cannot be marked as weak. If the comparision fails - * we return 412 Precondition Failed. - * - * if If-Match is specified AND - * If-Match is not a "*" AND - * Etag is missing or weak or not in the list THEN - * return 412 Precondition Failed + /* + * check If-Match + * + * we check if the Etag on the cached file is in the list of Etags in + * the If-Match field. The comparison must be a strong comparison, so + * the Etag cannot be marked as weak. If the comparision fails we + * return 412 Precondition Failed. + * + * if If-Match is specified AND If-Match is not a "*" AND Etag is + * missing or weak or not in the list THEN return 412 Precondition + * Failed */ if (c->im) { if (strcmp(c->im, "*") && - (!etag || (strlen(etag) > 1 && 'W' == etag[0] && '/' == etag[1]) || !ap_proxy_liststr(c->im, etag, NULL))) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "If-Match specified, and it didn't - return 412"); + (!etag || (strlen(etag) > 1 && 'W' == etag[0] && '/' == etag[1]) || !ap_proxy_liststr(c->im, etag, NULL))) { + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Match specified, and it didn't - return 412"); } else { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "If-Match specified, and it matched"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Match specified, and it matched"); break; } } - /* check If-Unmodified-Since - * - * if If-Unmodified-Since is specified AND - * Last-Modified is specified somewhere AND - * If-Unmodified-Since is in the past compared to Last-Modified THEN - * return 412 Precondition Failed + /* + * check If-Unmodified-Since + * + * if If-Unmodified-Since is specified AND Last-Modified is specified + * somewhere AND If-Unmodified-Since is in the past compared to + * Last-Modified THEN return 412 Precondition Failed */ if (BAD_DATE != c->ius && BAD_DATE != c->lmod) { if (c->ius < c->lmod) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "If-Unmodified-Since specified, but it wasn't - return 412"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Unmodified-Since specified, but it wasn't - return 412"); } else { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "If-Unmodified-Since specified, and it was unmodified"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Unmodified-Since specified, and it was unmodified"); break; } } @@ -788,13 +810,13 @@ int ap_proxy_cache_conditional(request_rec *r, cache_req *c, BUFF *cachefp) /* if cache file is being updated */ if (c->origfp) { ap_proxy_write_headers(c, c->resp_line, c->hdrs); - ap_proxy_send_fb(c->origfp, r, c, c->len, 1, IOBUFSIZE); + ap_proxy_send_fb(c->origfp, r, c, c->len, 1, 0, IOBUFSIZE); ap_proxy_cache_tidy(c); } else ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR)); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Use your cached copy, conditional precondition failed."); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Use your cached copy, conditional precondition failed."); return HTTP_PRECONDITION_FAILED; } @@ -802,53 +824,54 @@ int ap_proxy_cache_conditional(request_rec *r, cache_req *c, BUFF *cachefp) /* check for If-None-Match, If-Modified-Since */ while (1) { - /* check for existance of If-None-Match and If-Modified-Since - * - * if neither of these headers have been set, then the request - * is not conditional, and we just send the cached response and - * be done with it. + /* + * check for existance of If-None-Match and If-Modified-Since + * + * if neither of these headers have been set, then the request is not + * conditional, and we just send the cached response and be done with + * it. */ if (!c->inm && BAD_DATE == c->ims) { break; } - /* check If-None-Match - * - * we check if the Etag on the cached file is in the list of Etags - * in the If-None-Match field. The comparison must be a strong comparison, - * so the Etag cannot be marked as weak. If the comparision fails - * we return 412 Precondition Failed. - * - * if If-None-Match is specified: - * if If-None-Match is a "*" THEN 304 - * else if Etag is specified AND we get a match THEN 304 - * else if Weak Etag is specified AND we get a match THEN 304 - * else sent the original object + /* + * check If-None-Match + * + * we check if the Etag on the cached file is in the list of Etags in + * the If-None-Match field. The comparison must be a strong + * comparison, so the Etag cannot be marked as weak. If the + * comparision fails we return 412 Precondition Failed. + * + * if If-None-Match is specified: if If-None-Match is a "*" THEN 304 + * else if Etag is specified AND we get a match THEN 304 else if Weak + * Etag is specified AND we get a match THEN 304 else sent the + * original object */ if (c->inm) { if (!strcmp(c->inm, "*")) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "If-None-Match: * specified, return 304"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-None-Match: * specified, return 304"); } else if (etag && ap_proxy_liststr(c->inm, etag, NULL)) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "If-None-Match: specified and we got a strong match - return 304"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-None-Match: specified and we got a strong match - return 304"); } else if (wetag && ap_proxy_liststr(c->inm, wetag, NULL)) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "If-None-Match specified, and we got a weak match - return 304"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-None-Match specified, and we got a weak match - return 304"); } else break; } - /* check If-Modified-Since - * - * if If-Modified-Since is specified AND - * Last-Modified is specified somewhere: - * if last modification date is earlier than If-Modified-Since THEN 304 - * else send the original object + /* + * check If-Modified-Since + * + * if If-Modified-Since is specified AND Last-Modified is specified + * somewhere: if last modification date is earlier than + * If-Modified-Since THEN 304 else send the original object */ if (BAD_DATE != c->ims && BAD_DATE != c->lmod) { if (c->ims >= c->lmod) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "If-Modified-Since specified and not modified, try return 304"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Modified-Since specified and not modified, try return 304"); } else break; @@ -858,47 +881,43 @@ int ap_proxy_cache_conditional(request_rec *r, cache_req *c, BUFF *cachefp) /* are we updating the cache file? */ if (c->origfp) { ap_proxy_write_headers(c, c->resp_line, c->hdrs); - ap_proxy_send_fb(c->origfp, r, c, c->len, 1, IOBUFSIZE); + ap_proxy_send_fb(c->origfp, r, c, c->len, 1, 0, IOBUFSIZE); ap_proxy_cache_tidy(c); } else ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR)); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Use local copy, cached file hasn't changed"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Use local copy, cached file hasn't changed"); return HTTP_NOT_MODIFIED; } /* No conditional - just send it cousin! */ - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Local copy modified, send it"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Local copy modified, send it"); r->status_line = strchr(c->resp_line, ' ') + 1; r->status = c->status; /* Prepare and send headers to client */ - ap_overlap_tables(r->headers_out, c->hdrs, AP_OVERLAP_TABLES_SET); + ap_proxy_table_replace(r->headers_out, c->hdrs); /* make sure our X-Cache header does not stomp on a previous header */ ap_table_mergen(r->headers_out, "X-Cache", c->xcache); /* content type is already set in the headers */ r->content_type = ap_table_get(r->headers_out, "Content-Type"); - /* cookies are special: they must not be merged (stupid browsers) */ - ap_proxy_table_unmerge(r->pool, r->headers_out, "Set-Cookie"); - ap_proxy_table_unmerge(r->pool, r->headers_out, "Set-Cookie2"); - ap_send_http_header(r); /* are we rewriting the cache file? */ if (c->origfp) { ap_proxy_write_headers(c, c->resp_line, c->hdrs); - ap_proxy_send_fb(c->origfp, r, c, c->len, r->header_only, IOBUFSIZE); + ap_proxy_send_fb(c->origfp, r, c, c->len, r->header_only, 0, IOBUFSIZE); ap_proxy_cache_tidy(c); return OK; } /* no, we not */ if (!r->header_only) { - ap_proxy_send_fb(cachefp, r, NULL, c->len, 0, IOBUFSIZE); + ap_proxy_send_fb(cachefp, r, NULL, c->len, 0, 0, IOBUFSIZE); } else { ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR)); @@ -922,17 +941,17 @@ int ap_proxy_cache_conditional(request_rec *r, cache_req *c, BUFF *cachefp) * if last modified after if-modified-since then add * last modified date to request */ -int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, - cache_req **cr) +int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf * conf, + cache_req **cr) { - const char *datestr, *pragma_req = NULL, *pragma_cresp = NULL, *cc_req = NULL, *cc_cresp = NULL, *vary = NULL; + const char *datestr, *pragma_req = NULL, *pragma_cresp = NULL, *cc_req = NULL, + *cc_cresp = NULL; cache_req *c; - time_t now; BUFF *cachefp; int i; void *sconf = r->server->module_config; proxy_server_conf *pconf = - (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); const char *agestr = NULL; char *val; time_t age_c = 0; @@ -948,7 +967,7 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, c->origfp = NULL; c->version = 0; c->len = -1; - c->req_hdrs = NULL; + c->req_hdrs = NULL; c->hdrs = NULL; c->xcache = NULL; @@ -957,10 +976,10 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, datestr = ap_table_get(r->headers_in, "If-Modified-Since"); if (datestr != NULL) { /* this may modify the value in the original table */ - datestr = ap_proxy_date_canon(r->pool, datestr); - c->ims = ap_parseHTTPdate(datestr); - if (c->ims == BAD_DATE) /* bad or out of range date; remove it */ - ap_table_unset(r->headers_in, "If-Modified-Since"); + datestr = ap_proxy_date_canon(r->pool, datestr); + c->ims = ap_parseHTTPdate(datestr); + if (c->ims == BAD_DATE) /* bad or out of range date; remove it */ + ap_table_unset(r->headers_in, "If-Modified-Since"); } /* get the If-Unmodified-Since date of the request, if it exists */ @@ -968,15 +987,15 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, datestr = ap_table_get(r->headers_in, "If-Unmodified-Since"); if (datestr != NULL) { /* this may modify the value in the original table */ - datestr = ap_proxy_date_canon(r->pool, datestr); - c->ius = ap_parseHTTPdate(datestr); - if (c->ius == BAD_DATE) /* bad or out of range date; remove it */ - ap_table_unset(r->headers_in, "If-Unmodified-Since"); + datestr = ap_proxy_date_canon(r->pool, datestr); + c->ius = ap_parseHTTPdate(datestr); + if (c->ius == BAD_DATE) /* bad or out of range date; remove it */ + ap_table_unset(r->headers_in, "If-Unmodified-Since"); } - + /* get the If-Match of the request, if it exists */ c->im = ap_table_get(r->headers_in, "If-Match"); - + /* get the If-None-Match of the request, if it exists */ c->inm = ap_table_get(r->headers_in, "If-None-Match"); @@ -984,13 +1003,13 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, if (conf->root != NULL) { char hashfile[66]; ap_proxy_hash(url, hashfile, pconf->cache.dirlevels, pconf->cache.dirlength); - c->filename = ap_pstrcat(r->pool, conf->root, "/", hashfile, NULL); + c->filename = ap_pstrcat(r->pool, conf->root, "/", hashfile, NULL); } else { - c->filename = NULL; - c->fp = NULL; - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "No CacheRoot, so no caching. Declining."); - return DECLINED; + c->filename = NULL; + c->fp = NULL; + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "No CacheRoot, so no caching. Declining."); + return DECLINED; } /* find certain cache controlling headers */ @@ -1013,35 +1032,37 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, if (ap_proxy_liststr(cc_req, "no-store", NULL)) { /* delete the previously cached file */ - if (c->filename) - unlink(c->filename); - c->fp = NULL; - c->filename = NULL; - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "no-store forbids caching. Declining."); - return DECLINED; + if (c->filename) + unlink(c->filename); + c->fp = NULL; + c->filename = NULL; + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "no-store forbids caching. Declining."); + return DECLINED; } /* if the cache file exists, open it */ cachefp = NULL; - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Request for %s, pragma_req=%s, ims=%ld", url, - pragma_req, c->ims); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Request for %s, pragma_req=%s, ims=%ld", url, + (pragma_req == NULL) ? "(unset)" : pragma_req, c->ims); /* find out about whether the request can access the cache */ if (c->filename != NULL && r->method_number == M_GET && - strlen(url) < 1024 ) { - cachefp = ap_proxy_open_cachefile(r, c->filename); + strlen(url) < 1024) { + cachefp = ap_proxy_open_cachefile(r, c->filename); } - /* if a cache file exists, try reading body and headers from cache file */ + /* + * if a cache file exists, try reading body and headers from cache file + */ if (cachefp != NULL) { i = rdcache(r, cachefp, c); if (i == -1) ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "proxy: error reading cache file %s", - c->filename); + "proxy: error reading cache file %s", + c->filename); else if (i == 0) - ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r, - "proxy: bad (short?) cache file: %s", c->filename); + ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r, + "proxy: bad (short?) cache file: %s", c->filename); if (i != 1) { ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR)); cachefp = NULL; @@ -1049,7 +1070,6 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, if (c->hdrs) { cc_cresp = ap_table_get(c->hdrs, "Cache-Control"); pragma_cresp = ap_table_get(c->hdrs, "Pragma"); - vary = ap_table_get(c->hdrs, "Vary"); if ((agestr = ap_table_get(c->hdrs, "Age"))) { age_c = atoi(agestr); } @@ -1065,16 +1085,17 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, */ /* FIXME: Shouldn't we check the URL somewhere? */ - /* Check Content-Negotiation - Vary - * + /* + * Check Content-Negotiation - Vary + * * At this point we need to make sure that the object we found in the cache * is the same object that would be delivered to the client, when the * effects of content negotiation are taken into effect. - * + * * In plain english, we want to make sure that a language-negotiated * document in one language is not given to a client asking for a * language negotiated document in a different language by mistake. - * + * * RFC2616 13.6 and 14.44 describe the Vary mechanism. */ if (c->hdrs && c->req_hdrs) { @@ -1092,8 +1113,10 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, ++vary; } - /* is this header in the request and the header in the cached - * request identical? If not, we give up and do a straight get */ + /* + * is this header in the request and the header in the cached + * request identical? If not, we give up and do a straight get + */ h1 = ap_table_get(r->headers_in, name); h2 = ap_table_get(c->req_hdrs, name); if (h1 == h2) { @@ -1106,42 +1129,43 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, /* headers do not match, so Vary failed */ c->fp = cachefp; - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Vary header mismatch - object must be fetched from scratch. Declining."); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Vary header mismatch - object must be fetched from scratch. Declining."); return DECLINED; } } } - /* We now want to check if our cached data is still fresh. This depends + /* + * We now want to check if our cached data is still fresh. This depends * on a few things, in this order: - * - * - RFC2616 14.9.4 End to end reload, Cache-Control: no-cache - * no-cache in either the request or the cached response means that - * we must revalidate the request unconditionally, overriding any - * expiration mechanism. It's equivalent to max-age=0,must-revalidate. - * - * - RFC2616 14.32 Pragma: no-cache - * This is treated the same as Cache-Control: no-cache. - * - * - RFC2616 14.9.3 Cache-Control: max-stale, must-revalidate, proxy-revalidate - * if the max-stale request header exists, modify the stale calculations - * below so that an object can be at most <max-stale> seconds stale before - * we request a revalidation, _UNLESS_ a must-revalidate or - * proxy-revalidate cached response header exists to stop us doing this. - * - * - RFC2616 14.9.3 Cache-Control: s-maxage - * the origin server specifies the maximum age an object can be before - * it is considered stale. This directive has the effect of proxy|must - * revalidate, which in turn means simple ignore any max-stale setting. - * - * - RFC2616 14.9.4 Cache-Control: max-age - * this header can appear in both requests and responses. If both are - * specified, the smaller of the two takes priority. - * - * - RFC2616 14.21 Expires: - * if this request header exists in the cached entity, and it's value is - * in the past, it has expired. + * + * - RFC2616 14.9.4 End to end reload, Cache-Control: no-cache no-cache in + * either the request or the cached response means that we must + * revalidate the request unconditionally, overriding any expiration + * mechanism. It's equivalent to max-age=0,must-revalidate. + * + * - RFC2616 14.32 Pragma: no-cache This is treated the same as + * Cache-Control: no-cache. + * + * - RFC2616 14.9.3 Cache-Control: max-stale, must-revalidate, + * proxy-revalidate if the max-stale request header exists, modify the + * stale calculations below so that an object can be at most <max-stale> + * seconds stale before we request a revalidation, _UNLESS_ a + * must-revalidate or proxy-revalidate cached response header exists to + * stop us doing this. + * + * - RFC2616 14.9.3 Cache-Control: s-maxage the origin server specifies the + * maximum age an object can be before it is considered stale. This + * directive has the effect of proxy|must revalidate, which in turn means + * simple ignore any max-stale setting. + * + * - RFC2616 14.9.4 Cache-Control: max-age this header can appear in both + * requests and responses. If both are specified, the smaller of the two + * takes priority. + * + * - RFC2616 14.21 Expires: if this request header exists in the cached + * entity, and it's value is in the past, it has expired. * */ @@ -1156,17 +1180,19 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, /* extract max-age from request */ if (cc_req && ap_proxy_liststr(cc_req, "max-age", &val)) - maxage_req = atoi(val); + maxage_req = atoi(val); else maxage_req = -1; /* extract max-age from response */ if (cc_cresp && ap_proxy_liststr(cc_cresp, "max-age", &val)) - maxage_cresp = atoi(val); + maxage_cresp = atoi(val); else maxage_cresp = -1; - /* if both maxage request and response, the smaller one takes priority */ + /* + * if both maxage request and response, the smaller one takes priority + */ if (-1 == maxage_req) maxage = maxage_cresp; else if (-1 == maxage_cresp) @@ -1176,48 +1202,46 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, /* extract max-stale */ if (cc_req && ap_proxy_liststr(cc_req, "max-stale", &val)) - maxstale = atoi(val); + maxstale = atoi(val); else maxstale = 0; /* extract min-fresh */ if (cc_req && ap_proxy_liststr(cc_req, "min-fresh", &val)) - minfresh = atoi(val); + minfresh = atoi(val); else minfresh = 0; /* override maxstale if must-revalidate or proxy-revalidate */ - if (maxstale && ( (cc_cresp && ap_proxy_liststr(cc_cresp, "must-revalidate", NULL)) || (cc_cresp && ap_proxy_liststr(cc_cresp, "proxy-revalidate", NULL)) )) + if (maxstale && ((cc_cresp && ap_proxy_liststr(cc_cresp, "must-revalidate", NULL)) || (cc_cresp && ap_proxy_liststr(cc_cresp, "proxy-revalidate", NULL)))) maxstale = 0; - now = time(NULL); if (cachefp != NULL && - /* handle no-cache */ - !( (cc_req && ap_proxy_liststr(cc_req, "no-cache", NULL)) || + /* handle no-cache */ + !((cc_req && ap_proxy_liststr(cc_req, "no-cache", NULL)) || (pragma_req && ap_proxy_liststr(pragma_req, "no-cache", NULL)) || (cc_cresp && ap_proxy_liststr(cc_cresp, "no-cache", NULL)) || - (pragma_cresp && ap_proxy_liststr(pragma_cresp, "no-cache", NULL)) ) && - - /* handle expiration */ - ( (-1 < smaxage && age < (smaxage - minfresh)) || - (-1 < maxage && age < (maxage + maxstale - minfresh)) || - (c->expire != BAD_DATE && age < (c->expire - c->date + maxstale - minfresh)) ) + (pragma_cresp && ap_proxy_liststr(pragma_cresp, "no-cache", NULL))) && + /* handle expiration */ + ((-1 < smaxage && age < (smaxage - minfresh)) || + (-1 < maxage && age < (maxage + maxstale - minfresh)) || + (c->expire != BAD_DATE && age < (c->expire - c->date + maxstale - minfresh))) ) { /* it's fresh darlings... */ - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Unexpired data available"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Unexpired data available"); /* set age header on response */ ap_table_set(c->hdrs, "Age", - ap_psprintf(r->pool, "%lu", (unsigned long)age)); + ap_psprintf(r->pool, "%lu", (unsigned long)age)); /* add warning if maxstale overrode freshness calculation */ - if (!( (-1 < smaxage && age < smaxage) || - (-1 < maxage && age < maxage) || - (c->expire != BAD_DATE && (c->expire - c->date) > age) )) { + if (!((-1 < smaxage && age < smaxage) || + (-1 < maxage && age < maxage) || + (c->expire != BAD_DATE && (c->expire - c->date) > age))) { /* make sure we don't stomp on a previous warning */ ap_table_merge(c->hdrs, "Warning", "110 Response is stale"); } @@ -1229,11 +1253,12 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, } - /* at this point we have determined our cached data needs revalidation + /* + * at this point we have determined our cached data needs revalidation * but first - we check 1 thing: - * - * RFC2616 14.9.4 - if "only-if-cached" specified, send a - * 504 Gateway Timeout - we're not allowed to revalidate the object + * + * RFC2616 14.9.4 - if "only-if-cached" specified, send a 504 Gateway + * Timeout - we're not allowed to revalidate the object */ if (ap_proxy_liststr(cc_req, "only-if-cached", NULL)) { if (cachefp) @@ -1242,12 +1267,13 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, } - /* If we already have cached data and a last-modified date, and it is - * not a head request, then add an If-Modified-Since. - * - * If we also have an Etag, then the object must have come from - * an HTTP/1.1 server. Add an If-None-Match as well. - * + /* + * If we already have cached data and a last-modified date, and it is not + * a head request, then add an If-Modified-Since. + * + * If we also have an Etag, then the object must have come from an HTTP/1.1 + * server. Add an If-None-Match as well. + * * See RFC2616 13.3.4 */ @@ -1257,13 +1283,15 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, /* If-Modified-Since */ if (c->lmod != BAD_DATE) { - /* use the later of the one from the request and the last-modified date - * from the cache */ + /* + * use the later of the one from the request and the + * last-modified date from the cache + */ if (c->ims == BAD_DATE || c->ims < c->lmod) { const char *q; if ((q = ap_table_get(c->hdrs, "Last-Modified")) != NULL) - ap_table_set(r->headers_in, "If-Modified-Since", (char *) q); + ap_table_set(r->headers_in, "If-Modified-Since", (char *)q); } } @@ -1277,7 +1305,7 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, c->fp = cachefp; - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Local copy not present or expired. Declining."); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Local copy not present or expired. Declining."); return DECLINED; } @@ -1295,19 +1323,19 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, * otherwise, delete the old cached file and open a new temporary file */ int ap_proxy_cache_update(cache_req *c, table *resp_hdrs, - const int is_HTTP1, int nocache) + const int is_HTTP1, int nocache) { #if defined(ULTRIX_BRAIN_DEATH) || defined(SINIX_D_RESOLVER_BUG) - extern char *mktemp(char *template); -#endif + extern char *mktemp(char *template); +#endif request_rec *r = c->req; char *p; const char *expire, *lmods, *dates, *clen; time_t expc, date, lmod, now; - char buff[17*7+1]; + char buff[17 * 7 + 1]; void *sconf = r->server->module_config; proxy_server_conf *conf = - (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); const char *cc_resp; table *req_hdrs; @@ -1316,9 +1344,11 @@ int ap_proxy_cache_update(cache_req *c, table *resp_hdrs, c->tempfile = NULL; /* we've received the response from the origin server */ - - /* read expiry date; if a bad date, then leave it so the client can - * read it */ + + /* + * read expiry date; if a bad date, then leave it so the client can read + * it + */ expire = ap_table_get(resp_hdrs, "Expires"); if (expire != NULL) expc = ap_parseHTTPdate(expire); @@ -1340,55 +1370,66 @@ int ap_proxy_cache_update(cache_req *c, table *resp_hdrs, /* * what responses should we not cache? - * - * At this point we decide based on the response headers whether it - * is appropriate _NOT_ to cache the data from the server. There are - * a whole lot of conditions that prevent us from caching this data. - * They are tested here one by one to be clear and unambiguous. */ - - /* RFC2616 13.4 we are allowed to cache 200, 203, 206, 300, 301 or 410 - * We don't cache 206, because we don't (yet) cache partial responses. - * We include 304 Not Modified here too as this is the origin server - * telling us to serve the cached copy. */ + * + * At this point we decide based on the response headers whether it is + * appropriate _NOT_ to cache the data from the server. There are a whole + * lot of conditions that prevent us from caching this data. They are + * tested here one by one to be clear and unambiguous. + */ + + /* + * RFC2616 13.4 we are allowed to cache 200, 203, 206, 300, 301 or 410 We + * don't cache 206, because we don't (yet) cache partial responses. We + * include 304 Not Modified here too as this is the origin server telling + * us to serve the cached copy. + */ if ((r->status != HTTP_OK && r->status != HTTP_NON_AUTHORITATIVE && r->status != HTTP_MULTIPLE_CHOICES && r->status != HTTP_MOVED_PERMANENTLY && r->status != HTTP_NOT_MODIFIED) || /* if a broken Expires header is present, don't cache it */ (expire != NULL && expc == BAD_DATE) || - /* if the server said 304 Not Modified but we have no cache file - pass - * this untouched to the user agent, it's not for us. */ + /* + * if the server said 304 Not Modified but we have no cache file - pass + * this untouched to the user agent, it's not for us. + */ (r->status == HTTP_NOT_MODIFIED && (c == NULL || c->fp == NULL)) || - /* 200 OK response from HTTP/1.0 and up without a Last-Modified header */ + /* + * 200 OK response from HTTP/1.0 and up without a Last-Modified header + */ (r->status == HTTP_OK && lmods == NULL && is_HTTP1) || /* HEAD requests */ r->header_only || - /* RFC2616 14.9.2 Cache-Control: no-store response indicating do not - * cache, or stop now if you are trying to cache it */ + /* + * RFC2616 14.9.2 Cache-Control: no-store response indicating do not + * cache, or stop now if you are trying to cache it + */ ap_proxy_liststr(cc_resp, "no-store", NULL) || - /* RFC2616 14.9.1 Cache-Control: private - * this object is marked for this user's eyes only. Behave as a tunnel. */ + /* + * RFC2616 14.9.1 Cache-Control: private this object is marked for this + * user's eyes only. Behave as a tunnel. + */ ap_proxy_liststr(cc_resp, "private", NULL) || - /* RFC2616 14.8 Authorisation: - * if authorisation is included in the request, we don't cache, but we - * can cache if the following exceptions are true: - * 1) If Cache-Control: s-maxage is included - * 2) If Cache-Control: must-revalidate is included - * 3) If Cache-Control: public is included + /* + * RFC2616 14.8 Authorisation: if authorisation is included in the + * request, we don't cache, but we can cache if the following exceptions + * are true: 1) If Cache-Control: s-maxage is included 2) If + * Cache-Control: must-revalidate is included 3) If Cache-Control: public + * is included */ (ap_table_get(r->headers_in, "Authorization") != NULL - && !(ap_proxy_liststr(cc_resp, "s-maxage", NULL) || ap_proxy_liststr(cc_resp, "must-revalidate", NULL) || ap_proxy_liststr(cc_resp, "public", NULL)) - ) || + && !(ap_proxy_liststr(cc_resp, "s-maxage", NULL) || ap_proxy_liststr(cc_resp, "must-revalidate", NULL) || ap_proxy_liststr(cc_resp, "public", NULL)) + ) || /* or we've been asked not to cache it above */ nocache) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Response is not cacheable, unlinking %s", c->filename); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Response is not cacheable, unlinking %s", c->filename); /* close the file */ if (c->fp != NULL) { @@ -1403,15 +1444,15 @@ int ap_proxy_cache_update(cache_req *c, table *resp_hdrs, } - /* It's safe to cache the response. - * - * We now want to update the cache file header information with - * the new date, last modified, expire and content length and write - * it away to our cache file. First, we determine these values from - * the response, using heuristics if appropriate. - * - * In addition, we make HTTP/1.1 age calculations and write them away - * too. + /* + * It's safe to cache the response. + * + * We now want to update the cache file header information with the new + * date, last modified, expire and content length and write it away to + * our cache file. First, we determine these values from the response, + * using heuristics if appropriate. + * + * In addition, we make HTTP/1.1 age calculations and write them away too. */ /* Read the date. Generate one if one is not supplied */ @@ -1430,7 +1471,7 @@ int ap_proxy_cache_update(cache_req *c, table *resp_hdrs, date = now; dates = ap_gm_timestr_822(r->pool, now); ap_table_set(resp_hdrs, "Date", dates); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Added date header"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Added date header"); } /* set response_time for HTTP/1.1 age calculations */ @@ -1442,16 +1483,17 @@ int ap_proxy_cache_update(cache_req *c, table *resp_hdrs, { lmod = date; lmods = dates; - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Last modified is in the future, replacing with now"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Last modified is in the future, replacing with now"); } /* if the response did not contain the header, then use the cached version */ if (lmod == BAD_DATE && c->fp != NULL) { lmod = c->lmod; - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Reusing cached last modified"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Reusing cached last modified"); } /* we now need to calculate the expire data for the object. */ - if (expire == NULL && c->fp != NULL) { /* no expiry data sent in response */ + if (expire == NULL && c->fp != NULL) { /* no expiry data sent in + * response */ expire = ap_table_get(c->hdrs, "Expires"); if (expire != NULL) expc = ap_parseHTTPdate(expire); @@ -1463,18 +1505,18 @@ int ap_proxy_cache_update(cache_req *c, table *resp_hdrs, * else * expire date = now + defaultexpire */ - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Expiry date is %ld", (long)expc); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Expiry date is %ld", (long)expc); if (expc == BAD_DATE) { if (lmod != BAD_DATE) { - double x = (double) (date - lmod) * conf->cache.lmfactor; + double x = (double)(date - lmod) * conf->cache.lmfactor; double maxex = conf->cache.maxexpire; if (x > maxex) x = maxex; - expc = now + (int) x; + expc = now + (int)x; } else expc = now + conf->cache.defaultexpire; - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Expiry date calculated %ld", (long)expc); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Expiry date calculated %ld", (long)expc); } /* get the content-length header */ @@ -1486,21 +1528,21 @@ int ap_proxy_cache_update(cache_req *c, table *resp_hdrs, /* we have all the header information we need - write it to the cache file */ c->version++; - ap_proxy_sec2hex(date, buff + 17*(0)); - buff[17*(1)-1] = ' '; - ap_proxy_sec2hex(lmod, buff + 17*(1)); - buff[17*(2)-1] = ' '; - ap_proxy_sec2hex(expc, buff + 17*(2)); - buff[17*(3)-1] = ' '; - ap_proxy_sec2hex(c->version, buff + 17*(3)); - buff[17*(4)-1] = ' '; - ap_proxy_sec2hex(c->req_time, buff + 17*(4)); - buff[17*(5)-1] = ' '; - ap_proxy_sec2hex(c->resp_time, buff + 17*(5)); - buff[17*(6)-1] = ' '; - ap_proxy_sec2hex(c->len, buff + 17*(6)); - buff[17*(7)-1] = '\n'; - buff[17*(7)] = '\0'; + ap_proxy_sec2hex(date, buff + 17 * (0)); + buff[17 * (1) - 1] = ' '; + ap_proxy_sec2hex(lmod, buff + 17 * (1)); + buff[17 * (2) - 1] = ' '; + ap_proxy_sec2hex(expc, buff + 17 * (2)); + buff[17 * (3) - 1] = ' '; + ap_proxy_sec2hex(c->version, buff + 17 * (3)); + buff[17 * (4) - 1] = ' '; + ap_proxy_sec2hex(c->req_time, buff + 17 * (4)); + buff[17 * (5) - 1] = ' '; + ap_proxy_sec2hex(c->resp_time, buff + 17 * (5)); + buff[17 * (6) - 1] = ' '; + ap_proxy_sec2hex(c->len, buff + 17 * (6)); + buff[17 * (7) - 1] = '\n'; + buff[17 * (7)] = '\0'; /* Was the server response a 304 Not Modified? * @@ -1510,7 +1552,7 @@ int ap_proxy_cache_update(cache_req *c, table *resp_hdrs, */ /* if response from server 304 not modified */ - if (r->status == HTTP_NOT_MODIFIED) { + if (r->status == HTTP_NOT_MODIFIED) { /* Have the headers changed? * @@ -1518,107 +1560,107 @@ int ap_proxy_cache_update(cache_req *c, table *resp_hdrs, */ if (c->hdrs) { - if (!ap_proxy_table_replace(c->hdrs, resp_hdrs)) { - c->xcache = ap_pstrcat(r->pool, "HIT from ", ap_get_server_name(r), " (with revalidation)", NULL); - return ap_proxy_cache_conditional(r, c, c->fp); + if (!ap_proxy_table_replace(c->hdrs, resp_hdrs)) { + c->xcache = ap_pstrcat(r->pool, "HIT from ", ap_get_server_name(r), " (with revalidation)", NULL); + return ap_proxy_cache_conditional(r, c, c->fp); } } else - c->hdrs = resp_hdrs; + c->hdrs = resp_hdrs; /* if we get here - the headers have changed. Go through the motions * of creating a new temporary cache file below, we'll then serve * the request like we would have in ap_proxy_cache_conditional() * above, and at the same time we will also rewrite the contents * to the new temporary file. */ - } + } -/* +/* * Ok - lets prepare and open the cached file - * + * * If a cached file (in c->fp) is already open, then we want to * update that cached file. Copy the c->fp to c->origfp and open * up a new one. - * + * * If the cached file (in c->fp) is NULL, we must open a new cached * file from scratch. * * The new cache file will be moved to it's final location in the * directory tree later, overwriting the old cache file should it exist. - */ + */ /* if a cache file was already open */ if (c->fp != NULL) { - c->origfp = c->fp; + c->origfp = c->fp; } while (1) { /* create temporary filename */ #ifndef TPF #define TMPFILESTR "/tmpXXXXXX" - if (conf->cache.root == NULL) { - c = ap_proxy_cache_error(c); - break; - } - c->tempfile = ap_palloc(r->pool, strlen(conf->cache.root) + sizeof(TMPFILESTR)); - strcpy(c->tempfile, conf->cache.root); - strcat(c->tempfile, TMPFILESTR); + if (conf->cache.root == NULL) { + c = ap_proxy_cache_error(c); + break; + } + c->tempfile = ap_palloc(r->pool, strlen(conf->cache.root) + sizeof(TMPFILESTR)); + strcpy(c->tempfile, conf->cache.root); + strcat(c->tempfile, TMPFILESTR); #undef TMPFILESTR - p = mktemp(c->tempfile); + p = mktemp(c->tempfile); #else - if (conf->cache.root == NULL) { - c = ap_proxy_cache_error(c); - break; - } - c->tempfile = ap_palloc(r->pool, strlen(conf->cache.root) +1+ L_tmpnam); - strcpy(c->tempfile, conf->cache.root); - strcat(c->tempfile, "/"); - p = tmpnam(NULL); - strcat(c->tempfile, p); + if (conf->cache.root == NULL) { + c = ap_proxy_cache_error(c); + break; + } + c->tempfile = ap_palloc(r->pool, strlen(conf->cache.root) + 1 + L_tmpnam); + strcpy(c->tempfile, conf->cache.root); + strcat(c->tempfile, "/"); + p = tmpnam(NULL); + strcat(c->tempfile, p); #endif - if (p == NULL) { - c = ap_proxy_cache_error(c); - break; - } + if (p == NULL) { + c = ap_proxy_cache_error(c); + break; + } - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Create temporary file %s", c->tempfile); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Create temporary file %s", c->tempfile); /* create the new file */ - c->fp = ap_proxy_create_cachefile(r, c->tempfile); - if (NULL == c->fp) { - c = ap_proxy_cache_error(c); - break; - } + c->fp = ap_proxy_create_cachefile(r, c->tempfile); + if (NULL == c->fp) { + c = ap_proxy_cache_error(c); + break; + } /* write away the cache header and the URL */ - if (ap_bvputs(c->fp, buff, "X-URL: ", c->url, "\n", NULL) == -1) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "proxy: error writing cache file(%s)", c->tempfile); - c = ap_proxy_cache_error(c); - break; - } + if (ap_bvputs(c->fp, buff, "X-URL: ", c->url, "\n", NULL) == -1) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error writing cache file(%s)", c->tempfile); + c = ap_proxy_cache_error(c); + break; + } /* get original request headers */ - if (c->req_hdrs) - req_hdrs = ap_copy_table(r->pool, c->req_hdrs); - else - req_hdrs = ap_copy_table(r->pool, r->headers_in); + if (c->req_hdrs) + req_hdrs = ap_copy_table(r->pool, c->req_hdrs); + else + req_hdrs = ap_copy_table(r->pool, r->headers_in); /* remove hop-by-hop headers */ - ap_proxy_clear_connection(r->pool, req_hdrs); + ap_proxy_clear_connection(r->pool, req_hdrs); /* save original request headers */ - if (c->req_hdrs) + if (c->req_hdrs) ap_table_do(ap_proxy_send_hdr_line, c, c->req_hdrs, NULL); - else + else ap_table_do(ap_proxy_send_hdr_line, c, r->headers_in, NULL); - if (ap_bputs(CRLF, c->fp) == -1) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, - "proxy: error writing request headers terminating CRLF to %s", c->tempfile); - c = ap_proxy_cache_error(c); - break; - } - break; + if (ap_bputs(CRLF, c->fp) == -1) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, + "proxy: error writing request headers terminating CRLF to %s", c->tempfile); + c = ap_proxy_cache_error(c); + break; + } + break; } /* Was the server response a 304 Not Modified? @@ -1632,8 +1674,8 @@ int ap_proxy_cache_update(cache_req *c, table *resp_hdrs, if (r->status == HTTP_NOT_MODIFIED) { /* fulfil the request */ - c->xcache = ap_pstrcat(r->pool, "HIT from ", ap_get_server_name(r), " (with revalidation)", NULL); - return ap_proxy_cache_conditional(r, c, c->fp); + c->xcache = ap_pstrcat(r->pool, "HIT from ", ap_get_server_name(r), " (with revalidation)", NULL); + return ap_proxy_cache_conditional(r, c, c->fp); } return DECLINED; @@ -1677,10 +1719,10 @@ void ap_proxy_cache_tidy(cache_req *c) c->len = bc; ap_bflush(c->fp); ap_proxy_sec2hex(c->len, buff); - curpos = lseek(ap_bfileno(c->fp, B_WR), 17*6, SEEK_SET); + curpos = lseek(ap_bfileno(c->fp, B_WR), 17 * 6, SEEK_SET); if (curpos == -1) ap_log_error(APLOG_MARK, APLOG_ERR, s, - "proxy: error seeking on cache file %s", c->tempfile); + "proxy: error seeking on cache file %s", c->tempfile); else if (write(ap_bfileno(c->fp, B_WR), buff, sizeof(buff) - 1) == -1) ap_log_error(APLOG_MARK, APLOG_ERR, s, "proxy: error updating cache file %s", c->tempfile); @@ -1695,7 +1737,7 @@ void ap_proxy_cache_tidy(cache_req *c) return; } - if (ap_pclosef(c->req->pool, ap_bfileno(c->fp, B_WR)) == -1) { + if (ap_pclosef(c->req->pool, ap_bfileno(c->fp, B_WR))== -1) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "proxy: error closing cache file %s", c->tempfile); unlink(c->tempfile); @@ -1705,12 +1747,13 @@ void ap_proxy_cache_tidy(cache_req *c) if (unlink(c->filename) == -1 && errno != ENOENT) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "proxy: error deleting old cache file %s", - c->tempfile); + c->filename); + (void)unlink(c->tempfile); } else { char *p; proxy_server_conf *conf = - (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module); + (proxy_server_conf *)ap_get_module_config(s->module_config, &proxy_module); for (p = c->filename + strlen(conf->cache.root) + 1;;) { p = strchr(p, '/'); @@ -1720,10 +1763,10 @@ void ap_proxy_cache_tidy(cache_req *c) #if defined(WIN32) || defined(NETWARE) if (mkdir(c->filename) < 0 && errno != EEXIST) #elif defined(__TANDEM) - if (mkdir(c->filename, S_IRWXU | S_IRWXG | S_IRWXO) < 0 && errno != EEXIST) + 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 */ +#endif /* WIN32 */ ap_log_error(APLOG_MARK, APLOG_ERR, s, "proxy: error creating cache directory %s", c->filename); @@ -1732,22 +1775,21 @@ void ap_proxy_cache_tidy(cache_req *c) } #if defined(OS2) || defined(WIN32) || defined(NETWARE) || defined(MPE) /* Under OS/2 use rename. */ - if (rename(c->tempfile, c->filename) == -1) + if (rename(c->tempfile, c->filename) == -1) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "proxy: error renaming cache file %s to %s", c->tempfile, c->filename); - } + (void)unlink(c->tempfile); + } #else if (link(c->tempfile, c->filename) == -1) ap_log_error(APLOG_MARK, APLOG_ERR, s, "proxy: error linking cache file %s to %s", c->tempfile, c->filename); - } - - if (unlink(c->tempfile) == -1) - ap_log_error(APLOG_MARK, APLOG_ERR, s, - "proxy: error deleting temp file %s", c->tempfile); + if (unlink(c->tempfile) == -1) + ap_log_error(APLOG_MARK, APLOG_ERR, s, + "proxy: error deleting temp file %s", c->tempfile); #endif - + } } diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_connect.c b/usr.sbin/httpd/src/modules/proxy/proxy_connect.c index 4870e009088..9b955d51776 100644 --- a/usr.sbin/httpd/src/modules/proxy/proxy_connect.c +++ b/usr.sbin/httpd/src/modules/proxy/proxy_connect.c @@ -66,7 +66,7 @@ #include <bstring.h> /* for IRIX, FD_SET calls bzero() */ #endif -/* +/* * This handles Netscape CONNECT method secure proxy requests. * A connection is opened to the specified host and data is * passed through between the WWW site and the browser. @@ -75,8 +75,8 @@ * "Tunneling SSL Through a WWW Proxy" currently at * http://www.mcom.com/newsref/std/tunneling_ssl.html. * - * If proxyhost and proxyport are set, we send a CONNECT to - * the specified proxy.. + * If proxyhost and proxyport are set, we send a CONNECT to + * the specified proxy.. * * FIXME: this is bad, because it does its own socket I/O * instead of using the I/O in buff.c. However, @@ -96,14 +96,13 @@ * FIXME: no check for r->assbackwards, whatever that is. */ -static int -allowed_port(proxy_server_conf *conf, int port) +static int allowed_port(proxy_server_conf *conf, int port) { int i; - int *list = (int *) conf->allowed_connect_ports->elts; + int *list = (int *)conf->allowed_connect_ports->elts; - for(i = 0; i < conf->allowed_connect_ports->nelts; i++) { - if(port == list[i]) + for (i = 0; i < conf->allowed_connect_ports->nelts; i++) { + if (port == list[i]) return 1; } return 0; @@ -111,7 +110,7 @@ allowed_port(proxy_server_conf *conf, int port) int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url, - const char *proxyhost, int proxyport) + const char *proxyhost, int proxyport) { struct sockaddr_in server; struct in_addr destaddr; @@ -125,8 +124,8 @@ int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url, void *sconf = r->server->module_config; proxy_server_conf *conf = - (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); - struct noproxy_entry *npent = (struct noproxy_entry *)conf->noproxies->elts; + (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); + struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts; memset(&server, '\0', sizeof(server)); server.sin_family = AF_INET; @@ -156,22 +155,23 @@ int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url, if (conf->allowed_connect_ports->nelts == 0) { /* Default setting if not overridden by AllowCONNECT */ switch (port) { - case DEFAULT_HTTPS_PORT: - case DEFAULT_SNEWS_PORT: - break; - default: - return HTTP_FORBIDDEN; + case DEFAULT_HTTPS_PORT: + case DEFAULT_SNEWS_PORT: + break; + default: + return HTTP_FORBIDDEN; } - } else if(!allowed_port(conf, port)) + } + else if (!allowed_port(conf, port)) return HTTP_FORBIDDEN; if (proxyhost) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, - "CONNECT to remote proxy %s on port %d", proxyhost, proxyport); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "CONNECT to remote proxy %s on port %d", proxyhost, proxyport); } else { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, - "CONNECT to %s on port %d", host, port); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "CONNECT to %s on port %d", host, port); } /* Nasty cast to work around broken terniary expressions on MSVC */ @@ -180,7 +180,7 @@ int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url, if (err != NULL) return ap_proxyerror(r, - proxyhost ? HTTP_BAD_GATEWAY : HTTP_INTERNAL_SERVER_ERROR, err); + proxyhost ? HTTP_BAD_GATEWAY : HTTP_INTERNAL_SERVER_ERROR, err); sock = ap_psocket(r->pool, PF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == -1) { @@ -190,11 +190,11 @@ int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url, #ifdef CHECK_FD_SETSIZE if (sock >= FD_SETSIZE) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL, - "proxy_connect_handler: filedescriptor (%u) " - "larger than FD_SETSIZE (%u) " - "found, you probably need to rebuild Apache with a " - "larger FD_SETSIZE", sock, FD_SETSIZE); + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_WARNING, NULL, + "proxy_connect_handler: filedescriptor (%u) " + "larger than FD_SETSIZE (%u) " + "found, you probably need to rebuild Apache with a " + "larger FD_SETSIZE", sock, FD_SETSIZE); ap_pclosesocket(r->pool, sock); return HTTP_INTERNAL_SERVER_ERROR; } @@ -212,73 +212,76 @@ 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, HTTP_INTERNAL_SERVER_ERROR, ap_pstrcat(r->pool, - "Could not connect to remote machine:<br>", strerror(errno), NULL)); + "Could not connect to remote machine:<br>", strerror(errno), NULL)); } - /* If we are connecting through a remote proxy, we need to pass - * the CONNECT request on to it. + /* + * If we are connecting through a remote proxy, we need to pass the + * CONNECT request on to it. */ if (proxyport) { - /* FIXME: We should not be calling write() directly, but we currently - * have no alternative. Error checking ignored. Also, we force - * a HTTP/1.0 request to keep things simple. + /* + * FIXME: We should not be calling write() directly, but we currently + * have no alternative. Error checking ignored. Also, we force a + * HTTP/1.0 request to keep things simple. */ - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, - "Sending the CONNECT request to the remote proxy"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "Sending the CONNECT request to the remote proxy"); ap_snprintf(buffer, sizeof(buffer), "CONNECT %s HTTP/1.0" CRLF, r->uri); - send(sock, buffer, strlen(buffer),0); + send(sock, buffer, strlen(buffer), 0); ap_snprintf(buffer, sizeof(buffer), - "Proxy-agent: %s" CRLF CRLF, ap_get_server_version()); - send(sock, buffer, strlen(buffer),0); + "Proxy-agent: %s" CRLF CRLF, ap_get_server_version()); + send(sock, buffer, strlen(buffer), 0); } else { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, - "Returning 200 OK Status"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "Returning 200 OK Status"); ap_rvputs(r, "HTTP/1.0 200 Connection established" CRLF, NULL); ap_rvputs(r, "Proxy-agent: ", ap_get_server_version(), CRLF CRLF, NULL); ap_bflush(r->connection->client); } - while (1) { /* Infinite loop until error (one side closes the connection) */ + while (1) { /* Infinite loop until error (one side closes + * the connection) */ FD_ZERO(&fds); FD_SET(sock, &fds); FD_SET(ap_bfileno(r->connection->client, B_WR), &fds); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, - "Going to sleep (select)"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "Going to sleep (select)"); i = ap_select((ap_bfileno(r->connection->client, B_WR) > sock ? - ap_bfileno(r->connection->client, B_WR) + 1 : - sock + 1), &fds, NULL, NULL, NULL); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, - "Woke from select(), i=%d", i); + ap_bfileno(r->connection->client, B_WR) + 1 : + sock + 1), &fds, NULL, NULL, NULL); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "Woke from select(), i=%d", i); if (i) { if (FD_ISSET(sock, &fds)) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, - "sock was set"); - if ((nbytes = recv(sock, buffer, HUGE_STRING_LEN,0)) != 0) { + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "sock was set"); + if ((nbytes = recv(sock, buffer, HUGE_STRING_LEN, 0)) != 0) { if (nbytes == -1) break; if (send(ap_bfileno(r->connection->client, B_WR), buffer, - nbytes,0) == EOF) + nbytes, 0) == EOF) break; - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, - r->server, "Wrote %d bytes to client", nbytes); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, + r->server, "Wrote %d bytes to client", nbytes); } else break; } else if (FD_ISSET(ap_bfileno(r->connection->client, B_WR), &fds)) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, - "client->fd was set"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "client->fd was set"); if ((nbytes = recv(ap_bfileno(r->connection->client, B_WR), - buffer, HUGE_STRING_LEN, 0)) != 0) { + buffer, HUGE_STRING_LEN, 0)) != 0) { if (nbytes == -1) break; if (send(sock, buffer, nbytes, 0) == EOF) break; - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, - r->server, "Wrote %d bytes to server", nbytes); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, + r->server, "Wrote %d bytes to server", nbytes); } else break; diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c b/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c index 8f29738f8e2..076d23b00a7 100644 --- a/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c +++ b/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c @@ -73,7 +73,7 @@ static int decodeenc(char *x) int i, j, ch; if (x[0] == '\0') - return 0; /* special case for no characters */ + return 0; /* special case for no characters */ for (i = 0, j = 0; x[i] != '\0'; i++, j++) { /* decode it if not already done */ ch = x[i]; @@ -173,10 +173,10 @@ int ap_proxy_ftp_canon(request_rec *r, char *url) sport[0] = '\0'; r->filename = ap_pstrcat(p, "proxy:ftp://", (user != NULL) ? user : "", - (password != NULL) ? ":" : "", - (password != NULL) ? password : "", + (password != NULL) ? ":" : "", + (password != NULL) ? password : "", (user != NULL) ? "@" : "", host, sport, "/", path, - (parms[0] != '\0') ? ";" : "", parms, NULL); + (parms[0] != '\0') ? ";" : "", parms, NULL); return OK; } @@ -195,7 +195,7 @@ static int ftp_getrc(BUFF *ctrl) return -1; /* check format */ if (len < 5 || !ap_isdigit(linebuff[0]) || !ap_isdigit(linebuff[1]) || - !ap_isdigit(linebuff[2]) || (linebuff[3] != ' ' && linebuff[3] != '-')) + !ap_isdigit(linebuff[2]) || (linebuff[3] != ' ' && linebuff[3] != '-')) status = 0; else status = 100 * linebuff[0] + 10 * linebuff[1] + linebuff[2] - 111 * '0'; @@ -222,26 +222,25 @@ static int ftp_getrc(BUFF *ctrl) } /* - * Like ftp_getrc but returns both the ftp status code and + * Like ftp_getrc but returns both the ftp status code and * remembers the response message in the supplied buffer */ static int ftp_getrc_msg(BUFF *ctrl, char *msgbuf, int msglen) { int len, status; char linebuff[100], buff[5]; - char *mb = msgbuf, - *me = &msgbuf[msglen]; + char *mb = msgbuf, *me = &msgbuf[msglen]; len = ap_bgets(linebuff, sizeof linebuff, ctrl); if (len == -1) return -1; if (len < 5 || !ap_isdigit(linebuff[0]) || !ap_isdigit(linebuff[1]) || - !ap_isdigit(linebuff[2]) || (linebuff[3] != ' ' && linebuff[3] != '-')) + !ap_isdigit(linebuff[2]) || (linebuff[3] != ' ' && linebuff[3] != '-')) status = 0; else status = 100 * linebuff[0] + 10 * linebuff[1] + linebuff[2] - 111 * '0'; - mb = ap_cpystrn(mb, linebuff+4, me - mb); + mb = ap_cpystrn(mb, linebuff + 4, me - mb); if (linebuff[len - 1] != '\n') (void)ap_bskiplf(ctrl); @@ -256,7 +255,7 @@ static int ftp_getrc_msg(BUFF *ctrl, char *msgbuf, int msglen) if (linebuff[len - 1] != '\n') { (void)ap_bskiplf(ctrl); } - mb = ap_cpystrn(mb, linebuff+4, me - mb); + mb = ap_cpystrn(mb, linebuff + 4, me - mb); } while (memcmp(linebuff, buff, 4) != 0); } return status; @@ -275,7 +274,8 @@ static long int send_dir(BUFF *data, request_rec *r, cache_req *c, char *cwd) conn_rec *con = r->connection; pool *p = r->pool; char *dir, *path, *reldir, *site, *type = NULL; - char *basedir = ""; /* By default, path is relative to the $HOME dir */ + char *basedir = ""; /* By default, path is relative to the $HOME + * dir */ /* create default sized buffers for the stuff below */ buf_size = IOBUFSIZE; @@ -283,9 +283,9 @@ static long int send_dir(BUFF *data, request_rec *r, cache_req *c, char *cwd) buf2 = ap_palloc(r->pool, buf_size); /* Save "scheme://site" prefix without password */ - site = ap_unparse_uri_components(p, &r->parsed_uri, UNP_OMITPASSWORD|UNP_OMITPATHINFO); + site = ap_unparse_uri_components(p, &r->parsed_uri, UNP_OMITPASSWORD | UNP_OMITPATHINFO); /* ... and path without query args */ - path = ap_unparse_uri_components(p, &r->parsed_uri, UNP_OMITSITEPART|UNP_OMITQUERY); + path = ap_unparse_uri_components(p, &r->parsed_uri, UNP_OMITSITEPART | UNP_OMITQUERY); /* If path began with /%2f, change the basedir */ if (strncasecmp(path, "/%2f", 4) == 0) { @@ -298,24 +298,24 @@ static long int send_dir(BUFF *data, request_rec *r, cache_req *c, char *cwd) (void)decodeenc(path); - while (path[1] == '/') /* collapse multiple leading slashes to one */ + while (path[1] == '/') /* collapse multiple leading slashes to one */ ++path; /* Copy path, strip (all except the last) trailing slashes */ /* (the trailing slash is needed for the dir component loop below) */ path = dir = ap_pstrcat(r->pool, path, "/", NULL); - for (n = strlen(path); n > 1 && path[n-1] == '/' && path[n-2] == '/'; --n) - path[n-1] = '\0'; + for (n = strlen(path); n > 1 && path[n - 1] == '/' && path[n - 2] == '/'; --n) + path[n - 1] = '\0'; /* print "ftp://host/" */ n = ap_snprintf(buf, buf_size, DOCTYPE_HTML_3_2 - "<html><head><title>%s%s%s</title>\n" - "<base href=\"%s%s%s\"></head>\n" - "<body><h2>Directory of " - "<a href=\"/\">%s</a>/", - site, basedir, ap_escape_html(p,path), - site, basedir, ap_escape_uri(p,path), - site); + "<html><head><title>%s%s%s</title>\n" + "<base href=\"%s%s%s\"></head>\n" + "<body><h2>Directory of " + "<a href=\"/\">%s</a>/", + site, basedir, ap_escape_html(p, path), + site, basedir, ap_escape_uri(p, path), + site); total_bytes_sent += ap_proxy_bputs2(buf, con->client, c); /* Add a link to the root directory (if %2f hack was used) */ @@ -323,11 +323,10 @@ static long int send_dir(BUFF *data, request_rec *r, cache_req *c, char *cwd) total_bytes_sent += ap_proxy_bputs2("<a href=\"/%2f/\">%2f</a>/", con->client, c); } - for (dir = path+1; (dir = strchr(dir, '/')) != NULL; ) - { + for (dir = path + 1; (dir = strchr(dir, '/')) != NULL;) { *dir = '\0'; - if ((reldir = strrchr(path+1, '/'))==NULL) { - reldir = path+1; + if ((reldir = strrchr(path + 1, '/')) == NULL) { + reldir = path + 1; } else ++reldir; @@ -339,14 +338,15 @@ static long int send_dir(BUFF *data, request_rec *r, cache_req *c, char *cwd) total_bytes_sent += ap_proxy_bputs2(buf, con->client, c); *dir = '/'; while (*dir == '/') - ++dir; + ++dir; } /* If the caller has determined the current directory, and it differs */ /* from what the client requested, then show the real name */ - if (cwd == NULL || strncmp (cwd, path, strlen(cwd)) == 0) { + if (cwd == NULL || strncmp(cwd, path, strlen(cwd)) == 0) { ap_snprintf(buf, buf_size, "</h2>\n<hr /><pre>"); - } else { + } + else { ap_snprintf(buf, buf_size, "</h2>\n(%s)\n<hr /><pre>", ap_escape_html(p, cwd)); } @@ -357,21 +357,21 @@ static long int send_dir(BUFF *data, request_rec *r, cache_req *c, char *cwd) if (n == -1) { /* input error */ if (c != NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, - "proxy: error reading from %s", c->url); + "proxy: error reading from %s", c->url); c = ap_proxy_cache_error(c); } break; } if (n == 0) - break; /* EOF */ + break; /* EOF */ - if (buf[n-1] == '\n') /* strip trailing '\n' */ + if (buf[n - 1] == '\n') /* strip trailing '\n' */ buf[--n] = '\0'; - if (buf[n-1] == '\r') /* strip trailing '\r' if present */ + if (buf[n - 1] == '\r') /* strip trailing '\r' if present */ buf[--n] = '\0'; /* Handle unix-style symbolic link */ - if (buf[0] == 'l' && (filename=strstr(buf, " -> ")) != NULL) { + if (buf[0] == 'l' && (filename = strstr(buf, " -> ")) != NULL) { char *link_ptr = filename; do { @@ -382,7 +382,7 @@ static long int send_dir(BUFF *data, request_rec *r, cache_req *c, char *cwd) *(link_ptr++) = '\0'; ap_snprintf(buf2, buf_size, "%s <a href=\"%s\">%s %s</a>\n", ap_escape_html(p, buf), - ap_escape_uri(p,filename), + ap_escape_uri(p, filename), ap_escape_html(p, filename), ap_escape_html(p, link_ptr)); ap_cpystrn(buf, buf2, buf_size); @@ -416,13 +416,13 @@ static long int send_dir(BUFF *data, request_rec *r, cache_req *c, char *cwd) /* Special handling for '.' and '..': append slash to link */ if (!strcmp(filename, ".") || !strcmp(filename, "..") || buf[0] == 'd') { ap_snprintf(buf2, buf_size, "%s <a href=\"%s/\">%s</a>\n", - ap_escape_html(p, buf), ap_escape_uri(p,filename), + ap_escape_html(p, buf), ap_escape_uri(p, filename), ap_escape_html(p, filename)); } else { ap_snprintf(buf2, buf_size, "%s <a href=\"%s\">%s</a>\n", ap_escape_html(p, buf), - ap_escape_uri(p,filename), + ap_escape_uri(p, filename), ap_escape_html(p, filename)); } ap_cpystrn(buf, buf2, buf_size); @@ -430,13 +430,13 @@ static long int send_dir(BUFF *data, request_rec *r, cache_req *c, char *cwd) } /* else??? What about other OS's output formats? */ else { - strcat(buf, "\n"); /* re-append the newline char */ + strcat(buf, "\n"); /* re-append the newline char */ ap_cpystrn(buf, ap_escape_html(p, buf), buf_size); } total_bytes_sent += ap_proxy_bputs2(buf, con->client, c); - ap_reset_timeout(r); /* reset timeout after successfule write */ + ap_reset_timeout(r); /* reset timeout after successfule write */ } total_bytes_sent += ap_proxy_bputs2("</pre><hr />\n", con->client, c); @@ -457,23 +457,24 @@ static long int send_dir(BUFF *data, request_rec *r, cache_req *c, char *cwd) * Note that we "invent" a realm name which consists of the * ftp://user@host part of the reqest (sans password -if supplied but invalid-) */ -static int ftp_unauthorized (request_rec *r, int log_it) +static int ftp_unauthorized(request_rec *r, int log_it) { r->proxyreq = NOT_PROXY; - /* Log failed requests if they supplied a password - * (log username/password guessing attempts) + /* + * Log failed requests if they supplied a password (log username/password + * guessing attempts) */ if (log_it) - ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, r, + ap_log_rerror(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, r, "proxy: missing or failed auth to %s", ap_unparse_uri_components(r->pool, - &r->parsed_uri, UNP_OMITPATHINFO)); + &r->parsed_uri, UNP_OMITPATHINFO)); ap_table_setn(r->err_headers_out, "WWW-Authenticate", ap_pstrcat(r->pool, "Basic realm=\"", - ap_unparse_uri_components(r->pool, &r->parsed_uri, - UNP_OMITPASSWORD|UNP_OMITPATHINFO), - "\"", NULL)); + ap_unparse_uri_components(r->pool, &r->parsed_uri, + UNP_OMITPASSWORD | UNP_OMITPATHINFO), + "\"", NULL)); return HTTP_UNAUTHORIZED; } @@ -481,7 +482,7 @@ static int ftp_unauthorized (request_rec *r, int log_it) /* Set ftp server to TYPE {A,I,E} before transfer of a directory or file */ static int ftp_set_TYPE(request_rec *r, BUFF *ctrl, char xfer_type) { - static char old_type[2] = { 'A', '\0' }; /* After logon, mode is ASCII */ + static char old_type[2] = {'A', '\0'}; /* After logon, mode is ASCII */ int ret = HTTP_OK; int rc; @@ -492,7 +493,7 @@ static int ftp_set_TYPE(request_rec *r, BUFF *ctrl, char xfer_type) old_type[0] = xfer_type; ap_bvputs(ctrl, "TYPE ", old_type, CRLF, NULL); ap_bflush(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: TYPE %s", old_type); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: TYPE %s", old_type); /* responses: 200, 421, 500, 501, 504, 530 */ /* 200 Command okay. */ @@ -502,37 +503,36 @@ static int ftp_set_TYPE(request_rec *r, BUFF *ctrl, char xfer_type) /* 504 Command not implemented for that parameter. */ /* 530 Not logged in. */ rc = ftp_getrc(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: returned status %d", rc); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", rc); if (rc == -1 || rc == 421) { ap_kill_timeout(r); ret = ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server"); + "Error reading from remote server"); } else if (rc != 200 && rc != 504) { ap_kill_timeout(r); ret = ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Unable to set transfer type"); + "Unable to set transfer type"); } /* Allow not implemented */ else if (rc == 504) - /* ignore it silently */; + /* ignore it silently */ ; return ret; } /* Common cleanup routine: close open BUFFers or sockets, and return an error */ -static int -ftp_cleanup_and_return(request_rec *r, BUFF *ctrl, BUFF *data, int csock, int dsock, int rc) +static int ftp_cleanup_and_return(request_rec *r, BUFF *ctrl, BUFF *data, int csock, int dsock, int rc) { if (ctrl != NULL) - ap_bclose(ctrl); + ap_bclose(ctrl); else if (csock != -1) - ap_pclosesocket(r->pool, csock); + ap_pclosesocket(r->pool, csock); if (data != NULL) - ap_bclose(data); + ap_bclose(data); else if (dsock != -1) - ap_pclosesocket(r->pool, dsock); + ap_pclosesocket(r->pool, dsock); ap_kill_timeout(r); @@ -564,12 +564,12 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) pool *p = r->pool; int one = 1; NET_SIZE_T clen; - char xfer_type = 'A'; /* after ftp login, the default is ASCII */ + char xfer_type = 'A'; /* after ftp login, the default is ASCII */ int get_dirlisting = 0; void *sconf = r->server->module_config; proxy_server_conf *conf = - (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts; struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts; @@ -595,8 +595,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) host = r->parsed_uri.hostname; port = (r->parsed_uri.port != 0) - ? r->parsed_uri.port - : ap_default_port_for_request(r); + ? r->parsed_uri.port + : ap_default_port_for_request(r); path = ap_pstrdup(p, r->parsed_uri.path); if (path == NULL) path = ""; @@ -604,25 +604,27 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) while (*path == '/') ++path; - /* The "Authorization:" header must be checked first. - * We allow the user to "override" the URL-coded user [ & password ] - * in the Browsers' User&Password Dialog. - * NOTE that this is only marginally more secure than having the - * password travel in plain as part of the URL, because Basic Auth - * simply uuencodes the plain text password. - * But chances are still smaller that the URL is logged regularly. + /* + * The "Authorization:" header must be checked first. We allow the user + * to "override" the URL-coded user [ & password ] in the Browsers' + * User&Password Dialog. NOTE that this is only marginally more secure + * than having the password travel in plain as part of the URL, because + * Basic Auth simply uuencodes the plain text password. But chances are + * still smaller that the URL is logged regularly. */ if ((password = ap_table_get(r->headers_in, "Authorization")) != NULL && strcasecmp(ap_getword(r->pool, &password, ' '), "Basic") == 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. + /* + * 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. */ - user = ap_getword_nulls (r->connection->pool, &password, ':'); + user = ap_getword_nulls(r->connection->pool, &password, ':'); r->connection->ap_auth_type = "Basic"; r->connection->user = r->parsed_uri.user = user; - nocache = 1; /* This resource only accessible with username/password */ + nocache = 1; /* This resource only accessible with + * username/password */ } else if ((user = r->parsed_uri.user) != NULL) { user = ap_pstrdup(p, user); @@ -632,7 +634,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) decodeenc(tmp); password = tmp; } - nocache = 1; /* This resource only accessible with username/password */ + nocache = 1; /* This resource only accessible with + * username/password */ } else { user = "anonymous"; @@ -644,12 +647,12 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) for (i = 0; i < conf->noproxies->nelts; i++) { if (destaddr.s_addr == npent[i].addr.s_addr || (npent[i].name != NULL && - (npent[i].name[0] == '*' || strstr(host, npent[i].name) != NULL))) + (npent[i].name[0] == '*' || strstr(host, npent[i].name) != NULL))) return ap_proxyerror(r, HTTP_FORBIDDEN, "Connect to remote machine blocked"); } - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: connect to %s:%d", host, port); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: connect to %s:%d", host, port); parms = strchr(path, ';'); if (parms != NULL) @@ -665,33 +668,33 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "proxy: error creating socket"); + "proxy: error creating socket"); return HTTP_INTERNAL_SERVER_ERROR; } #if !defined(TPF) && !defined(BEOS) if (conf->recv_buffer_size > 0 && setsockopt(sock, SOL_SOCKET, SO_RCVBUF, - (const char *) &conf->recv_buffer_size, sizeof(int)) - == -1) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); + (const char *)&conf->recv_buffer_size, sizeof(int)) + == -1) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); } #endif - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &one, + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)) == -1) { -#ifndef _OSD_POSIX /* BS2000 has this option "always on" */ +#ifndef _OSD_POSIX /* BS2000 has this option "always on" */ ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "proxy: error setting reuseaddr option: setsockopt(SO_REUSEADDR)"); + "proxy: error setting reuseaddr option: setsockopt(SO_REUSEADDR)"); ap_pclosesocket(p, sock); return HTTP_INTERNAL_SERVER_ERROR; -#endif /*_OSD_POSIX*/ +#endif /* _OSD_POSIX */ } #ifdef SINIX_D_RESOLVER_BUG { - struct in_addr *ip_addr = (struct in_addr *) *server_hp.h_addr_list; + struct in_addr *ip_addr = (struct in_addr *)*server_hp.h_addr_list; for (; ip_addr->s_addr != 0; ++ip_addr) { memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr)); @@ -715,7 +718,7 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool, "Could not connect to remote machine: ", - strerror(errno), NULL))); + strerror(errno), NULL))); } /* record request_time for HTTP/1.1 age calculation */ @@ -726,8 +729,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) /* shouldn't we implement telnet control options here? */ #ifdef CHARSET_EBCDIC - ap_bsetflag(ctrl, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 1); -#endif /*CHARSET_EBCDIC*/ + ap_bsetflag(ctrl, B_ASCII2EBCDIC | B_EBCDIC2ASCII, 1); +#endif /* CHARSET_EBCDIC */ /* possible results: */ /* 120 Service ready in nnn minutes. */ @@ -735,39 +738,40 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) /* 421 Service not available, closing control connection. */ ap_hard_timeout("proxy ftp", r); i = ftp_getrc_msg(ctrl, resp, sizeof resp); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: returned status %d", i); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i); if (i == -1 || i == 421) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server")); + ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server")); } #if 0 if (i == 120) { - /* RFC2068 states: - * 14.38 Retry-After + /* + * RFC2068 states: 14.38 Retry-After * - * The Retry-After response-header field can be used with a 503 (Service - * Unavailable) response to indicate how long the service is expected to - * be unavailable to the requesting client. The value of this field can - * be either an HTTP-date or an integer number of seconds (in decimal) - * after the time of the response. - * Retry-After = "Retry-After" ":" ( HTTP-date | delta-seconds ) + * The Retry-After response-header field can be used with a 503 (Service + * Unavailable) response to indicate how long the service is expected + * to be unavailable to the requesting client. The value of this + * field can be either an HTTP-date or an integer number of seconds + * (in decimal) after the time of the response. Retry-After = + * "Retry-After" ":" ( HTTP-date | delta-seconds ) */ - ap_set_header("Retry-After", ap_psprintf(p, "%u", 60*wait_mins); +/**INDENT** Error@756: Unbalanced parens */ + ap_set_header("Retry-After", ap_psprintf(p, "%u", 60 * wait_mins); return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_SERVICE_UNAVAILABLE, resp)); + ap_proxyerror(r, HTTP_SERVICE_UNAVAILABLE, resp)); } #endif if (i != 220) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_GATEWAY, resp)); + ap_proxyerror(r, HTTP_BAD_GATEWAY, resp)); } - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: connected."); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: connected."); ap_bvputs(ctrl, "USER ", user, CRLF, NULL); - ap_bflush(ctrl); /* capture any errors */ - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: USER %s", user); + ap_bflush(ctrl); /* capture any errors */ + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: USER %s", user); /* possible results; 230, 331, 332, 421, 500, 501, 530 */ /* states: 1 - error, 2 - success; 3 - send password, 4,5 fail */ @@ -776,19 +780,19 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) /* 332 Need account for login. */ /* 421 Service not available, closing control connection. */ /* 500 Syntax error, command unrecognized. */ - /* (This may include errors such as command line too long.) */ + /* (This may include errors such as command line too long.) */ /* 501 Syntax error in parameters or arguments. */ /* 530 Not logged in. */ i = ftp_getrc(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: returned status %d", i); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i); if (i == -1 || i == 421) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server")); + ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server")); } if (i == 530) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ftp_unauthorized (r, 1)); + ftp_unauthorized(r, 1)); } if (i != 230 && i != 331) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, @@ -798,50 +802,51 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) if (i == 331) { /* send password */ if (password == NULL) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ftp_unauthorized (r, 0)); + ftp_unauthorized(r, 0)); } ap_bvputs(ctrl, "PASS ", password, CRLF, NULL); ap_bflush(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: PASS %s", password); - /* possible results 202, 230, 332, 421, 500, 501, 503, 530 */ - /* 230 User logged in, proceed. */ - /* 332 Need account for login. */ - /* 421 Service not available, closing control connection. */ - /* 500 Syntax error, command unrecognized. */ - /* 501 Syntax error in parameters or arguments. */ - /* 503 Bad sequence of commands. */ - /* 530 Not logged in. */ + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PASS %s", password); + /* possible results 202, 230, 332, 421, 500, 501, 503, 530 */ + /* 230 User logged in, proceed. */ + /* 332 Need account for login. */ + /* 421 Service not available, closing control connection. */ + /* 500 Syntax error, command unrecognized. */ + /* 501 Syntax error in parameters or arguments. */ + /* 503 Bad sequence of commands. */ + /* 530 Not logged in. */ i = ftp_getrc(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: returned status %d", i); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i); if (i == -1 || i == 421) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server")); + ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server")); } if (i == 332) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_UNAUTHORIZED, - "Need account for login")); + ap_proxyerror(r, HTTP_UNAUTHORIZED, + "Need account for login")); } /* @@@ questionable -- we might as well return a 403 Forbidden here */ - if (i == 530) /* log it: passwd guessing attempt? */ + if (i == 530) /* log it: passwd guessing attempt? */ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ftp_unauthorized (r, 1)); + ftp_unauthorized(r, 1)); if (i != 230 && i != 202) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, HTTP_BAD_GATEWAY); } - /* Special handling for leading "%2f": this enforces a "cwd /" - * out of the $HOME directory which was the starting point after login + /* + * Special handling for leading "%2f": this enforces a "cwd /" out of the + * $HOME directory which was the starting point after login */ if (strncasecmp(path, "%2f", 3) == 0) { path += 3; - while (*path == '/') /* skip leading '/' (after root %2f) */ + while (*path == '/') /* skip leading '/' (after root %2f) */ ++path; ap_bputs("CWD /" CRLF, ctrl); ap_bflush(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: CWD /"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: CWD /"); /* possible results: 250, 421, 500, 501, 502, 530, 550 */ /* 250 Requested file action okay, completed. */ @@ -852,11 +857,11 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) /* 530 Not logged in. */ /* 550 Requested action not taken. */ i = ftp_getrc(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: returned status %d", i); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i); if (i == -1 || i == 421) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server")); + ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server")); else if (i == 550) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, HTTP_NOT_FOUND); @@ -869,7 +874,7 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) * this is what we must do if we don't know the OS type of the remote * machine */ - for ( ; (strp = strchr(path, '/')) != NULL ; path = strp + 1) { + for (; (strp = strchr(path, '/')) != NULL; path = strp + 1) { char *slash = strp; *slash = '\0'; @@ -880,38 +885,38 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) if (strp[1] == '\0') break; - len = decodeenc(path); /* Note! This decodes a %2f -> "/" */ - if (strchr(path, '/')) /* were there any '/' characters? */ + len = decodeenc(path); /* Note! This decodes a %2f -> "/" */ + if (strchr(path, '/')) /* were there any '/' characters? */ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_REQUEST, - "Use of %2F is only allowed at the base directory")); + ap_proxyerror(r, HTTP_BAD_REQUEST, + "Use of %2F is only allowed at the base directory")); ap_bvputs(ctrl, "CWD ", path, CRLF, NULL); ap_bflush(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: CWD %s", path); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: CWD %s", path); *slash = '/'; /* responses: 250, 421, 500, 501, 502, 530, 550 */ - /* 250 Requested file action okay, completed. */ - /* 421 Service not available, closing control connection. */ - /* 500 Syntax error, command unrecognized. */ - /* 501 Syntax error in parameters or arguments. */ - /* 502 Command not implemented. */ - /* 530 Not logged in. */ - /* 550 Requested action not taken. */ + /* 250 Requested file action okay, completed. */ + /* 421 Service not available, closing control connection. */ + /* 500 Syntax error, command unrecognized. */ + /* 501 Syntax error in parameters or arguments. */ + /* 502 Command not implemented. */ + /* 530 Not logged in. */ + /* 550 Requested action not taken. */ i = ftp_getrc(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: returned status %d", i); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i); if (i == -1 || i == 421) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server")); + ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server")); if (i == 550) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, HTTP_NOT_FOUND); if (i == 500 || i == 501) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_REQUEST, - "Syntax error in filename (reported by ftp server)")); + ap_proxyerror(r, HTTP_BAD_REQUEST, + "Syntax error in filename (reported by ftp server)")); if (i != 250) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, HTTP_BAD_GATEWAY); @@ -919,18 +924,19 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) if (parms != NULL && strncmp(parms, "type=", 5) == 0 && ap_isalpha(parms[5])) { - /* "type=d" forces a dir listing. - * The other types (i|a|e) are directly used for the ftp TYPE command + /* + * "type=d" forces a dir listing. The other types (i|a|e) are + * directly used for the ftp TYPE command */ - if ( ! (get_dirlisting = (parms[5] == 'd'))) + if (!(get_dirlisting = (parms[5] == 'd'))) xfer_type = ap_toupper(parms[5]); /* Check valid types, rather than ignoring invalid types silently: */ if (strchr("AEI", xfer_type) == NULL) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, ap_proxyerror(r, HTTP_BAD_REQUEST, ap_pstrcat(r->pool, - "ftp proxy supports only types 'a', 'i', or 'e': \"", - parms, "\" is invalid.", NULL))); + "ftp proxy supports only types 'a', 'i', or 'e': \"", + parms, "\" is invalid.", NULL))); } else { /* make binary transfers the default */ @@ -941,23 +947,23 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); if (dsock == -1) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, - "proxy: error creating PASV socket")); + ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, + "proxy: error creating PASV socket")); } #if !defined (TPF) && !defined(BEOS) if (conf->recv_buffer_size) { if (setsockopt(dsock, SOL_SOCKET, SO_RCVBUF, - (const char *) &conf->recv_buffer_size, sizeof(int)) == -1) { + (const char *)&conf->recv_buffer_size, sizeof(int)) == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); + "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); } } #endif ap_bputs("PASV" CRLF, ctrl); ap_bflush(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: PASV command issued"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PASV command issued"); /* possible results: 227, 421, 500, 501, 502, 530 */ /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */ /* 421 Service not available, closing control connection. */ @@ -969,19 +975,19 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) i = ap_bgets(pasv, sizeof(pasv), ctrl); if (i == -1 || i == 421) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, - "proxy: PASV: control connection is toast")); + ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, + "proxy: PASV: control connection is toast")); } else { pasv[i - 1] = '\0'; - pstr = strtok(pasv, " "); /* separate result code */ + pstr = strtok(pasv, " "); /* separate result code */ if (pstr != NULL) { presult = atoi(pstr); if (*(pstr + strlen(pstr) + 1) == '=') pstr += strlen(pstr) + 2; - else - { - pstr = strtok(NULL, "("); /* separate address & port params */ + else { + pstr = strtok(NULL, "("); /* separate address & port + * params */ if (pstr != NULL) pstr = strtok(NULL, ")"); } @@ -989,15 +995,15 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) else presult = atoi(pasv); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: returned status %d", presult); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", presult); if (presult == 227 && pstr != NULL && (sscanf(pstr, "%d,%d,%d,%d,%d,%d", &h3, &h2, &h1, &h0, &p1, &p0) == 6)) { /* pardon the parens, but it makes gcc happy */ paddr = (((((h3 << 8) + h2) << 8) + h1) << 8) + h0; pport = (p1 << 8) + p0; - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: contacting host %d.%d.%d.%d:%d", - h3, h2, h1, h0, pport); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: contacting host %d.%d.%d.%d:%d", + h3, h2, h1, h0, pport); data_addr.sin_family = AF_INET; data_addr.sin_addr.s_addr = htonl(paddr); data_addr.sin_port = htons(pport); @@ -1005,10 +1011,10 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) if (i == -1) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_GATEWAY, - ap_pstrcat(r->pool, - "Could not connect to remote machine: ", - strerror(errno), NULL))); + ap_proxyerror(r, HTTP_BAD_GATEWAY, + ap_pstrcat(r->pool, + "Could not connect to remote machine: ", + strerror(errno), NULL))); } pasvmode = 1; } @@ -1020,45 +1026,45 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) if (!pasvmode) { /* set up data connection */ clen = sizeof(struct sockaddr_in); - if (getsockname(sock, (struct sockaddr *) &server, &clen) < 0) { + if (getsockname(sock, (struct sockaddr *)&server, &clen) < 0) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, + ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, "proxy: error getting socket address")); } dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); if (dsock == -1) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, - "proxy: error creating socket")); + ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, + "proxy: error creating socket")); } - if (setsockopt(dsock, SOL_SOCKET, SO_REUSEADDR, (void *) &one, + if (setsockopt(dsock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)) == -1) { -#ifndef _OSD_POSIX /* BS2000 has this option "always on" */ +#ifndef _OSD_POSIX /* BS2000 has this option "always on" */ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, - "proxy: error setting reuseaddr option")); -#endif /*_OSD_POSIX*/ + ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, + "proxy: error setting reuseaddr option")); +#endif /* _OSD_POSIX */ } - if (bind(dsock, (struct sockaddr *) &server, + if (bind(dsock, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, - ap_psprintf(p, "proxy: error binding to ftp data socket %s:%d", - inet_ntoa(server.sin_addr), server.sin_port))); + ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, + ap_psprintf(p, "proxy: error binding to ftp data socket %s:%d", + inet_ntoa(server.sin_addr), server.sin_port))); } - listen(dsock, 2); /* only need a short queue */ + listen(dsock, 2); /* only need a short queue */ } /* set request; "path" holds last path component */ len = decodeenc(path); - if (strchr(path, '/')) /* were there any '/' characters? */ + if (strchr(path, '/')) /* were there any '/' characters? */ return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_REQUEST, - "Use of %2F is only allowed at the base directory")); + ap_proxyerror(r, HTTP_BAD_REQUEST, + "Use of %2F is only allowed at the base directory")); /* TM - if len == 0 then it must be a directory (you can't RETR nothing) */ @@ -1068,16 +1074,16 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) else { ap_bvputs(ctrl, "SIZE ", path, CRLF, NULL); ap_bflush(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: SIZE %s", path); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: SIZE %s", path); i = ftp_getrc_msg(ctrl, resp, sizeof resp); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: returned status %d with response %s", i, resp); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d with response %s", i, resp); if (i != 500) { /* Size command not recognized */ if (i == 550) { /* Not a regular file */ - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: SIZE shows this is a directory"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: SIZE shows this is a directory"); get_dirlisting = 1; ap_bvputs(ctrl, "CWD ", path, CRLF, NULL); ap_bflush(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: CWD %s", path); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: CWD %s", path); /* possible results: 250, 421, 500, 501, 502, 530, 550 */ /* 250 Requested file action okay, completed. */ @@ -1088,11 +1094,11 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) /* 530 Not logged in. */ /* 550 Requested action not taken. */ i = ftp_getrc(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: returned status %d", i); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i); if (i == -1 || i == 421) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server")); + ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server")); if (i == 550) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, HTTP_NOT_FOUND); @@ -1102,9 +1108,8 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) path = ""; len = 0; } - else if (i == 213) { /* Size command ok */ - for (j = 0; j < sizeof resp && ap_isdigit(resp[j]); j++) - ; + else if (i == 213) {/* Size command ok */ + for (j = 0; j < sizeof resp && ap_isdigit(resp[j]); j++); resp[j] = '\0'; if (resp[0] != '\0') size = ap_pstrdup(p, resp); @@ -1115,7 +1120,7 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) #ifdef AUTODETECT_PWD ap_bvputs(ctrl, "PWD", CRLF, NULL); ap_bflush(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: PWD"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PWD"); /* responses: 257, 500, 501, 502, 421, 550 */ /* 257 "<directory-name>" <commentary> */ /* 421 Service not available, closing control connection. */ @@ -1124,11 +1129,11 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) /* 502 Command not implemented. */ /* 550 Requested action not taken. */ i = ftp_getrc_msg(ctrl, resp, sizeof resp); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: PWD returned status %d", i); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PWD returned status %d", i); if (i == -1 || i == 421) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server")); + ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server")); if (i == 550) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, HTTP_NOT_FOUND); @@ -1136,19 +1141,19 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) const char *dirp = resp; cwd = ap_getword_conf(r->pool, &dirp); } -#endif /*AUTODETECT_PWD*/ +#endif /* AUTODETECT_PWD */ if (get_dirlisting) { if (len != 0) ap_bvputs(ctrl, "LIST ", path, CRLF, NULL); else ap_bputs("LIST -lag" CRLF, ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: LIST %s", (len == 0 ? "" : path)); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: LIST %s", (len == 0 ? "" : path)); } else { ftp_set_TYPE(r, ctrl, xfer_type); ap_bvputs(ctrl, "RETR ", path, CRLF, NULL); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: RETR %s", path); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: RETR %s", path); } ap_bflush(ctrl); /* RETR: 110, 125, 150, 226, 250, 421, 425, 426, 450, 451, 500, 501, 530, 550 @@ -1168,19 +1173,20 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) /* 530 Not logged in. */ /* 550 Requested action not taken. */ rc = ftp_getrc(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: returned status %d", rc); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", rc); if (rc == -1 || rc == 421) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server")); + ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server")); if (rc == 550) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: RETR failed, trying LIST instead"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: RETR failed, trying LIST instead"); get_dirlisting = 1; - ftp_set_TYPE(r, ctrl, 'A'); /* directories must be transferred in ASCII */ + ftp_set_TYPE(r, ctrl, 'A'); /* directories must be transferred in + * ASCII */ ap_bvputs(ctrl, "CWD ", path, CRLF, NULL); ap_bflush(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: CWD %s", path); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: CWD %s", path); /* possible results: 250, 421, 500, 501, 502, 530, 550 */ /* 250 Requested file action okay, completed. */ /* 421 Service not available, closing control connection. */ @@ -1190,11 +1196,11 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) /* 530 Not logged in. */ /* 550 Requested action not taken. */ rc = ftp_getrc(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: returned status %d", rc); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", rc); if (rc == -1 || rc == 421) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server")); + ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server")); if (rc == 550) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, HTTP_NOT_FOUND); @@ -1205,7 +1211,7 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) #ifdef AUTODETECT_PWD ap_bvputs(ctrl, "PWD", CRLF, NULL); ap_bflush(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: PWD"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PWD"); /* responses: 257, 500, 501, 502, 421, 550 */ /* 257 "<directory-name>" <commentary> */ /* 421 Service not available, closing control connection. */ @@ -1214,11 +1220,11 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) /* 502 Command not implemented. */ /* 550 Requested action not taken. */ i = ftp_getrc_msg(ctrl, resp, sizeof resp); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: PWD returned status %d", i); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PWD returned status %d", i); if (i == -1 || i == 421) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server")); + ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server")); if (i == 550) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, HTTP_NOT_FOUND); @@ -1226,22 +1232,22 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) const char *dirp = resp; cwd = ap_getword_conf(r->pool, &dirp); } -#endif /*AUTODETECT_PWD*/ +#endif /* AUTODETECT_PWD */ ap_bputs("LIST -lag" CRLF, ctrl); ap_bflush(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: LIST -lag"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: LIST -lag"); rc = ftp_getrc(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: returned status %d", rc); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", rc); if (rc == -1 || rc == 421) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server")); + ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server")); } ap_kill_timeout(r); if (rc != 125 && rc != 150 && rc != 226 && rc != 250) return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, - HTTP_BAD_GATEWAY); + HTTP_BAD_GATEWAY); r->status = HTTP_OK; r->status_line = "200 OK"; @@ -1260,11 +1266,12 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) } else { #ifdef CHARSET_EBCDIC - r->ebcdic.conv_out = 0; /* do not convert what we read from the ftp server */ + r->ebcdic.conv_out = 0; /* do not convert what we read from the ftp + * server */ #endif if (r->content_type != NULL) { ap_table_setn(resp_hdrs, "Content-Type", r->content_type); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: Content-Type set to %s", r->content_type); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: Content-Type set to %s", r->content_type); } else { ap_table_setn(resp_hdrs, "Content-Type", ap_default_type(r)); @@ -1272,11 +1279,11 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) if (xfer_type != 'A' && size != NULL) { /* We "trust" the ftp server to really serve (size) bytes... */ ap_table_set(resp_hdrs, "Content-Length", size); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: Content-Length set to %s", size); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: Content-Length set to %s", size); } } if (r->content_encoding != NULL && r->content_encoding[0] != '\0') { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: Content-Encoding set to %s", r->content_encoding); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: Content-Encoding set to %s", r->content_encoding); ap_table_setn(resp_hdrs, "Content-Encoding", r->content_encoding); } @@ -1285,10 +1292,10 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) for (i = 0; i < conf->nocaches->nelts; i++) { if (destaddr.s_addr == ncent[i].addr.s_addr || (ncent[i].name != NULL && - (ncent[i].name[0] == '*' || - strstr(host, ncent[i].name) != NULL))) { - nocache = 1; - break; + (ncent[i].name[0] == '*' || + strstr(host, ncent[i].name) != NULL))) { + nocache = 1; + break; } } } @@ -1303,11 +1310,11 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) ap_hard_timeout("proxy ftp data connect", r); clen = sizeof(struct sockaddr_in); do - csd = accept(dsock, (struct sockaddr *) &server, &clen); + csd = accept(dsock, (struct sockaddr *)&server, &clen); while (csd == -1 && errno == EINTR); if (csd == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "proxy: failed to accept data connection"); + "proxy: failed to accept data connection"); if (c != NULL) c = ap_proxy_cache_error(c); return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, @@ -1327,15 +1334,15 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) /* send response */ /* write status line and headers to the cache file */ ap_proxy_write_headers(c, ap_pstrcat(p, "HTTP/1.1 ", r->status_line, NULL), resp_hdrs); - + /* Setup the headers for our client from upstreams response-headers */ ap_overlap_tables(r->headers_out, resp_hdrs, AP_OVERLAP_TABLES_SET); /* Add X-Cache header */ ap_table_setn(r->headers_out, "X-Cache", ap_pstrcat(r->pool, "MISS from ", - ap_get_server_name(r), NULL)); + ap_get_server_name(r), NULL)); /* The Content-Type of this response is the upstream one. */ - r->content_type = ap_table_get (r->headers_out, "Content-Type"); + r->content_type = ap_table_get(r->headers_out, "Content-Type"); /* finally output the headers to the client */ ap_send_http_header(r); @@ -1348,7 +1355,7 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) /* we need to set this for ap_proxy_send_fb()... */ if (c != NULL) c->cache_completion = 0; - ap_proxy_send_fb(data, r, c, -1, 0, conf->io_buffer_size); + ap_proxy_send_fb(data, r, c, -1, 0, 0, conf->io_buffer_size); } else { send_dir(data, r, c, cwd); @@ -1357,8 +1364,9 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) data = NULL; dsock = -1; - /* We checked for 125||150||226||250 above. - * See if another rc is pending, and fetch it: + /* + * We checked for 125||150||226||250 above. See if another rc is + * pending, and fetch it: */ if (rc == 125 || rc == 150) rc = ftp_getrc(ctrl); @@ -1372,16 +1380,16 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) data = NULL; dsock = -1; } - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: ABOR"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: ABOR"); /* responses: 225, 226, 421, 500, 501, 502 */ - /* 225 Data connection open; no transfer in progress. */ - /* 226 Closing data connection. */ - /* 421 Service not available, closing control connection. */ - /* 500 Syntax error, command unrecognized. */ - /* 501 Syntax error in parameters or arguments. */ - /* 502 Command not implemented. */ + /* 225 Data connection open; no transfer in progress. */ + /* 226 Closing data connection. */ + /* 421 Service not available, closing control connection. */ + /* 500 Syntax error, command unrecognized. */ + /* 501 Syntax error in parameters or arguments. */ + /* 502 Command not implemented. */ i = ftp_getrc(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: returned status %d", i); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i); } ap_kill_timeout(r); @@ -1390,16 +1398,16 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) /* finish */ ap_bputs("QUIT" CRLF, ctrl); ap_bflush(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: QUIT"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: QUIT"); /* responses: 221, 500 */ /* 221 Service closing control connection. */ /* 500 Syntax error, command unrecognized. */ i = ftp_getrc(ctrl); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: QUIT: status %d", i); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: QUIT: status %d", i); ap_bclose(ctrl); - ap_rflush(r); /* flush before garbage collection */ + ap_rflush(r); /* flush before garbage collection */ ap_proxy_garbage_coll(r); diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_http.c b/usr.sbin/httpd/src/modules/proxy/proxy_http.c index d756a0f7f90..92f06493e72 100644 --- a/usr.sbin/httpd/src/modules/proxy/proxy_http.c +++ b/usr.sbin/httpd/src/modules/proxy/proxy_http.c @@ -76,8 +76,8 @@ int ap_proxy_http_canon(request_rec *r, char *url, const char *scheme, int def_p const char *err; int port; - /* do syntatic check. - * We break the URL into host, port, path, search + /* + * do syntatic check. We break the URL into host, port, path, search */ port = def_port; err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port); @@ -85,9 +85,10 @@ int ap_proxy_http_canon(request_rec *r, char *url, const char *scheme, int def_p return HTTP_BAD_REQUEST; /* now parse path/search args, according to rfc1738 */ - /* N.B. if this isn't a true proxy request, then the URL _path_ - * has already been decoded. True proxy requests have r->uri - * == r->unparsed_uri, and no others have that property. + /* + * N.B. if this isn't a true proxy request, then the URL _path_ has + * already been decoded. True proxy requests have r->uri == + * r->unparsed_uri, and no others have that property. */ if (r->uri == r->unparsed_uri) { search = strchr(url, '?'); @@ -146,12 +147,12 @@ static const char *proxy_location_reverse_map(request_rec *r, const char *url) * route.) */ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, - const char *proxyhost, int proxyport) + const char *proxyhost, int proxyport) { const char *strp; char *strp2; const char *err, *desthost; - int i, j, sock, len, backasswards; + int i, j, sock,/* len,*/ backasswards; table *req_hdrs, *resp_hdrs; array_header *reqhdrs_arr; table_entry *reqhdrs_elts; @@ -163,21 +164,25 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, char portstr[32]; pool *p = r->pool; int destport = 0; + int chunked = 0; char *destportstr = NULL; const char *urlptr = NULL; const char *datestr, *urlstr; + int result, major, minor; + const char *content_length; #ifdef EAPI char *peer; #endif void *sconf = r->server->module_config; proxy_server_conf *conf = - (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts; struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts; int nocache = 0; - if (conf->cache.root == NULL) nocache = 1; + if (conf->cache.root == NULL) + nocache = 1; memset(&server, '\0', sizeof(server)); server.sin_family = AF_INET; @@ -222,7 +227,7 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, for (i = 0; i < conf->noproxies->nelts; i++) { if (destaddr.s_addr == npent[i].addr.s_addr || (npent[i].name != NULL && - (npent[i].name[0] == '*' || strstr(desthost, npent[i].name) != NULL))) + (npent[i].name[0] == '*' || strstr(desthost, npent[i].name) != NULL))) return ap_proxyerror(r, HTTP_FORBIDDEN, "Connect to remote machine blocked"); } @@ -247,30 +252,31 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, } - /* we have worked out who exactly we are going to connect to, now - * make that connection... + /* + * we have worked out who exactly we are going to connect to, now make + * that connection... */ sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "proxy: error creating socket"); + "proxy: error creating socket"); return HTTP_INTERNAL_SERVER_ERROR; } #if !defined(TPF) && !defined(BEOS) if (conf->recv_buffer_size) { if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, - (const char *) &conf->recv_buffer_size, sizeof(int)) + (const char *)&conf->recv_buffer_size, sizeof(int)) == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); + "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); } } #endif #ifdef SINIX_D_RESOLVER_BUG { - struct in_addr *ip_addr = (struct in_addr *) *server_hp.h_addr_list; + struct in_addr *ip_addr = (struct in_addr *)*server_hp.h_addr_list; for (; ip_addr->s_addr != 0; ++ip_addr) { memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr)); @@ -295,23 +301,24 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, return DECLINED; /* try again another way */ else return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool, - "Could not connect to remote machine: ", - strerror(errno), NULL)); + "Could not connect to remote machine: ", + strerror(errno), NULL)); } /* record request_time for HTTP/1.1 age calculation */ c->req_time = time(NULL); - /* build upstream-request headers by stripping r->headers_in from - * connection specific headers. - * We must not remove the Connection: header from r->headers_in, - * we still have to react to Connection: close + /* + * build upstream-request headers by stripping r->headers_in from + * connection specific headers. We must not remove the Connection: header + * from r->headers_in, we still have to react to Connection: close */ req_hdrs = ap_copy_table(r->pool, r->headers_in); ap_proxy_clear_connection(r->pool, req_hdrs); - /* At this point, we start sending the HTTP/1.1 request to the - * remote server (proxy or otherwise). + /* + * At this point, we start sending the HTTP/1.1 request to the remote + * server (proxy or otherwise). */ f = ap_bcreate(p, B_RDWR | B_SOCKET); ap_bpushfd(f, sock, sock); @@ -330,7 +337,7 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, ap_hard_timeout("proxy send", r); ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.1" CRLF, - NULL); + NULL); #ifdef EAPI { int rc = DECLINED; @@ -356,43 +363,68 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, if (conf->viaopt == via_block) { /* Block all outgoing Via: headers */ ap_table_unset(req_hdrs, "Via"); - } else if (conf->viaopt != via_off) { + } + else if (conf->viaopt != via_off) { /* Create a "Via:" request header entry and merge it */ i = ap_get_server_port(r); - if (ap_is_default_port(i,r)) { - strcpy(portstr,""); - } else { + if (ap_is_default_port(i, r)) { + strcpy(portstr, ""); + } + else { ap_snprintf(portstr, sizeof portstr, ":%d", i); } /* Generate outgoing Via: header with/without server comment: */ ap_table_mergen(req_hdrs, "Via", - (conf->viaopt == via_full) + (conf->viaopt == via_full) ? ap_psprintf(p, "%d.%d %s%s (%s)", - HTTP_VERSION_MAJOR(r->proto_num), - HTTP_VERSION_MINOR(r->proto_num), - ap_get_server_name(r), portstr, - SERVER_BASEVERSION) + HTTP_VERSION_MAJOR(r->proto_num), + HTTP_VERSION_MINOR(r->proto_num), + ap_get_server_name(r), portstr, + SERVER_BASEVERSION) : ap_psprintf(p, "%d.%d %s%s", - HTTP_VERSION_MAJOR(r->proto_num), - HTTP_VERSION_MINOR(r->proto_num), - ap_get_server_name(r), portstr) - ); + HTTP_VERSION_MAJOR(r->proto_num), + HTTP_VERSION_MINOR(r->proto_num), + ap_get_server_name(r), portstr) + ); } - /* Add X-Forwarded-For: so that the upstream has a chance to - determine, where the original request came from. */ - ap_table_mergen(req_hdrs, "X-Forwarded-For", r->connection->remote_ip); - + /* the X-* headers are only added if we are a reverse + * proxy, otherwise we would be giving away private information. + */ + if (r->proxyreq == PROXY_PASS) { + const char *buf; + + /* + * Add X-Forwarded-For: so that the upstream has a chance to determine, + * where the original request came from. + */ + ap_table_mergen(req_hdrs, "X-Forwarded-For", r->connection->remote_ip); + + /* Add X-Forwarded-Host: so that upstream knows what the + * original request hostname was. + */ + if ((buf = ap_table_get(r->headers_in, "Host"))) { + ap_table_mergen(req_hdrs, "X-Forwarded-Host", buf); + } + + /* Add X-Forwarded-Server: so that upstream knows what the + * name of this proxy server is (if there are more than one) + * XXX: This duplicates Via: - do we strictly need it? + */ + ap_table_mergen(req_hdrs, "X-Forwarded-Server", r->server->server_hostname); + } + /* we don't yet support keepalives - but we will soon, I promise! */ ap_table_set(req_hdrs, "Connection", "close"); reqhdrs_arr = ap_table_elts(req_hdrs); - reqhdrs_elts = (table_entry *) reqhdrs_arr->elts; + reqhdrs_elts = (table_entry *)reqhdrs_arr->elts; for (i = 0; i < reqhdrs_arr->nelts; i++) { if (reqhdrs_elts[i].key == NULL || reqhdrs_elts[i].val == NULL - /* Clear out hop-by-hop request headers not to send: - * RFC2616 13.5.1 says we should strip these headers: + /* + * Clear out hop-by-hop request headers not to send: RFC2616 13.5.1 + * says we should strip these headers: */ || !strcasecmp(reqhdrs_elts[i].key, "Host") /* Already sent */ || !strcasecmp(reqhdrs_elts[i].key, "Keep-Alive") @@ -400,16 +432,16 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, || !strcasecmp(reqhdrs_elts[i].key, "Trailer") || !strcasecmp(reqhdrs_elts[i].key, "Transfer-Encoding") || !strcasecmp(reqhdrs_elts[i].key, "Upgrade") - - /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be - * suppressed if THIS server requested the authentication, - * not when a frontend proxy requested it! - * - * The solution to this problem is probably to strip out - * the Proxy-Authorisation header in the authorisation - * code itself, not here. This saves us having to signal - * somehow whether this request was authenticated or not. - */ + /* + * XXX: @@@ FIXME: "Proxy-Authorization" should *only* be suppressed + * if THIS server requested the authentication, not when a frontend + * proxy requested it! + * + * The solution to this problem is probably to strip out the + * Proxy-Authorisation header in the authorisation code itself, not + * here. This saves us having to signal somehow whether this request + * was authenticated or not. + */ || !strcasecmp(reqhdrs_elts[i].key, "Proxy-Authorization")) continue; ap_bvputs(f, reqhdrs_elts[i].key, ": ", reqhdrs_elts[i].val, CRLF, NULL); @@ -418,105 +450,124 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, /* the obligatory empty line to mark the end of the headers */ ap_bputs(CRLF, f); - /* send the request data, if any. */ - if (ap_should_client_block(r)) { - while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) - ap_bwrite(f, buffer, i); - } + /* and flush the above away */ ap_bflush(f); + + /* and kill the send timeout */ ap_kill_timeout(r); - /* Right - now it's time to listen for a response. + /* read the request data, and pass it to the backend. + * we might encounter a stray 100-continue reponse from a PUT or POST, + * if this happens we ignore the 100 continue status line and read the + * response again. */ - ap_hard_timeout("proxy receive", r); - - len = ap_bgets(buffer, sizeof buffer - 1, f); - if (len == -1) { - ap_bclose(f); + { + /* send the request data, if any. */ + ap_hard_timeout("proxy receive request data", r); + if (ap_should_client_block(r)) { + while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) { + ap_reset_timeout(r); + ap_bwrite(f, buffer, i); + } + } + ap_bflush(f); ap_kill_timeout(r); - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "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); + + + /* then, read a response line */ + ap_hard_timeout("proxy receive response status line", r); + result = ap_proxy_read_response_line(f, r, buffer, sizeof(buffer)-1, &backasswards, &major, &minor); ap_kill_timeout(r); - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Document contains no data"); - } - /* Is it an HTTP/1 response? - * Do some sanity checks on the response. - * (This is buggy if we ever see an HTTP/1.10) - */ - if (ap_checkmask(buffer, "HTTP/#.# ###*")) { - int major, minor; - if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) { - /* if no response, default to HTTP/1.1 - is this correct? */ - major = 1; - minor = 1; + /* trap any errors */ + if (result != OK) { + ap_bclose(f); + return result; } - /* If not an HTTP/1 message or if the status line was > 8192 bytes */ - if (buffer[5] != '1' || buffer[len - 1] != '\n') { - ap_bclose(f); + /* if this response was 100-continue, a stray response has been caught. + * read the line again for the real response + */ + if (r->status == 100) { + ap_hard_timeout("proxy receive response status line", r); + result = ap_proxy_read_response_line(f, r, buffer, sizeof(buffer)-1, &backasswards, &major, &minor); ap_kill_timeout(r); - return HTTP_BAD_GATEWAY; + + /* trap any errors */ + if (result != OK) { + ap_bclose(f); + return result; + } } - backasswards = 0; - buffer[--len] = '\0'; + } - buffer[12] = '\0'; - r->status = atoi(&buffer[9]); - buffer[12] = ' '; - r->status_line = ap_pstrdup(p, &buffer[9]); + + /* + * We have our response status line from the convoluted code above, + * now we read the headers to continue. + */ + ap_hard_timeout("proxy receive response headers", r); + + /* + * Is it an HTTP/1 response? Do some sanity checks on the response. (This + * is buggy if we ever see an HTTP/1.10) + */ + if (backasswards == 0) { /* read the response headers. */ /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */ /* Also, take care with headers with multiple occurences. */ - resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, f); + resp_hdrs = ap_proxy_read_headers(r, buffer, sizeof(buffer), f); if (resp_hdrs == NULL) { - ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, r->server, - "proxy: Bad HTTP/%d.%d header returned by %s (%s)", - major, minor, r->uri, r->method); + ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, r->server, + "proxy: Bad HTTP/%d.%d header returned by %s (%s)", + major, minor, r->uri, r->method); resp_hdrs = ap_make_table(p, 20); - nocache = 1; /* do not cache this broken file */ + nocache = 1; /* do not cache this broken file */ } /* handle Via header in the response */ if (conf->viaopt != via_off && conf->viaopt != via_block) { /* Create a "Via:" response header entry and merge it */ i = ap_get_server_port(r); - if (ap_is_default_port(i,r)) { - strcpy(portstr,""); - } else { + if (ap_is_default_port(i, r)) { + strcpy(portstr, ""); + } + else { ap_snprintf(portstr, sizeof portstr, ":%d", i); } ap_table_mergen((table *)resp_hdrs, "Via", (conf->viaopt == via_full) ? ap_psprintf(p, "%d.%d %s%s (%s)", - major, minor, - ap_get_server_name(r), portstr, - SERVER_BASEVERSION) + major, minor, + ap_get_server_name(r), portstr, + SERVER_BASEVERSION) : ap_psprintf(p, "%d.%d %s%s", - major, minor, - ap_get_server_name(r), portstr) - ); + major, minor, + ap_get_server_name(r), portstr) + ); } - /* strip hop-by-hop headers defined by Connection */ + /* is this content chunked? */ + chunked = ap_find_last_token(r->pool, + ap_table_get(resp_hdrs, "Transfer-Encoding"), + "chunked"); + + /* strip hop-by-hop headers defined by Connection and RFC2616 */ ap_proxy_clear_connection(p, resp_hdrs); + + content_length = ap_table_get(resp_hdrs, "Content-Length"); + if (content_length != NULL) { + c->len = ap_strtol(content_length, NULL, 10); + } + /* Now add out bound headers set by other modules */ resp_hdrs = ap_overlay_tables(r->pool, r->err_headers_out, resp_hdrs); -} + } else { /* an http/0.9 response */ - backasswards = 1; - r->status = 200; - r->status_line = "200 OK"; /* no headers */ resp_hdrs = ap_make_table(p, 20); @@ -525,10 +576,11 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, ap_kill_timeout(r); /* - * HTTP/1.1 requires us to accept 3 types of dates, but only generate - * one type + * HTTP/1.1 requires us to accept 3 types of dates, but only generate one + * type */ - /* we SET the dates here, obliterating possible multiple dates, as only + /* + * we SET the dates here, obliterating possible multiple dates, as only * one of each date makes sense in each response. */ if ((datestr = ap_table_get(resp_hdrs, "Date")) != NULL) @@ -540,72 +592,82 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, /* handle the ProxyPassReverse mappings */ if ((urlstr = ap_table_get(resp_hdrs, "Location")) != NULL) - ap_table_set(resp_hdrs, "Location", proxy_location_reverse_map(r, urlstr)); + ap_table_set(resp_hdrs, "Location", proxy_location_reverse_map(r, urlstr)); if ((urlstr = ap_table_get(resp_hdrs, "URI")) != NULL) - ap_table_set(resp_hdrs, "URI", proxy_location_reverse_map(r, urlstr)); + ap_table_set(resp_hdrs, "URI", proxy_location_reverse_map(r, urlstr)); if ((urlstr = ap_table_get(resp_hdrs, "Content-Location")) != NULL) - ap_table_set(resp_hdrs, "Content-Location", proxy_location_reverse_map(r , urlstr)); + ap_table_set(resp_hdrs, "Content-Location", proxy_location_reverse_map(r, urlstr)); /* check if NoCache directive on this host */ if (nocache == 0) { for (i = 0; i < conf->nocaches->nelts; i++) { if (destaddr.s_addr == ncent[i].addr.s_addr || (ncent[i].name != NULL && - (ncent[i].name[0] == '*' || - strstr(desthost, ncent[i].name) != NULL))) { - nocache = 1; - break; + (ncent[i].name[0] == '*' || + strstr(desthost, ncent[i].name) != NULL))) { + nocache = 1; + break; } } - /* update the cache file, possibly even fulfilling the request if - * it turns out a conditional allowed us to serve the object from the - * cache... - */ - i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache); - if (i != DECLINED) { - ap_bclose(f); - return i; - } + /* + * update the cache file, possibly even fulfilling the request if it + * turns out a conditional allowed us to serve the object from the + * cache... + */ + i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache); + if (i != DECLINED) { + ap_bclose(f); + return i; + } /* write status line and headers to the cache file */ ap_proxy_write_headers(c, ap_pstrcat(p, "HTTP/1.1 ", r->status_line, NULL), resp_hdrs); } /* Setup the headers for our client from upstreams response-headers */ - ap_overlap_tables(r->headers_out, resp_hdrs, AP_OVERLAP_TABLES_SET); + ap_proxy_table_replace(r->headers_out, resp_hdrs); /* Add X-Cache header - be careful not to obliterate any upstream headers */ ap_table_mergen(r->headers_out, "X-Cache", - ap_pstrcat(r->pool, "MISS from ", - ap_get_server_name(r), NULL)); + ap_pstrcat(r->pool, "MISS from ", + ap_get_server_name(r), NULL)); /* The Content-Type of this response is the upstream one. */ - r->content_type = ap_table_get (r->headers_out, "Content-Type"); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Content-Type: %s", r->content_type); + r->content_type = ap_table_get(r->headers_out, "Content-Type"); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Content-Type: %s", r->content_type); /* finally output the headers to the client */ ap_send_http_header(r); - /* Is it an HTTP/0.9 respose? If so, send the extra data we read - from upstream as the start of the reponse to client */ + /* + * Is it an HTTP/0.9 respose? If so, send the extra data we read from + * upstream as the start of the reponse to client + */ +/* FIXME: This code is broken: we try and write a buffer and length that + * were never intelligently initialised. Rather have a bit of broken protocol + * handling for now than broken code. + */ +/* if (backasswards) { ap_hard_timeout("proxy send assbackward", r); ap_bwrite(r->connection->client, buffer, 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); + "proxy: error writing extra data to %s", c->tempfile); c = ap_proxy_cache_error(c); } ap_kill_timeout(r); } - +*/ #ifdef CHARSET_EBCDIC - /* What we read/write after the header should not be modified - * (i.e., the cache copy is ASCII, not EBCDIC, even for text/html) + /* + * What we read/write after the header should not be modified (i.e., the + * cache copy is ASCII, not EBCDIC, even for text/html) */ - ap_bsetflag(f, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); - ap_bsetflag(r->connection->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); + r->ebcdic.conv_in = r->ebcdic.conv_out = 0; + ap_bsetflag(f, B_ASCII2EBCDIC | B_EBCDIC2ASCII, 0); + ap_bsetflag(r->connection->client, B_ASCII2EBCDIC | B_EBCDIC2ASCII, 0); #endif /* send body */ @@ -621,7 +683,7 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, * content length is not known. We need to make 100% sure c->len is always * set correctly before we get here to correctly do keepalive. */ - ap_proxy_send_fb(f, r, c, c->len, 0, conf->io_buffer_size); + ap_proxy_send_fb(f, r, c, c->len, 0, chunked, conf->io_buffer_size); } /* ap_proxy_send_fb() closes the socket f for us */ diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_util.c b/usr.sbin/httpd/src/modules/proxy/proxy_util.c index 0863019dd7b..d350412e938 100644 --- a/usr.sbin/httpd/src/modules/proxy/proxy_util.c +++ b/usr.sbin/httpd/src/modules/proxy/proxy_util.c @@ -63,7 +63,7 @@ #include "multithread.h" #include "http_log.h" #include "util_uri.h" -#include "util_date.h" /* get ap_checkmask() decl. */ +#include "util_date.h" /* get ap_checkmask() decl. */ static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r); static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r); @@ -73,9 +73,10 @@ static struct per_thread_data *get_per_thread_data(void); /* already called in the knowledge that the characters are hex digits */ int ap_proxy_hex2c(const char *x) { - int i, ch; - + int i; #ifndef CHARSET_EBCDIC + int ch; + ch = x[0]; if (ap_isdigit(ch)) i = ch - '0'; @@ -93,9 +94,9 @@ int ap_proxy_hex2c(const char *x) else i += ch - ('a' - 10); return i; -#else /*CHARSET_EBCDIC*/ - return (1 == sscanf(x, "%2x", &i)) ? os_toebcdic[i&0xFF] : 0; -#endif /*CHARSET_EBCDIC*/ +#else /* CHARSET_EBCDIC */ + return (1 == sscanf(x, "%2x", &i)) ? os_toebcdic[i & 0xFF] : 0; +#endif /* CHARSET_EBCDIC */ } void ap_proxy_c2hex(int ch, char *x) @@ -115,14 +116,14 @@ void ap_proxy_c2hex(int ch, char *x) x[2] = ('A' - 10) + i; else x[2] = '0' + i; -#else /*CHARSET_EBCDIC*/ - static const char ntoa[] = { "0123456789ABCDEF" }; +#else /* CHARSET_EBCDIC */ + static const char ntoa[] = {"0123456789ABCDEF"}; ch = os_toascii[ch & 0xFF]; x[0] = '%'; - x[1] = ntoa[(ch>>4)&0x0F]; - x[2] = ntoa[ch&0x0F]; + x[1] = ntoa[(ch >> 4) & 0x0F]; + x[2] = ntoa[ch & 0x0F]; x[3] = '\0'; -#endif /*CHARSET_EBCDIC*/ +#endif /* CHARSET_EBCDIC */ } /* @@ -136,7 +137,7 @@ void ap_proxy_c2hex(int ch, char *x) * those which must not be touched. */ char *ap_proxy_canonenc(pool *p, const char *x, int len, enum enctype t, - enum proxyreqtype isenc) + enum proxyreqtype isenc) { int i, j, ch; char *y; @@ -145,7 +146,7 @@ char *ap_proxy_canonenc(pool *p, const char *x, int len, enum enctype t, /* N.B. in addition to :@&=, this allows ';' in an http path * and '?' in an ftp path -- this may be revised - * + * * Also, it makes a '+' character in a search string reserved, as * it may be form-encoded. (Although RFC 1738 doesn't allow this - * it only permits ; / ? : @ = & as reserved chars.) @@ -213,7 +214,7 @@ char *ap_proxy_canonenc(pool *p, const char *x, int len, enum enctype t, */ char * ap_proxy_canon_netloc(pool *p, char **const urlp, char **userp, - char **passwordp, char **hostp, int *port) + char **passwordp, char **hostp, int *port) { int i; char *strp, *host, *url = *urlp; @@ -267,13 +268,14 @@ char * /* if (i == 0) the no port was given; keep default */ if (strp[i] != '\0') { return "Bad port number in URL"; - } else if (i > 0) { + } + else if (i > 0) { *port = atoi(strp); if (*port > 65535) return "Port number in URL > 65535"; } } - ap_str_tolower(host); /* DNS names are case-insensitive */ + ap_str_tolower(host); /* DNS names are case-insensitive */ if (*host == '\0') return "Missing host in URL"; /* check hostname syntax */ @@ -299,7 +301,7 @@ char * return NULL; } -static const char * const lwday[7] = +static const char *const lwday[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; /* @@ -365,63 +367,6 @@ const char * } -/* NOTE: This routine is taken from http_protocol::getline() - * because the old code found in the proxy module was too - * difficult to understand and maintain. - */ -/* Get a line of protocol input, including any continuation lines - * caused by MIME folding (or broken clients) if fold != 0, and place it - * in the buffer s, of size n bytes, without the ending newline. - * - * Returns -1 on error, or the length of s. - * - * Note: Because bgets uses 1 char for newline and 1 char for NUL, - * the most we can get is (n - 2) actual characters if it - * was ended by a newline, or (n - 1) characters if the line - * length exceeded (n - 1). So, if the result == (n - 1), - * then the actual input line exceeded the buffer length, - * and it would be a good idea for the caller to puke 400 or 414. - */ -static int proxy_getline(char *s, int n, BUFF *in, int fold) -{ - char *pos, next; - int retval; - int total = 0; - - pos = s; - - do { - retval = ap_bgets(pos, n, in); /* retval == -1 if error, 0 if EOF */ - - if (retval <= 0) - return ((retval < 0) && (total == 0)) ? -1 : total; - - /* retval is the number of characters read, not including NUL */ - - n -= retval; /* Keep track of how much of s is full */ - pos += (retval - 1); /* and where s ends */ - total += retval; /* and how long s has become */ - - if (*pos == '\n') { /* Did we get a full line of input? */ - *pos = '\0'; - --total; - ++n; - } - else - return total; /* if not, input line exceeded buffer size */ - - /* Continue appending if line folding is desired and - * the last line was not empty and we have room in the buffer and - * the next line begins with a continuation character. - */ - } while (fold && (retval != 1) && (n > 1) - && (ap_blookc(&next, in) == 1) - && ((next == ' ') || (next == '\t'))); - - return total; -} - - /* * Reads headers from a buffer and returns an array of headers. * Returns NULL on file error @@ -445,72 +390,80 @@ table *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF *f) * Read header lines until we get the empty separator line, a read error, * the connection closes (EOF), or we timeout. */ - while ((len = proxy_getline(buffer, size, f, 1)) > 0) { - - if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */ + while ((len = ap_getline(buffer, size, f, 1)) > 0) { - /* Buggy MS IIS servers sometimes return invalid headers - * (an extra "HTTP/1.0 200, OK" line sprinkled in between - * the usual MIME headers). Try to deal with it in a sensible - * way, but log the fact. - * XXX: The mask check is buggy if we ever see an HTTP/1.10 */ + if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */ + + /* + * Buggy MS IIS servers sometimes return invalid headers (an + * extra "HTTP/1.0 200, OK" line sprinkled in between the usual + * MIME headers). Try to deal with it in a sensible way, but log + * the fact. XXX: The mask check is buggy if we ever see an + * HTTP/1.10 + */ if (!ap_checkmask(buffer, "HTTP/#.# ###*")) { /* Nope, it wasn't even an extra HTTP header. Give up. */ return NULL; } - ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, r->server, - "proxy: Ignoring duplicate HTTP header " - "returned by %s (%s)", r->uri, r->method); + ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, r->server, + "proxy: Ignoring duplicate HTTP status line " + "returned by buggy server %s (%s)", r->uri, r->method); continue; } *value = '\0'; ++value; - /* XXX: RFC2068 defines only SP and HT as whitespace, this test is + /* + * XXX: RFC2068 defines only SP and HT as whitespace, this test is * wrong... and so are many others probably. */ while (ap_isspace(*value)) ++value; /* Skip to start of value */ /* should strip trailing whitespace as well */ - for (end = &value[strlen(value)-1]; end > value && ap_isspace(*end); --end) + for (end = &value[strlen(value) - 1]; end > value && ap_isspace(*end); --end) *end = '\0'; /* make sure we add so as not to destroy duplicated headers */ ap_table_add(resp_hdrs, buffer, value); /* the header was too long; at the least we should skip extra data */ - if (len >= size - 1) { - while ((len = proxy_getline(field, MAX_STRING_LEN, f, 1)) - >= MAX_STRING_LEN - 1) { + if (len >= size - 1) { + while ((len = ap_getline(field, MAX_STRING_LEN, f, 1)) + >= MAX_STRING_LEN - 1) { /* soak up the extra data */ } - if (len == 0) /* time to exit the larger loop as well */ + if (len == 0) /* time to exit the larger loop as well */ break; } } return resp_hdrs; } -/* read data from f, write it to: +/* read data from (socket BUFF*) f, write it to: * - c->fp, if it is open * - r->connection->client, if nowrite == 0 */ -long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int nowrite, size_t recv_buffer_size) +long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int nowrite, int chunked, size_t recv_buffer_size) { - int ok; + int ok, end_of_chunk; char *buf; size_t buf_size; + long remaining = 0; long total_bytes_rcvd; - register int n, o, w; + register int n = 0, o, w; conn_rec *con = r->connection; - int alternate_timeouts = 1; /* 1 if we alternate between soft & hard timeouts */ + int alternate_timeouts = 1; /* 1 if we alternate between soft & hard + * timeouts */ /* allocate a buffer to store the bytes in */ - /* make sure it is at least IOBUFSIZE, as recv_buffer_size may be zero for system default */ + /* + * make sure it is at least IOBUFSIZE, as recv_buffer_size may be zero + * for system default + */ buf_size = MAX(recv_buffer_size, IOBUFSIZE); buf = ap_palloc(r->pool, buf_size); @@ -520,15 +473,14 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int #ifdef CHARSET_EBCDIC /* The cache copy is ASCII, not EBCDIC, even for text/html) */ - ap_bsetflag(f, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); - if (c != NULL && c->fp != NULL) - ap_bsetflag(c->fp, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); - ap_bsetflag(con->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); + ap_bsetflag(f, B_ASCII2EBCDIC | B_EBCDIC2ASCII, 0); + ap_bsetflag(con->client, B_ASCII2EBCDIC | B_EBCDIC2ASCII, 0); #endif - /* Since we are reading from one buffer and writing to another, - * it is unsafe to do a soft_timeout here, at least until the proxy - * has its own timeout handler which can set both buffers to EOUT. + /* + * Since we are reading from one buffer and writing to another, it is + * unsafe to do a soft_timeout here, at least until the proxy has its own + * timeout handler which can set both buffers to EOUT. */ ap_kill_timeout(r); @@ -538,12 +490,13 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int ap_hard_timeout("proxy send body", r); 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) + /* + * 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 == NULL || c->len <= 0 || c->cache_completion == 1.0) { @@ -552,22 +505,98 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int } #endif - /* 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. + /* + * 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; ) { + for (end_of_chunk = ok = 1; ok;) { if (alternate_timeouts) ap_hard_timeout("proxy recv body from upstream server", r); - /* Read block from server */ - if (-1 == len) { - n = ap_bread(f, buf, buf_size); + + /* read a chunked block */ + if (chunked) { + long chunk_start = 0; + n = 0; + + /* start of a new chunk */ + if (end_of_chunk) { + end_of_chunk = 0; + /* get the chunk size from the stream */ + chunk_start = ap_getline(buf, buf_size, f, 0); + if ((chunk_start <= 0) || ((size_t)chunk_start + 1 >= buf_size) || !ap_isxdigit(*buf)) { + n = -1; + } + /* parse the chunk size */ + else { + remaining = ap_get_chunk_size(buf); + if (remaining == 0) { /* Last chunk indicated, get footers */ + /* as we are a proxy, we discard the footers, as the headers + * have already been sent at this point. + */ + if (NULL == ap_proxy_read_headers(r, buf, buf_size, f)) { + n = -1; + } + } + else if (remaining < 0) { + n = -1; + ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r, + "proxy: remote protocol error, invalid chunk size"); + + } + } + } + + /* read the chunk */ + if (remaining > 0) { + n = ap_bread(f, buf, MIN((int)buf_size, (int)remaining)); + if (n > -1) { + remaining -= n; + end_of_chunk = (remaining == 0); + } + } + + /* soak up trailing CRLF */ + if (end_of_chunk) { + int ch; /* int because it may hold an EOF */ + /* + * For EBCDIC, the proxy has configured the BUFF layer to + * transparently pass the ascii characters thru (also writing + * an ASCII copy to the cache, where appropriate). + * Therefore, we see here an ASCII-CRLF (\015\012), + * not an EBCDIC-CRLF (\r\n). + */ + if ((ch = ap_bgetc(f)) == EOF) { + /* Protocol error: EOF detected within chunk */ + n = -1; + ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r, + "proxy: remote protocol error, eof while reading chunked from proxy"); + } + else + { + if (ch == '\015') { /* _ASCII_ CR */ + ch = ap_bgetc(f); + } + if (ch != '\012') { + n = -1; + } + } + } } + + /* otherwise read block normally */ else { - n = ap_bread(f, buf, MIN((off_t)buf_size, len - total_bytes_rcvd)); + if (-1 == len) { + n = ap_bread(f, buf, buf_size); + } + else { + n = ap_bread(f, buf, MIN((int)buf_size, + (int)(len - total_bytes_rcvd))); + } } + if (alternate_timeouts) ap_kill_timeout(r); else @@ -576,22 +605,23 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int if (n == -1) { /* input error */ if (c != NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, - "proxy: error reading from %s", c->url); + "proxy: error reading from %s", c->url); c = ap_proxy_cache_error(c); } break; } if (n == 0) - break; /* EOF */ + break; /* EOF */ o = 0; total_bytes_rcvd += n; /* if we've received everything... */ - /* in the case of slow frontends and expensive backends, - * we want to avoid leaving a backend connection hanging - * while the frontend takes it's time to absorb the bytes. - * so: if we just read the last block, we close the backend - * connection now instead of later - it's no longer needed. + /* + * in the case of slow frontends and expensive backends, we want to + * avoid leaving a backend connection hanging while the frontend + * takes it's time to absorb the bytes. so: if we just read the last + * block, we close the backend connection now instead of later - it's + * no longer needed. */ if (total_bytes_rcvd == len) { ap_bclose(f); @@ -599,13 +629,17 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int } /* Write to cache first. */ - /*@@@ XXX FIXME: Assuming that writing the cache file won't time out?!!? */ + /* + * @@@ 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) { ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, - "proxy: error writing to %s", c->tempfile); + "proxy: error writing to %s", c->tempfile); c = ap_proxy_cache_error(c); - } else { + } + else { c->written += n; } } @@ -624,18 +658,19 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int if (w <= 0) { if (c != NULL) { - /* when a send failure occurs, we need to decide - * whether to continue loading and caching the - * document, or to abort the whole thing + /* + * when a send failure occurs, we need to decide whether + * to continue loading and caching the document, or to + * abort the whole thing */ ok = (c->len > 0) && - (c->cache_completion > 0) && - (c->len * c->cache_completion < total_bytes_rcvd); + (c->cache_completion > 0) && + (c->len * c->cache_completion < total_bytes_rcvd); - if (! ok) { - if (c->fp!=NULL) { - ap_pclosef(c->req->pool, ap_bfileno(c->fp, B_WR)); - c->fp = NULL; + if (!ok) { + if (c->fp != NULL) { + ap_pclosef(c->req->pool, ap_bfileno(c->fp, B_WR)); + c->fp = NULL; } unlink(c->tempfile); c = NULL; @@ -646,13 +681,13 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int } n -= w; o += w; - } /* while client alive and more data to send */ + } /* while client alive and more data to send */ /* if we've received everything, leave now */ if (total_bytes_rcvd == len) break; - } /* loop and ap_bread while "ok" */ + } /* loop and ap_bread while "ok" */ /* if the backend connection is still open, close it */ if (f) { @@ -664,6 +699,9 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int } ap_kill_timeout(r); + + r->bytes_sent += total_bytes_rcvd; + return total_bytes_rcvd; } @@ -677,11 +715,11 @@ void ap_proxy_write_headers(cache_req *c, const char *respline, table *t) /* write status line */ if (respline && c->fp != NULL && ap_bvputs(c->fp, respline, 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); + ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, + "proxy: error writing status line to %s", c->tempfile); + c = ap_proxy_cache_error(c); return; - } + } /* write response headers to the cache file */ ap_table_do(ap_proxy_send_hdr_line, c, t, NULL); @@ -706,7 +744,7 @@ int ap_proxy_liststr(const char *list, const char *key, char **val) int len, i; const char *p; char valbuf[HUGE_STRING_LEN]; - valbuf[sizeof(valbuf)-1] = 0; /* safety terminating zero */ + valbuf[sizeof(valbuf) - 1] = 0; /* safety terminating zero */ len = strlen(key); @@ -734,7 +772,7 @@ int ap_proxy_liststr(const char *list, const char *key, char **val) while (ap_isspace(*list)) { list++; } - strncpy(valbuf, list, MIN(p-list, sizeof(valbuf)-1)); + strncpy(valbuf, list, MIN(p - list, sizeof(valbuf) - 1)); *val = valbuf; } return 1; @@ -760,7 +798,7 @@ void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength) static const char enc_table[32] = "abcdefghijklmnopqrstuvwxyz012345"; ap_MD5Init(&context); - ap_MD5Update(&context, (const unsigned char *) it, strlen(it)); + ap_MD5Update(&context, (const unsigned char *)it, strlen(it)); ap_MD5Final(digest, &context); /* encode 128 bits as 26 characters, using a modified uuencoding */ @@ -805,17 +843,19 @@ void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength) int i, k, d; unsigned int x; #if defined(MPE) || (defined(AIX) && defined(__ps2__)) - /* Believe it or not, AIX 1.x does not allow you to name a file '@', - * so hack around it in the encoding. */ + /* + * Believe it or not, AIX 1.x does not allow you to name a file '@', so + * hack around it in the encoding. + */ static const char enc_table[64] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_%"; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_%"; #else static const char enc_table[64] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@"; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@"; #endif ap_MD5Init(&context); - ap_MD5Update(&context, (const unsigned char *) it, strlen(it)); + ap_MD5Update(&context, (const unsigned char *)it, strlen(it)); ap_MD5Final(digest, &context); /* encode 128 bits as 22 characters, using a modified uuencoding */ @@ -831,7 +871,7 @@ void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength) } /* one byte left */ x = digest[15]; - tmp[k++] = enc_table[x >> 2]; /* use up 6 bits */ + tmp[k++] = enc_table[x >> 2]; /* use up 6 bits */ tmp[k++] = enc_table[(x << 4) & 0x3f]; /* now split into directory levels */ @@ -845,7 +885,7 @@ void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength) val[i + 22 - k] = '\0'; } -#endif /* CASE_BLIND_FILESYSTEM */ +#endif /* CASE_BLIND_FILESYSTEM */ /* * Converts 16 hex digits to a time integer @@ -867,9 +907,9 @@ int ap_proxy_hex2sec(const char *x) } /* no longer necessary, as the source hex is 8-byte int */ /* if (j == 0xffffffff)*/ -/* return -1;*/ /* so that it works with 8-byte ints */ + /* return -1;*//* so that it works with 8-byte ints */ /* else */ - return j; + return j; } /* @@ -917,14 +957,14 @@ cache_req *ap_proxy_cache_error(cache_req *c) int ap_proxyerror(request_rec *r, int statuscode, const char *message) { ap_table_setn(r->notes, "error-notes", - ap_pstrcat(r->pool, + ap_pstrcat(r->pool, "The proxy server could not handle the request " - "<EM><A HREF=\"", ap_escape_uri(r->pool, r->uri), + "<EM><A HREF=\"", ap_escape_uri(r->pool, r->uri), "\">", ap_escape_html(r->pool, r->method), - " ", - ap_escape_html(r->pool, r->uri), "</A></EM>.<P>\n" + " ", + ap_escape_html(r->pool, r->uri), "</A></EM>.<P>\n" "Reason: <STRONG>", - ap_escape_html(r->pool, message), + ap_escape_html(r->pool, message), "</STRONG>", NULL)); /* Allow "error-notes" string to be printed by ap_send_error_response() */ @@ -938,7 +978,7 @@ int ap_proxyerror(request_rec *r, int statuscode, const char *message) * This routine returns its own error message */ const char * - ap_proxy_host2addr(const char *host, struct hostent *reqhp) + ap_proxy_host2addr(const char *host, struct hostent * reqhp) { int i; struct hostent *hp; @@ -955,14 +995,14 @@ const char * } else { ptd->ipaddr = ap_inet_addr(host); - hp = gethostbyaddr((char *) &ptd->ipaddr, sizeof(ptd->ipaddr), AF_INET); + hp = gethostbyaddr((char *)&ptd->ipaddr, sizeof(ptd->ipaddr), AF_INET); if (hp == NULL) { memset(&ptd->hpbuf, 0, sizeof(ptd->hpbuf)); ptd->hpbuf.h_name = 0; ptd->hpbuf.h_addrtype = AF_INET; ptd->hpbuf.h_length = sizeof(ptd->ipaddr); ptd->hpbuf.h_addr_list = ptd->charpbuf; - ptd->hpbuf.h_addr_list[0] = (char *) &ptd->ipaddr; + ptd->hpbuf.h_addr_list[0] = (char *)&ptd->ipaddr; ptd->hpbuf.h_addr_list[1] = 0; hp = &ptd->hpbuf; } @@ -985,13 +1025,14 @@ static const char * || url[1] != '/' || url[2] != '/') return NULL; - url = ap_pstrdup(r->pool, &url[1]); /* make it point to "//", which is what proxy_canon_netloc expects */ + url = ap_pstrdup(r->pool, &url[1]); /* make it point to "//", which is + * what proxy_canon_netloc expects */ err = ap_proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port); if (err != NULL) - ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r, - "%s", err); + ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r, + "%s", err); r->hostname = host; @@ -1011,9 +1052,12 @@ int ap_proxy_is_ipaddr(struct dirconn_entry *This, pool *p) /* "partial" addresses (with less than 4 quads) correctly, i.e. */ /* 192.168.123 is parsed as 192.168.0.123, which is not what I want. */ /* I therefore have to parse the IP address manually: */ - /*if (proxy_readmask(This->name, &This->addr.s_addr, &This->mask.s_addr) == 0) */ + /* + * if (proxy_readmask(This->name, &This->addr.s_addr, &This->mask.s_addr) + * == 0) + */ /* addr and mask were set by proxy_readmask() */ - /*return 1; */ + /* return 1; */ /* Parse IP addr manually, optionally allowing */ /* abbreviated net addresses like 192.168. */ @@ -1028,7 +1072,7 @@ int ap_proxy_is_ipaddr(struct dirconn_entry *This, pool *p) if (!ap_isdigit(*addr)) return 0; /* no digit at start of quad */ - ip_addr[quads] = strtol(addr, &tmp, 0); + ip_addr[quads] = ap_strtol(addr, &tmp, 0); if (tmp == addr) /* expected a digit, found something else */ return 0; @@ -1052,7 +1096,7 @@ int ap_proxy_is_ipaddr(struct dirconn_entry *This, pool *p) ++addr; - bits = strtol(addr, &tmp, 0); + bits = ap_strtol(addr, &tmp, 0); if (tmp == addr) /* expected a digit, found something else */ return 0; @@ -1070,7 +1114,10 @@ int ap_proxy_is_ipaddr(struct dirconn_entry *This, pool *p) while (quads > 0 && ip_addr[quads - 1] == 0) --quads; - /* "IP Address should be given in dotted-quad form, optionally followed by a netmask (e.g., 192.168.111.0/24)"; */ + /* + * "IP Address should be given in dotted-quad form, optionally + * followed by a netmask (e.g., 192.168.111.0/24)"; + */ if (quads < 1) return 0; @@ -1111,8 +1158,8 @@ static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r) const char *found; const char *host = proxy_get_host_of_request(r); - if (host == NULL) /* oops! */ - return 0; + if (host == NULL) /* oops! */ + return 0; memset(&addr, '\0', sizeof addr); memset(ip_addr, '\0', sizeof ip_addr); @@ -1157,7 +1204,7 @@ static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r) /* Try to deal with multiple IP addr's for a host */ for (ip_listptr = the_host.h_addr_list; *ip_listptr; ++ip_listptr) { - ip_list = (struct in_addr *) *ip_listptr; + ip_list = (struct in_addr *)*ip_listptr; if (This->addr.s_addr == (ip_list->s_addr & This->mask.s_addr)) { #if DEBUGGING fprintf(stderr, "3)IP-Match: %s[%s] <-> ", found, inet_ntoa(*ip_list)); @@ -1256,7 +1303,7 @@ int ap_proxy_is_hostname(struct dirconn_entry *This, pool *p) if (addr[i] != '\0' || ap_proxy_host2addr(addr, &host) != NULL) return 0; - This->hostentry = ap_pduphostent (p, &host); + This->hostentry = ap_pduphostent(p, &host); /* Strip trailing dots */ for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i) @@ -1275,7 +1322,7 @@ static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r) int h1_len; if (host == NULL || host2 == NULL) - return 0; /* oops! */ + return 0; /* oops! */ h2_len = strlen(host2); h1_len = strlen(host); @@ -1318,16 +1365,16 @@ int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r) ap_hard_timeout("proxy connect", r); do { - i = connect(sock, (struct sockaddr *) addr, sizeof(struct sockaddr_in)); + i = connect(sock, (struct sockaddr *)addr, sizeof(struct sockaddr_in)); #if defined(WIN32) || defined(NETWARE) if (i == SOCKET_ERROR) errno = WSAGetLastError(); -#endif /* WIN32 */ +#endif /* WIN32 */ } while (i == -1 && errno == EINTR); if (i == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "proxy connect to %s port %d failed", - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port)); + "proxy connect to %s port %d failed", + inet_ntoa(addr->sin_addr), ntohs(addr->sin_port)); } ap_kill_timeout(r); @@ -1342,16 +1389,17 @@ int ap_proxy_send_hdr_line(void *p, const char *key, const char *value) { cache_req *c = (cache_req *)p; - if (key == NULL || value == NULL || value[0] == '\0') + if (key == NULL || value == NULL || value[0] == '\0') return 1; - if (c->fp != NULL && + if (c->fp != NULL && ap_bvputs(c->fp, key, ": ", value, CRLF, NULL) == -1) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, - "proxy: error writing header to %s", c->tempfile); - c = ap_proxy_cache_error(c); - return 0; /* no need to continue, it failed already */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, + "proxy: error writing header to %s", c->tempfile); + c = ap_proxy_cache_error(c); + return 0; /* no need to continue, it failed already */ } - return 1; /* tell ap_table_do() to continue calling us for more headers */ + return 1; /* tell ap_table_do() to continue calling us + * for more headers */ } /* send a text line to one or two BUFF's; return line length */ @@ -1366,7 +1414,8 @@ unsigned ap_proxy_bputs2(const char *data, BUFF *client, cache_req *cache) /* do a HTTP/1.1 age calculation */ time_t ap_proxy_current_age(cache_req *c, const time_t age_value) { - time_t apparent_age, corrected_received_age, response_delay, corrected_initial_age, resident_time, current_age; + time_t apparent_age, corrected_received_age, response_delay, corrected_initial_age, + resident_time, current_age; /* Perform an HTTP/1.1 age calculation. (RFC2616 13.2.3) */ @@ -1398,7 +1447,7 @@ BUFF *ap_proxy_open_cachefile(request_rec *r, char *filename) "proxy: error opening cache file %s", filename); else - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "File %s not found", filename); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "File %s not found", filename); } return cachefp; @@ -1431,21 +1480,45 @@ void ap_proxy_clear_connection(pool *p, table *headers) const char *name; char *next = ap_pstrdup(p, ap_table_get(headers, "Connection")); + /* Some proxies (Squid, ICS) use the non-standard "Proxy-Connection" header. */ ap_table_unset(headers, "Proxy-Connection"); - if (!next) - return; - while (*next) { - name = next; - while (*next && !ap_isspace(*next) && (*next != ',')) - ++next; - while (*next && (ap_isspace(*next) || (*next == ','))) { - *next = '\0'; - ++next; + if (next != NULL) { + while (*next) { + name = next; + while (*next && !ap_isspace(*next) && (*next != ',')) + ++next; + while (*next && (ap_isspace(*next) || (*next == ','))) { + *next = '\0'; + ++next; + } + ap_table_unset(headers, name); } - ap_table_unset(headers, name); + ap_table_unset(headers, "Connection"); } - ap_table_unset(headers, "Connection"); + + /* unset hop-by-hop headers defined in RFC2616 13.5.1 */ + ap_table_unset(headers,"Keep-Alive"); + /* + * XXX: @@@ FIXME: "Proxy-Authenticate" should IMO *not* be stripped + * because in a chain of proxies some "front" proxy might need + * proxy authentication, while a "back-end" proxy which needs none can + * simply pass the "Proxy-Authenticate" back to the client, and pass + * the client's "Proxy-Authorization" to the front-end proxy. + * (See the note in proxy_http.c for the "Proxy-Authorization" case.) + * + * MnKr 04/2002 + */ + ap_table_unset(headers,"Proxy-Authenticate"); + ap_table_unset(headers,"TE"); + ap_table_unset(headers,"Trailer"); + /* it is safe to just chop the transfer-encoding header + * here, because proxy doesn't support any other encodings + * to the backend other than chunked. + */ + ap_table_unset(headers,"Transfer-Encoding"); + ap_table_unset(headers,"Upgrade"); + } /* overlay one table on another @@ -1467,7 +1540,7 @@ void ap_proxy_clear_connection(pool *p, table *headers) */ int ap_proxy_table_replace(table *base, table *overlay) { - table_entry *elts = (table_entry *) overlay->a.elts; + table_entry *elts = (table_entry *)overlay->a.elts; int i, q = 0; const char *val; @@ -1490,54 +1563,96 @@ int ap_proxy_table_replace(table *base, table *overlay) return q; } -/* unmerge an element in the table */ -void ap_proxy_table_unmerge(pool *p, table *t, char *key) -{ - long int offset = 0; - long int count = 0; - char *value = NULL; +/* read the response line + * This function reads a single line of response from the server, + * and returns a status code. + * It also populates the request_rec with the resultant status, and + * returns backasswards status (HTTP/0.9). + */ +int ap_proxy_read_response_line(BUFF *f, request_rec *r, char *buffer, int size, int *backasswards, int *major, int *minor) { - /* get the value to unmerge */ - const char *initial = ap_table_get(t, key); - if (!initial) { - return; + long len; + + len = ap_getline(buffer, size-1, f, 0); + if (len == -1) { + ap_bclose(f); + ap_kill_timeout(r); + 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"); } - value = ap_pstrdup(p, initial); - /* remove the value from the headers */ - ap_table_unset(t, key); + /* + * Is it an HTTP/1 response? Do some sanity checks on the response. (This + * is buggy if we ever see an HTTP/1.10) + */ + if (ap_checkmask(buffer, "HTTP/#.# ###*")) { - /* find each comma */ - while (value[count]) { - if (value[count] == ',') { - value[count] = 0; - ap_table_add(t, key, value + offset); - offset = count + 1; + if (2 != sscanf(buffer, "HTTP/%u.%u", major, minor)) { + /* if no response, default to HTTP/1.1 - is this correct? */ + *major = 1; + *minor = 1; } - count++; + + /* If not an HTTP/1 message */ + if (*major < 1) { + ap_bclose(f); + ap_kill_timeout(r); + return HTTP_BAD_GATEWAY; + } + *backasswards = 0; + + buffer[12] = '\0'; + r->status = atoi(&buffer[9]); + buffer[12] = ' '; + r->status_line = ap_pstrdup(r->pool, &buffer[9]); + + /* if the response was 100 continue, soak up any headers */ + if (r->status == 100) { + ap_proxy_read_headers(r, buffer, size, f); + } + + } + else { + + /* an http/0.9 response */ + *backasswards = 1; + r->status = 200; + r->status_line = "200 OK"; + *major = 0; + *minor = 9; + } - ap_table_add(t, key, value + offset); + + return OK; + } + #if defined WIN32 static DWORD tls_index; -BOOL WINAPI DllMain (HINSTANCE dllhandle, DWORD reason, LPVOID reserved) +BOOL WINAPI DllMain(HINSTANCE dllhandle, DWORD reason, LPVOID reserved) { LPVOID memptr; switch (reason) { case DLL_PROCESS_ATTACH: tls_index = TlsAlloc(); - case DLL_THREAD_ATTACH: /* intentional no break */ - TlsSetValue (tls_index, malloc (sizeof (struct per_thread_data))); + case DLL_THREAD_ATTACH: /* intentional no break */ + TlsSetValue(tls_index, malloc(sizeof(struct per_thread_data))); break; case DLL_THREAD_DETACH: - memptr = TlsGetValue (tls_index); + memptr = TlsGetValue(tls_index); if (memptr) { - free (memptr); - TlsSetValue (tls_index, 0); + free(memptr); + TlsSetValue(tls_index, 0); } break; } @@ -1551,7 +1666,7 @@ static struct per_thread_data *get_per_thread_data(void) { #if defined(WIN32) - return (struct per_thread_data *) TlsGetValue (tls_index); + return (struct per_thread_data *)TlsGetValue(tls_index); #else diff --git a/usr.sbin/httpd/src/modules/ssl/libssl.version b/usr.sbin/httpd/src/modules/ssl/libssl.version index bb603d2de18..2cdfab25e0a 100644 --- a/usr.sbin/httpd/src/modules/ssl/libssl.version +++ b/usr.sbin/httpd/src/modules/ssl/libssl.version @@ -1 +1 @@ -mod_ssl/2.8.8-1.3.24 +mod_ssl/2.8.10-1.3.26 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 dec62cc17cf..9ed29b7b65f 100644 --- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_init.c +++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_engine_init.c,v 1.18 2002/07/15 09:40:49 henning Exp $ */ +/* $OpenBSD: ssl_engine_init.c,v 1.19 2002/07/19 21:31:16 henning Exp $ */ /* _ _ ** _ __ ___ ___ __| | ___ ___| | mod_ssl @@ -934,7 +934,7 @@ void ssl_init_CheckServers(server_rec *sm, pool *p) } /* - * Give out warnings when more than one SSL-aware virtual server uses the + * Give out warnings if 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). @@ -946,6 +946,8 @@ void ssl_init_CheckServers(server_rec *sm, pool *p) sc = mySrvConfig(s); if (!sc->bEnabled) continue; + if (s->addrs == NULL) + 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) { @@ -1007,11 +1009,14 @@ STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s, pool *pp, char *cpCAfile if (cpCAfile != NULL) { sk = SSL_load_client_CA_file(cpCAfile); for (n = 0; sk != NULL && n < sk_X509_NAME_num(sk); n++) { + X509_NAME *name = sk_X509_NAME_value(sk, n); ssl_log(s, SSL_LOG_TRACE, "CA certificate: %s", - X509_NAME_oneline(sk_X509_NAME_value(sk, n), buf, sizeof(buf))); - if (sk_X509_NAME_find(skCAList, sk_X509_NAME_value(sk, n)) < 0) - sk_X509_NAME_push(skCAList, sk_X509_NAME_value(sk, n)); + X509_NAME_oneline(name, buf, sizeof(buf))); + if (sk_X509_NAME_find(skCAList, name) < 0) + sk_X509_NAME_push(skCAList, name); /* will be freed when skCAList is */ + else + X509_NAME_free(name); } sk_X509_NAME_free(sk); } @@ -1025,11 +1030,14 @@ STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s, pool *pp, char *cpCAfile cp = ap_pstrcat(p, cpCApath, "/", direntry->d_name, NULL); sk = SSL_load_client_CA_file(cp); for (n = 0; sk != NULL && n < sk_X509_NAME_num(sk); n++) { + X509_NAME *name = sk_X509_NAME_value(sk, n); ssl_log(s, SSL_LOG_TRACE, "CA certificate: %s", - X509_NAME_oneline(sk_X509_NAME_value(sk, n), buf, sizeof(buf))); - if (sk_X509_NAME_find(skCAList, sk_X509_NAME_value(sk, n)) < 0) - sk_X509_NAME_push(skCAList, sk_X509_NAME_value(sk, n)); + X509_NAME_oneline(name, buf, sizeof(buf))); + if (sk_X509_NAME_find(skCAList, name) < 0) + sk_X509_NAME_push(skCAList, name); + else + X509_NAME_free(name); } sk_X509_NAME_free(sk); } 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 594a0503479..e5a9c5eb6a3 100644 --- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_kernel.c +++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_kernel.c @@ -957,17 +957,28 @@ int ssl_hook_Access(request_rec *r) /* 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); + cert = SSL_get_peer_certificate(ssl); + if (certstack == NULL && cert != NULL) { + /* client cert is in the session cache, but there is + no chain, since ssl3_get_client_certificate() + sk_X509_shift'ed the peer cert out of the chain. + So we put it back here for the purpose of quick + renegotiation. */ + certstack = sk_new_null(); + sk_X509_push(certstack, cert); + } 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); + if (cert == NULL) + cert = sk_X509_value(certstack, 0); + + if ((certstore = SSL_CTX_get_cert_store(ctx)) == NULL) { + ssl_log(r->server, SSL_LOG_ERROR, "Cannot find certificate storage"); + return FORBIDDEN; + } X509_STORE_CTX_init(&certstorectx, certstore, cert, certstack); depth = SSL_get_verify_depth(ssl); if (depth >= 0) @@ -979,6 +990,10 @@ int ssl_hook_Access(request_rec *r) "Re-negotiation verification step failed"); SSL_set_verify_result(ssl, certstorectx.error); X509_STORE_CTX_cleanup(&certstorectx); + if (SSL_get_peer_cert_chain(ssl) != certstack) { + /* created by us, so free it */ + sk_X509_pop_free(certstack, X509_free); + } } else { /* do a full renegotiation */ @@ -1132,15 +1147,19 @@ int ssl_hook_Auth(request_rec *r) * ("/XX=YYY/XX=YYY/..") as the username and "password" as the * password. */ - if ((cpAL = ap_table_get(r->headers_in, "Authorization")) != NULL) { + if ( ap_is_initial_req(r) + && (cpAL = ap_table_get(r->headers_in, "Authorization")) != NULL) { if (strcEQ(ap_getword(r->pool, &cpAL, ' '), "Basic")) { while (*cpAL == ' ' || *cpAL == '\t') cpAL++; cpAL = ap_pbase64decode(r->pool, cpAL); cpUN = ap_getword_nulls(r->pool, &cpAL, ':'); cpPW = cpAL; - if (cpUN[0] == '/' && strEQ(cpPW, "password")) + if (cpUN[0] == '/' && strEQ(cpPW, "password")) { + ssl_log(r->server, SSL_LOG_WARN, + "real Basic Authentication with DN \"%s\" and fake password attempted", cpUN); return FORBIDDEN; + } } } 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 8631c86d743..37af9c16680 100644 --- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_rand.c +++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_rand.c @@ -101,7 +101,11 @@ int ssl_rand_seed(server_rec *s, pool *p, ssl_rsctx_t nCtx, char *prefix) /* * seed in contents of an external file */ +#ifdef WIN32 + if ((fp = ap_pfopen(p, pRandSeed->cpPath, "rb")) == NULL) +#else if ((fp = ap_pfopen(p, pRandSeed->cpPath, "r")) == NULL) +#endif continue; nDone += ssl_rand_feedfp(p, fp, pRandSeed->nBytes); ap_pfclose(p, fp); @@ -155,7 +159,8 @@ int ssl_rand_seed(server_rec *s, pool *p, ssl_rsctx_t nCtx, char *prefix) * seed in extract data from the current scoreboard */ if (ap_scoreboard_image != NULL && SCOREBOARD_SIZE > 16) { - m = ((SCOREBOARD_SIZE / 2) - 1); + if ((m = ((SCOREBOARD_SIZE / 2) - 1)) > 1024) + m = 1024; n = ssl_rand_choosenum(0, m); RAND_seed(((unsigned char *)ap_scoreboard_image)+n, m); nDone += m; @@ -167,7 +172,7 @@ int ssl_rand_seed(server_rec *s, pool *p, ssl_rsctx_t nCtx, char *prefix) #if SSL_LIBRARY_VERSION >= 0x00905100 if (RAND_status() == 0) - ssl_log(s, SSL_LOG_WARN, "%sPRNG still contains not sufficient entropy!", prefix); + ssl_log(s, SSL_LOG_WARN, "%sPRNG still contains insufficient entropy!", prefix); #endif return nDone; } 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 e1dbfdfbc8e..a6013cdd44c 100644 --- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_vars.c +++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_vars.c @@ -411,7 +411,11 @@ static const struct { { "G", NID_givenName }, { "S", NID_surname }, { "D", NID_description }, +#if SSL_LIBRARY_VERSION >= 0x00907000 + { "UID", NID_x500UniqueIdentifier }, +#else { "UID", NID_uniqueIdentifier }, +#endif { "Email", NID_pkcs9_emailAddress }, { NULL, 0 } }; diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_scache_shmcb.c b/usr.sbin/httpd/src/modules/ssl/ssl_scache_shmcb.c index ef3c2c1989a..1cf5816dfd6 100644 --- a/usr.sbin/httpd/src/modules/ssl/ssl_scache_shmcb.c +++ b/usr.sbin/httpd/src/modules/ssl/ssl_scache_shmcb.c @@ -63,8 +63,8 @@ /* * This shared memory based SSL session cache implementation was - * originally written by Geoff Thorpe <geoff@eu.c2.net> for C2Net Europe - * and as a contribution to Ralf Engelschall's mod_ssl project. + * originally written by Geoff Thorpe <geoff@geoffthorpe.net> for C2Net + * Europe and as a contribution to Ralf Engelschall's mod_ssl project. */ /* diff --git a/usr.sbin/httpd/src/modules/standard/mod_cgi.c b/usr.sbin/httpd/src/modules/standard/mod_cgi.c index d05786eec19..c0c2307df95 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_cgi.c +++ b/usr.sbin/httpd/src/modules/standard/mod_cgi.c @@ -240,7 +240,7 @@ static int log_script(request_rec *r, cgi_server_conf * conf, int ret, fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val); } if ((r->method_number == M_POST || r->method_number == M_PUT) - && *dbuf) { + && dbuf && *dbuf) { fprintf(f, "\n%s\n", dbuf); } 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 9c512a597e7..420807cabf4 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_log_config.c +++ b/usr.sbin/httpd/src/modules/standard/mod_log_config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mod_log_config.c,v 1.11 2002/07/17 11:19:10 henning Exp $ */ +/* $OpenBSD: mod_log_config.c,v 1.12 2002/07/19 21:31:16 henning Exp $ */ /* ==================================================================== * The Apache Software License, Version 1.1 @@ -297,8 +297,8 @@ static const char *constant_item(request_rec *dummy, char *stuff) static const char *log_remote_host(request_rec *r, char *a) { - return ap_get_remote_host(r->connection, r->per_dir_config, - REMOTE_NAME); + return ap_escape_logitem(r->pool, ap_get_remote_host(r->connection, r->per_dir_config, + REMOTE_NAME)); } static const char *log_remote_address(request_rec *r, char *a) @@ -313,7 +313,7 @@ static const char *log_local_address(request_rec *r, char *a) static const char *log_remote_logname(request_rec *r, char *a) { - return ap_get_remote_logname(r); + return ap_escape_logitem(r->pool, ap_get_remote_logname(r)); } static const char *log_remote_user(request_rec *r, char *a) @@ -326,6 +326,8 @@ static const char *log_remote_user(request_rec *r, char *a) else if (strlen(rvalue) == 0) { rvalue = "\"\""; } + else + rvalue = ap_escape_logitem(r->pool, rvalue); return rvalue; } @@ -336,10 +338,12 @@ static const char *log_request_line(request_rec *r, char *a) * (note the truncation before the protocol string for HTTP/0.9 requests) * (note also that r->the_request contains the unmodified request) */ - return (r->parsed_uri.password) ? ap_pstrcat(r->pool, r->method, " ", + return ap_escape_logitem(r->pool, + (r->parsed_uri.password) ? ap_pstrcat(r->pool, r->method, " ", ap_unparse_uri_components(r->pool, &r->parsed_uri, 0), r->assbackwards ? NULL : " ", r->protocol, NULL) - : r->the_request; + : r->the_request + ); } static const char *log_request_file(request_rec *r, char *a) @@ -348,19 +352,20 @@ static const char *log_request_file(request_rec *r, char *a) } static const char *log_request_uri(request_rec *r, char *a) { - return r->uri; + return ap_escape_logitem(r->pool, r->uri); } static const char *log_request_method(request_rec *r, char *a) { - return r->method; + return ap_escape_logitem(r->pool, r->method); } static const char *log_request_protocol(request_rec *r, char *a) { - return r->protocol; + return ap_escape_logitem(r->pool, r->protocol); } static const char *log_request_query(request_rec *r, char *a) { - return (r->args != NULL) ? ap_pstrcat(r->pool, "?", r->args, NULL) + return (r->args != NULL) ? ap_pstrcat(r->pool, "?", + ap_escape_logitem(r->pool, r->args), NULL) : ""; } static const char *log_status(request_rec *r, char *a) @@ -395,7 +400,7 @@ static const char *log_bytes_sent(request_rec *r, char *a) static const char *log_header_in(request_rec *r, char *a) { - return ap_table_get(r->headers_in, a); + return ap_escape_logitem(r->pool, ap_table_get(r->headers_in, a)); } static const char *log_header_out(request_rec *r, char *a) @@ -476,6 +481,7 @@ static const char *log_child_pid(request_rec *r, char *a) { return ap_psprintf(r->pool, "%ld", (long) getpid()); } + static const char *log_connection_status(request_rec *r, char *a) { if (r->connection->aborted) @@ -488,6 +494,7 @@ static const char *log_connection_status(request_rec *r, char *a) return "-"; } + /***************************************************************** * * Parsing the log format string 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 77e1f1b8cc9..2ec733f77c4 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_mime_magic.c +++ b/usr.sbin/httpd/src/modules/standard/mod_mime_magic.c @@ -1110,7 +1110,7 @@ static int parse(server_rec *serv, pool *p, char *l, int lineno) } /* get offset, then skip over it */ - m->offset = (int) strtol(l, &t, 0); + m->offset = (int) ap_strtol(l, &t, 0); if (l == t) { ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, serv, MODNAME ": offset %s invalid", l); @@ -1145,7 +1145,7 @@ static int parse(server_rec *serv, pool *p, char *l, int lineno) if (*l == '+' || *l == '-') l++; if (ap_isdigit((unsigned char) *l)) { - m->in.offset = strtol(l, &t, 0); + m->in.offset = ap_strtol(l, &t, 0); if (*s == '-') m->in.offset = -m->in.offset; } @@ -1233,7 +1233,7 @@ static int parse(server_rec *serv, pool *p, char *l, int lineno) /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */ if (*l == '&') { ++l; - m->mask = signextend(serv, m, strtol(l, &l, 0)); + m->mask = signextend(serv, m, ap_strtol(l, &l, 0)); } else m->mask = ~0L; @@ -1311,7 +1311,7 @@ static int getvalue(server_rec *s, struct magic *m, char **p) m->vallen = slen; } else if (m->reln != 'x') - m->value.l = signextend(s, m, strtol(*p, p, 0)); + m->value.l = signextend(s, m, ap_strtol(*p, p, 0)); return 0; } diff --git a/usr.sbin/httpd/src/modules/standard/mod_rewrite.c b/usr.sbin/httpd/src/modules/standard/mod_rewrite.c index 39bfbc67a64..f138b546c52 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_rewrite.c +++ b/usr.sbin/httpd/src/modules/standard/mod_rewrite.c @@ -1220,7 +1220,7 @@ static int hook_uri2file(request_rec *r) rewritelog(r, 2, "local path result: %s", r->filename); /* the filename has to start with a slash! */ - if (r->filename[0] != '/') { + if (!ap_os_is_path_absolute(r->filename)) { return BAD_REQUEST; } @@ -1505,7 +1505,7 @@ static int hook_fixup(request_rec *r) } /* the filename has to start with a slash! */ - if (r->filename[0] != '/') { + if (!ap_os_is_path_absolute(r->filename)) { return BAD_REQUEST; } @@ -1983,7 +1983,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p, * location, i.e. if it's not starting with either a slash * or a fully qualified URL scheme. */ - if (prefixstrip && r->filename[0] != '/' + if (prefixstrip && !ap_os_is_path_absolute(r->filename) && !is_absolute_uri(r->filename)) { rewritelog(r, 3, "[per-dir %s] add per-dir prefix: %s -> %s%s", perdir, r->filename, perdir, r->filename); @@ -2070,7 +2070,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p, * not start with a slash. Here we add again the initially * stripped per-directory prefix. */ - if (prefixstrip && r->filename[0] != '/') { + if (prefixstrip && !ap_os_is_path_absolute(r->filename)) { rewritelog(r, 3, "[per-dir %s] add per-dir prefix: %s -> %s%s", perdir, r->filename, perdir, r->filename); r->filename = ap_pstrcat(r->pool, perdir, r->filename, NULL); diff --git a/usr.sbin/httpd/src/os/netware/ApacheCore.imp b/usr.sbin/httpd/src/os/netware/ApacheCore.imp index a1aa7f758bf..2e70a60aa90 100644 --- a/usr.sbin/httpd/src/os/netware/ApacheCore.imp +++ b/usr.sbin/httpd/src/os/netware/ApacheCore.imp @@ -418,3 +418,5 @@ ap_update_child_status, ap_sendwithtimeout, ap_recvwithtimeout, + ap_getline, + ap_get_chunk_size, diff --git a/usr.sbin/httpd/src/os/netware/mod_log_nw.c b/usr.sbin/httpd/src/os/netware/mod_log_nw.c index 99a93a24d19..f5718746f13 100644 --- a/usr.sbin/httpd/src/os/netware/mod_log_nw.c +++ b/usr.sbin/httpd/src/os/netware/mod_log_nw.c @@ -231,10 +231,8 @@ typedef struct { array_header *config_logs; array_header *server_config_logs; table *formats; -#ifdef NETWARE int rotatedaily; int rotateinterval; -#endif } multi_log_state; /* @@ -256,9 +254,7 @@ typedef struct { int outcnt; char outbuf[LOG_BUFSIZE]; #endif -#ifdef NETWARE time_t time_jump; -#endif } config_log_state; /* @@ -810,7 +806,6 @@ static int config_log_transaction(request_rec *r, config_log_state *cls, int len = 0; array_header *format; char *envar; -#ifdef NETWARE int log_fd; multi_log_state *mls = ap_get_module_config(r->server->module_config,&config_log_module); @@ -844,7 +839,6 @@ static int config_log_transaction(request_rec *r, config_log_state *cls, close (log_fd); } } -#endif if (cls->fname == NULL) { return DECLINED; @@ -969,10 +963,8 @@ static void *make_config_log_state(pool *p, server_rec *s) mls->server_config_logs = NULL; mls->formats = ap_make_table(p, 4); ap_table_setn(mls->formats, "CLF", DEFAULT_LOG_FORMAT); -#ifdef NETWARE mls->rotatedaily = 0; mls->rotateinterval = 0; -#endif return mls; } @@ -988,14 +980,12 @@ static void *merge_config_log_state(pool *p, void *basev, void *addv) multi_log_state *base = (multi_log_state *) basev; multi_log_state *add = (multi_log_state *) addv; -#ifdef NETWARE if (add->rotatedaily==0) { add->rotatedaily=base->rotatedaily; } if (add->rotateinterval==0) { add->rotateinterval=base->rotateinterval; } -#endif add->server_config_logs = base->config_logs; if (!add->default_format) { @@ -1080,7 +1070,6 @@ static const char *set_cookie_log(cmd_parms *cmd, void *dummy, char *fn) return add_custom_log(cmd, dummy, fn, "%{Cookie}n \"%r\" %t", NULL); } -#ifdef NETWARE static const char *set_rotate_log_daily(cmd_parms *cmd, void *dummy, int arg) { multi_log_state *mls = ap_get_module_config(cmd->server->module_config, @@ -1108,7 +1097,6 @@ static const char *set_rotate_log_interval(cmd_parms *cmd, void *dummy, char *ar mls->rotateinterval = interval; return NULL; } -#endif static const command_rec config_log_cmds[] = { @@ -1121,12 +1109,10 @@ static const command_rec config_log_cmds[] = "a log format string (see docs) and an optional format name"}, {"CookieLog", set_cookie_log, NULL, RSRC_CONF, TAKE1, "the filename of the cookie log"}, -#ifdef NETWARE {"LogRotateDaily", set_rotate_log_daily, NULL, RSRC_CONF, FLAG, "rotate logs daily (On:Off)"}, {"LogRotateInterval", set_rotate_log_interval, NULL, RSRC_CONF, TAKE1, "rotate logs every NNN minutes"}, -#endif {NULL} }; @@ -1152,7 +1138,6 @@ static config_log_state *open_config_log(server_rec *s, pool *p, cls->log_fd = ap_piped_log_write_fd(pl); } else { -#ifdef NETWARE char * fname; struct tm *time_tmp; time_t time_now; @@ -1175,9 +1160,6 @@ static config_log_state *open_config_log(server_rec *s, pool *p, } else { fname = ap_server_root_relative(p, cls->fname); } -#else - char *fname = ap_server_root_relative(p, cls->fname); -#endif if ((cls->log_fd = ap_popenf(p, fname, xfer_flags, xfer_mode)) < 0) { ap_log_error(APLOG_MARK, APLOG_ERR, s, diff --git a/usr.sbin/httpd/src/os/netware/os.h b/usr.sbin/httpd/src/os/netware/os.h index 55153a13310..be95fe7b12e 100644 --- a/usr.sbin/httpd/src/os/netware/os.h +++ b/usr.sbin/httpd/src/os/netware/os.h @@ -126,6 +126,11 @@ typedef int tid_t; #define mktemp(s) tmpnam(s) #define _getch getch +/* Watcom reports that ERANGE is returned properly for any out of bounds + * conditions, with a MIN/MAX_LONG value. This should be safe. + */ +#define ap_strtol strtol + #define opendir_411(p) os_opendir(p) #define opendir(p) os_opendir(p) DIR *os_opendir (const char *pathname); diff --git a/usr.sbin/httpd/src/os/netware/test_char.h b/usr.sbin/httpd/src/os/netware/test_char.h index bd26df220aa..46212b121d1 100644 --- a/usr.sbin/httpd/src/os/netware/test_char.h +++ b/usr.sbin/httpd/src/os/netware/test_char.h @@ -1,21 +1,42 @@ /* this file is automatically generated by gen_test_char, do not edit */ -#define T_ESCAPE_SHELL_CMD (1) -#define T_ESCAPE_PATH_SEGMENT (2) -#define T_OS_ESCAPE_PATH (4) -#define T_HTTP_TOKEN_STOP (8) +#define T_ESCAPE_SHELL_CMD 0x01 /* chars with special meaning in the shell */ +#define T_ESCAPE_PATH_SEGMENT 0x02 /* find path segment, as defined in RFC1808 */ +#define T_OS_ESCAPE_PATH 0x04 /* escape characters in a path or uri */ +#define T_HTTP_TOKEN_STOP 0x08 /* find http tokens, as defined in RFC2616 */ +#define T_ESCAPE_LOGITEM 0x10 /* filter what should go in the log file */ static const unsigned char test_char_table[256] = { - 0,14,14,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,14,14, - 14,14,14,14,14,14,14,14,14,14,14,14,14,0,7,6,1,6,1,1, - 9,9,1,0,8,0,0,10,0,0,0,0,0,0,0,0,0,0,8,15, - 15,8,15,15,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,15,15,15,7,0,7,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,15,7,15,1,14,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 + 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, /*0x00...0x07*/ + 0x1e, 0x1e, 0x1f, 0x1e, 0x1e, 0x1f, 0x1e, 0x1e, /*0x08...0x0f*/ + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, /*0x10...0x17*/ + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, /*0x18...0x1f*/ + 0x0e, 0x00, 0x17, 0x06, 0x01, 0x07, 0x01, 0x01, /*0x20...0x27*/ + 0x09, 0x09, 0x01, 0x00, 0x08, 0x00, 0x00, 0x0a, /*0x28...0x2f*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x30...0x37*/ + 0x00, 0x00, 0x08, 0x0f, 0x0f, 0x08, 0x0f, 0x0f, /*0x38...0x3f*/ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x40...0x47*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x48...0x4f*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x50...0x57*/ + 0x00, 0x00, 0x00, 0x0f, 0x1f, 0x0f, 0x07, 0x00, /*0x58...0x5f*/ + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x60...0x67*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x68...0x6f*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x70...0x77*/ + 0x00, 0x00, 0x00, 0x0f, 0x07, 0x0f, 0x01, 0x1e, /*0x78...0x7f*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0x80...0x87*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0x88...0x8f*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0x90...0x97*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0x98...0x9f*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0xa0...0xa7*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0xa8...0xaf*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0xb0...0xb7*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0xb8...0xbf*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0xc0...0xc7*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0xc8...0xcf*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0xd0...0xd7*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0xd8...0xdf*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0xe0...0xe7*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0xe8...0xef*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /*0xf0...0xf7*/ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16 /*0xf8...0xff*/ + }; diff --git a/usr.sbin/httpd/src/os/os2/os.h b/usr.sbin/httpd/src/os/os2/os.h index 4ce97ce584e..5a37e4e764f 100644 --- a/usr.sbin/httpd/src/os/os2/os.h +++ b/usr.sbin/httpd/src/os/os2/os.h @@ -47,6 +47,9 @@ char *ap_os_error_message(int err); #define HAVE_ISINF #define HAVE_ISNAN +/* strtol() correctly returns ERANGE on overflow, use it */ +#define ap_strtol strtol + /* Dynamic loading functions */ #define ap_os_dso_handle_t unsigned long void ap_os_dso_init(void); diff --git a/usr.sbin/httpd/src/os/tpf/os.c b/usr.sbin/httpd/src/os/tpf/os.c index dadd9534d58..b7aefc19e1a 100644 --- a/usr.sbin/httpd/src/os/tpf/os.c +++ b/usr.sbin/httpd/src/os/tpf/os.c @@ -75,6 +75,7 @@ static TPF_FD_LIST *tpf_fds = NULL; void *tpf_shm_static_ptr = NULL; unsigned short zinet_model; +char *argv_ptr = NULL; static FILE *sock_fp; @@ -394,7 +395,7 @@ pid_t os_fork(server_rec *s, int slot) 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"; + fork_input.parm_data = argv_ptr; #ifdef TPF_FORK_EXTENDED return tpf_fork(&fork_input, NULL, NULL); #else @@ -447,25 +448,25 @@ void ap_tpf_zinet_checks(int standalone, int os_check_server(char *server) { int *current_acn; - if (zinet_model == INETD_IDCF_MODEL_NOLISTEN) { - /* if NOLISTEN model, check with ZINET for status */ - if (inetd_getServerStatus(server) == INETD_SERVER_STATUS_INACTIVE) { - return 1; - } - /* and check that program activation number hasn't changed */ + /* check that the program activation number hasn't changed */ current_acn = (int *)cinfc_fast(CINFC_CMMACNUM); if (ecbp2()->ce2acn != *current_acn) { - return 1; + return 1; /* shutdown */ } - } else { - /* if DAEMON model, just make sure parent is still around */ + /* check our InetD status */ + if (inetd_getServerStatus(server) != INETD_SERVER_STATUS_ACTIVE) { + return 1; /* shutdown */ + } + + /* if DAEMON model, make sure parent is still around */ + if (zinet_model == INETD_IDCF_MODEL_DAEMON) { if (getppid() == 1) { - return 1; + return 1; /* shutdown */ } } - return 0; + return 0; /* keep on running... */ } void os_note_additional_cleanups(pool *p, int sd) { @@ -479,6 +480,23 @@ void os_note_additional_cleanups(pool *p, int sd) { fcntl(sd,F_SETFD,FD_CLOEXEC); } +void ap_tpf_save_argv(int argc, char **argv) { + + int i, len = 3; /* 3 for "-x " */ + + for (i = 1; i < argc; i++) { /* find len for calloc */ + len += strlen (argv[i]); + ++len; /* 1 for blank */ + } + + argv_ptr = malloc(len + 1); + strcpy(argv_ptr, "-x"); + for (i = 1; i < argc; i++) { + strcat(argv_ptr, " "); + strcat(argv_ptr, argv[i]); + } +} + void os_tpf_child(APACHE_TPF_INPUT *input_parms) { tpf_child = 1; ap_my_generation = input_parms->generation; @@ -795,5 +813,9 @@ void show_os_specific_compile_settings(void) #ifdef TPF_HAVE_NSD printf(" -D TPF_HAVE_NSD\n"); #endif + +#ifdef HAVE_SYSLOG + printf(" -D HAVE_SYSLOG\n"); +#endif } diff --git a/usr.sbin/httpd/src/os/tpf/os.h b/usr.sbin/httpd/src/os/tpf/os.h index cf0b087186f..37f42d40a0d 100644 --- a/usr.sbin/httpd/src/os/tpf/os.h +++ b/usr.sbin/httpd/src/os/tpf/os.h @@ -76,6 +76,10 @@ #undef HAVE_ISNAN #endif +#ifdef HAVE_ISINF +#undef HAVE_ISINF +#endif + #if !defined(INLINE) && defined(USE_GNU_INLINE) /* Compiler supports inline, so include the inlineable functions as * part of the header @@ -193,6 +197,7 @@ extern int scoreboard_fd; #ifdef NSIG #undef NSIG #endif +void ap_tpf_save_argv(int argc, char **argv); /* various #defines for ServerType/ZINET model checks: */ diff --git a/usr.sbin/httpd/src/os/tpf/samples/linkhttp.jcl b/usr.sbin/httpd/src/os/tpf/samples/linkhttp.jcl index 0d7124f8560..bf64d233df1 100644 --- a/usr.sbin/httpd/src/os/tpf/samples/linkhttp.jcl +++ b/usr.sbin/httpd/src/os/tpf/samples/linkhttp.jcl @@ -24,70 +24,65 @@ //PLKED.OBJ10 DD PATH='/<your-path-here>/src/ap/ap_signal.o'
//PLKED.OBJ11 DD PATH='/<your-path-here>/src/ap/ap_slack.o'
//PLKED.OBJ12 DD PATH='/<your-path-here>/src/ap/ap_snprintf.o'
-//PLKED.OBJ13 DD PATH='/<your-path-here>/src/buildmark.o'
-//PLKED.OBJ14 DD PATH='/<your-path-here>/src/main/alloc.o'
-//PLKED.OBJ15 DD PATH='/<your-path-here>/src/main/buff.o'
-//PLKED.OBJ16 DD PATH='/<your-path-here>/src/main/http_config.o'
-//PLKED.OBJ17 DD PATH='/<your-path-here>/src/main/http_core.o'
-//PLKED.OBJ18 DD PATH='/<your-path-here>/src/main/http_log.o'
-//PLKED.OBJ19 DD PATH='/<your-path-here>/src/main/http_main.o'
-//PLKED.OBJ20 DD PATH='/<your-path-here>/src/main/http_protocol.o'
-//PLKED.OBJ21 DD PATH='/<your-path-here>/src/main/http_request.o'
-//PLKED.OBJ22 DD PATH='/<your-path-here>/src/main/http_vhost.o'
-//PLKED.OBJ23 DD PATH='/<your-path-here>/src/main/rfc1413.o'
-//PLKED.OBJ24 DD PATH='/<your-path-here>/src/main/util.o'
-//PLKED.OBJ25 DD PATH='/<your-path-here>/src/main/util_date.o'
-//PLKED.OBJ26 DD PATH='/<your-path-here>/src/main/util_md5.o'
-//PLKED.OBJ27 DD PATH='/<your-path-here>/src/main/util_script.o'
-//PLKED.OBJ28 DD PATH='/<your-path-here>/src/main/util_uri.o'
-//PLKED.OBJ29 DD PATH='/<your-path-here>/src/modules.o'
-//PLKED.OBJ30 DD PATH='/<your-path-here>/src/modules/standard/mod_acce\
+//PLKED.OBJ13 DD PATH='/<your-path-here>/src/ap/ap_strtol.o'
+//PLKED.OBJ14 DD PATH='/<your-path-here>/src/buildmark.o'
+//PLKED.OBJ15 DD PATH='/<your-path-here>/src/main/alloc.o'
+//PLKED.OBJ16 DD PATH='/<your-path-here>/src/main/buff.o'
+//PLKED.OBJ17 DD PATH='/<your-path-here>/src/main/http_config.o'
+//PLKED.OBJ18 DD PATH='/<your-path-here>/src/main/http_core.o'
+//PLKED.OBJ19 DD PATH='/<your-path-here>/src/main/http_log.o'
+//PLKED.OBJ20 DD PATH='/<your-path-here>/src/main/http_main.o'
+//PLKED.OBJ21 DD PATH='/<your-path-here>/src/main/http_protocol.o'
+//PLKED.OBJ22 DD PATH='/<your-path-here>/src/main/http_request.o'
+//PLKED.OBJ23 DD PATH='/<your-path-here>/src/main/http_vhost.o'
+//PLKED.OBJ24 DD PATH='/<your-path-here>/src/main/rfc1413.o'
+//PLKED.OBJ25 DD PATH='/<your-path-here>/src/main/util.o'
+//PLKED.OBJ26 DD PATH='/<your-path-here>/src/main/util_date.o'
+//PLKED.OBJ27 DD PATH='/<your-path-here>/src/main/util_md5.o'
+//PLKED.OBJ28 DD PATH='/<your-path-here>/src/main/util_script.o'
+//PLKED.OBJ29 DD PATH='/<your-path-here>/src/main/util_uri.o'
+//PLKED.OBJ30 DD PATH='/<your-path-here>/src/modules.o'
+//PLKED.OBJ31 DD PATH='/<your-path-here>/src/modules/standard/mod_acce\
// ss.o'
-//PLKED.OBJ31 DD PATH='/<your-path-here>/src/modules/standard/mod_acti\
+//PLKED.OBJ32 DD PATH='/<your-path-here>/src/modules/standard/mod_acti\
// ons.o'
-//PLKED.OBJ32 DD PATH='/<your-path-here>/src/modules/standard/mod_alia\
+//PLKED.OBJ33 DD PATH='/<your-path-here>/src/modules/standard/mod_alia\
// s.o'
-//PLKED.OBJ33 DD PATH='/<your-path-here>/src/modules/standard/mod_asis\
+//PLKED.OBJ34 DD PATH='/<your-path-here>/src/modules/standard/mod_asis\
// .o'
-//PLKED.OBJ34 DD PATH='/<your-path-here>/src/modules/standard/mod_auth\
+//PLKED.OBJ35 DD PATH='/<your-path-here>/src/modules/standard/mod_auth\
// .o'
-//PLKED.OBJ35 DD PATH='/<your-path-here>/src/modules/standard/mod_auto\
+//PLKED.OBJ36 DD PATH='/<your-path-here>/src/modules/standard/mod_auto\
// index.o'
-//PLKED.OBJ36 DD PATH='/<your-path-here>/src/modules/standard/mod_cgi.\
+//PLKED.OBJ37 DD PATH='/<your-path-here>/src/modules/standard/mod_cgi.\
// o'
-//PLKED.OBJ37 DD PATH='/<your-path-here>/src/modules/standard/mod_dir.\
+//PLKED.OBJ38 DD PATH='/<your-path-here>/src/modules/standard/mod_dir.\
// o'
-//PLKED.OBJ38 DD PATH='/<your-path-here>/src/modules/standard/mod_env.\
+//PLKED.OBJ39 DD PATH='/<your-path-here>/src/modules/standard/mod_env.\
// o'
-//PLKED.OBJ39 DD PATH='/<your-path-here>/src/modules/standard/mod_imap\
+//PLKED.OBJ40 DD PATH='/<your-path-here>/src/modules/standard/mod_imap\
// .o'
-//PLKED.OBJ40 DD PATH='/<your-path-here>/src/modules/standard/mod_incl\
+//PLKED.OBJ41 DD PATH='/<your-path-here>/src/modules/standard/mod_incl\
// ude.o'
-//PLKED.OBJ41 DD PATH='/<your-path-here>/src/modules/standard/mod_log_\
+//PLKED.OBJ42 DD PATH='/<your-path-here>/src/modules/standard/mod_log_\
// config.o'
-//PLKED.OBJ42 DD PATH='/<your-path-here>/src/modules/standard/mod_mime\
+//PLKED.OBJ43 DD PATH='/<your-path-here>/src/modules/standard/mod_mime\
// .o'
-//PLKED.OBJ43 DD PATH='/<your-path-here>/src/modules/standard/mod_nego\
+//PLKED.OBJ44 DD PATH='/<your-path-here>/src/modules/standard/mod_nego\
// tiation.o'
-//PLKED.OBJ44 DD PATH='/<your-path-here>/src/modules/standard/mod_sete\
+//PLKED.OBJ45 DD PATH='/<your-path-here>/src/modules/standard/mod_sete\
// nvif.o'
-//PLKED.OBJ45 DD PATH='/<your-path-here>/src/modules/standard/mod_stat\
+//PLKED.OBJ46 DD PATH='/<your-path-here>/src/modules/standard/mod_stat\
// us.o'
-//PLKED.OBJ46 DD PATH='/<your-path-here>/src/modules/standard/mod_user\
+//PLKED.OBJ47 DD PATH='/<your-path-here>/src/modules/standard/mod_user\
// dir.o'
-//PLKED.OBJ47 DD PATH='/<your-path-here>/src/os/tpf/cgetop.o'
-//PLKED.OBJ48 DD PATH='/<your-path-here>/src/os/tpf/os.o'
-//PLKED.OBJ49 DD PATH='/<your-path-here>/src/os/tpf/os-inline.o'
-//PLKED.OBJ50 DD PATH='/<your-path-here>/src/regex/regcomp.o'
-//PLKED.OBJ51 DD PATH='/<your-path-here>/src/regex/regerror.o'
-//PLKED.OBJ52 DD PATH='/<your-path-here>/src/regex/regexec.o'
-//PLKED.OBJ53 DD PATH='/<your-path-here>/src/regex/regfree.o'
-//PLKED.OBJ54 DD PATH='/<your-path-here>/src/lib/expat-lite/hashtable.\
-// o'
-//PLKED.OBJ55 DD PATH='/<your-path-here>/src/lib/expat-lite/xmlparse.o\
-// '
-//PLKED.OBJ56 DD PATH='/<your-path-here>/src/lib/expat-lite/xmlrole.o'
-//PLKED.OBJ57 DD PATH='/<your-path-here>/src/lib/expat-lite/xmltok.o'
+//PLKED.OBJ48 DD PATH='/<your-path-here>/src/os/tpf/cgetop.o'
+//PLKED.OBJ49 DD PATH='/<your-path-here>/src/os/tpf/os.o'
+//PLKED.OBJ50 DD PATH='/<your-path-here>/src/os/tpf/os-inline.o'
+//PLKED.OBJ51 DD PATH='/<your-path-here>/src/regex/regcomp.o'
+//PLKED.OBJ52 DD PATH='/<your-path-here>/src/regex/regerror.o'
+//PLKED.OBJ53 DD PATH='/<your-path-here>/src/regex/regexec.o'
+//PLKED.OBJ54 DD PATH='/<your-path-here>/src/regex/regfree.o'
//PLKED.SYSIN DD *
ORDER @@DLMHDR
INCLUDE OBJLIB(CSTRTD40)
@@ -145,9 +140,6 @@ INCLUDE OBJ52
INCLUDE OBJ53
INCLUDE OBJ54
- INCLUDE OBJ55
- INCLUDE OBJ56
- INCLUDE OBJ57
INCLUDE OBJLIB(CINET640)
/*
//*** WARNING *** NEVER change .LK to .OB in SYSLMOD!!!
diff --git a/usr.sbin/httpd/src/os/unix/os.c b/usr.sbin/httpd/src/os/unix/os.c index afccc315a98..3ee29642c49 100644 --- a/usr.sbin/httpd/src/os/unix/os.c +++ b/usr.sbin/httpd/src/os/unix/os.c @@ -111,7 +111,13 @@ void *ap_os_dso_load(const char *path) if (NSCreateObjectFileImageFromFile(path, &image) != NSObjectFileImageSuccess) return NULL; - handle = NSLinkModule(image, path, TRUE); +#if defined(NSLINKMODULE_OPTION_RETURN_ON_ERROR) && defined(NSLINKMODULE_OPTION_NONE) + handle = NSLinkModule(image, path, + NSLINKMODULE_OPTION_RETURN_ON_ERROR | + NSLINKMODULE_OPTION_NONE); +#else + handle = NSLinkModule(image, path, FALSE); +#endif NSDestroyObjectFileImage(image); return handle; diff --git a/usr.sbin/httpd/src/os/win32/mod_isapi.c b/usr.sbin/httpd/src/os/win32/mod_isapi.c index 0f502e275f9..0065e929065 100644 --- a/usr.sbin/httpd/src/os/win32/mod_isapi.c +++ b/usr.sbin/httpd/src/os/win32/mod_isapi.c @@ -825,7 +825,7 @@ static const char *isapi_cmd_readaheadbuffer(cmd_parms *cmd, void *config, return err; } - if (((val = strtol(arg, (char **) &err, 10)) <= 0) || *err) + if (((val = ap_strtol(arg, (char **) &err, 10)) <= 0) || *err) return "ISAPIReadAheadBuffer must be a legitimate value."; ReadAheadBuffer = val; diff --git a/usr.sbin/httpd/src/os/win32/os.h b/usr.sbin/httpd/src/os/win32/os.h index 442c5f5a90e..4cb1f65ff1d 100644 --- a/usr.sbin/httpd/src/os/win32/os.h +++ b/usr.sbin/httpd/src/os/win32/os.h @@ -172,6 +172,12 @@ every configuration function as __stdcall. #define NO_SLACK #include <stddef.h> +/* MSVC asserts that strtol "errno is set to ERANGE + * if overflow or underflow occurs" + * Ergo we can use the library strtol safely. + */ +#define ap_strtol strtol + #define NO_OTHER_CHILD #define NO_RELIABLE_PIPED_LOGS diff --git a/usr.sbin/httpd/src/support/ab.8 b/usr.sbin/httpd/src/support/ab.8 index dc86e902665..6183a534d16 100644 --- a/usr.sbin/httpd/src/support/ab.8 +++ b/usr.sbin/httpd/src/support/ab.8 @@ -291,8 +291,7 @@ will shift several thousands of milli-second responses by a considerable factor. This was further componded by a serious interger overrun which would for realistic run's (i.e. those longer than a few minutes) produce believable but totally -bogus results. Thanks to Sander Temme <sctemme@covalent.net> -for solving this riddle. +bogus results. Thanks to Sander Temme for solving this riddle. .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 d5967b22483..19862ab00b0 100644 --- a/usr.sbin/httpd/src/support/ab.c +++ b/usr.sbin/httpd/src/support/ab.c @@ -95,7 +95,7 @@ ** - Fixed serious int overflow issues which would cause realistic (longer ** than a few minutes) run's to have wrong (but believable) results. Added ** trapping of connection errors which influenced measurements. - ** Contributed by Sander Temme - <sctemme@covalent.net>, Early 2001 + ** Contributed by Sander Temme - Early 2001 ** */ /* @@ -161,7 +161,7 @@ #endif /* NO_APACHE_INCLUDES */ #ifdef USE_SSL -#if ((!(RSAREF)) && (!(SYSSSL))) +#if ((!defined(RSAREF)) && (!defined(SYSSSL))) /* Libraries on most systems.. */ #include <openssl/rsa.h> #include <openssl/crypto.h> @@ -255,6 +255,7 @@ char *gnuplot; /* GNUplot file */ char *csvperc; /* CSV Percentile file */ char url[1024]; char fullurl[1024]; +char colonport[1024]; 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 */ @@ -288,7 +289,7 @@ int err_response = 0; struct timeval start, endtime; /* global request (and its length) */ -char request[512]; +char request[1024]; int reqlen; /* one global throw-away buffer to read stuff into */ @@ -311,8 +312,9 @@ struct sockaddr_in server; /* server addr structure */ #endif static void close_connection(struct connection * c); -#if NO_WRITEV || USE_SSL -static void s_write(struct connection * c, char *buff, int len); +#if (defined(NO_WRITEV) || defined(USE_SSL)) +#define USE_S_WRITE +static int s_write(struct connection * c, char *buff, int len); #endif /* --------------------------------------------------------- */ @@ -342,12 +344,13 @@ static void write_request(struct connection * c) /* XXX this sucks - SSL mode and writev() do not mix * another artificial difference. */ -#if !NO_WRITEV && !USE_SSL +#ifndef USE_S_WRITE struct iovec out[2]; int outcnt = 1; #endif + int snd = 0; gettimeofday(&c->connect, 0); -#if !NO_WRITEV && !USE_SSL +#ifndef USE_S_WRITE out[0].iov_base = request; out[0].iov_len = reqlen; @@ -357,18 +360,28 @@ static void write_request(struct connection * c) outcnt = 2; totalposted += (reqlen + postlen); } - writev(c->fd, out, outcnt); + snd = writev(c->fd, out, outcnt); #else - s_write(c, request, reqlen); + snd = s_write(c, request, reqlen); if (posting > 0) { - s_write(c, postdata, postlen); - totalposted += (reqlen + postlen); + snd += s_write(c, postdata, postlen); + totalposted += (reqlen + postlen); } #endif - - c->state = STATE_READ; + if (snd < 0) { + bad++; + err_conn++; + close_connection(c); + return; + } else + if (snd != (reqlen + postlen)) { + /* We cannot cope with this. */ + fprintf(stderr,"The entire post RQ could not be transmitted to the socket.\n"); + exit(1); + } FD_SET(c->fd, &readbits); FD_CLR(c->fd, &writebits); + c->state = STATE_READ; gettimeofday(&c->endwrite, 0); } @@ -376,17 +389,18 @@ static void write_request(struct connection * c) /* Do actual data writing */ -#if NO_WRITEV || USE_SSL -static void s_write(struct connection * c, char *buff, int len) +#ifdef USE_S_WRITE +static int s_write(struct connection * c, char *buff, int len) { + int left = len; do { int n; -#if USE_SSL +#ifdef USE_SSL if (ssl) { - n = SSL_write(c->ssl, buff, len); + n = SSL_write(c->ssl, buff, left); if (n < 0) { int e = SSL_get_error(c->ssl, n); - /* XXXX propably wrong !!! */ + /* XXXX probably wrong !!! */ if ((e != SSL_ERROR_WANT_READ) && (e != SSL_ERROR_WANT_WRITE)) n = -1; else @@ -395,7 +409,7 @@ static void s_write(struct connection * c, char *buff, int len) } else #endif - n = ab_write(c->fd, buff, len); + n = ab_write(c->fd, buff, left); if (n < 0) { switch (errno) { @@ -405,9 +419,9 @@ static void s_write(struct connection * c, char *buff, int len) /* We've tried to write to a broken pipe. */ epipe++; close_connection(c); - return; + return len-left; default: -#if USE_SSL +#ifdef USE_SSL if (ssl) { fprintf(stderr,"Error writing: "); ERR_print_errors_fp(stderr); @@ -419,11 +433,13 @@ static void s_write(struct connection * c, char *buff, int len) } else if (n) { if (verbosity >= 3) - printf(" --> write(%x) %d (%d)\n", (unsigned char) buff[0], n, len); + printf(" --> write(%x) %d (%d)\n", (unsigned char) buff[0], n, left); buff += n; - len -= n; + left -= n; }; - } while (len > 0); + } while (left > 0); + + return len - left; } #endif @@ -623,7 +639,7 @@ static void output_results(void) /* * XXX: what is better; this hideous cast of the copare function; or * the four warnings during compile ? dirkx just does not know and - * hates both/ + * hates both */ qsort(stats, requests, sizeof(struct data), (int (*) (const void *, const void *)) compradre); @@ -865,12 +881,12 @@ static void start_connect(struct connection * c) c->fd = socket(AF_INET, SOCK_STREAM, 0); if (c->fd < 0) { what = "SOCKET"; - goto bad; + goto _bad; }; -#if USE_SSL +#ifdef USE_SSL /* - * XXXX move nonblocker - so that measnurement needs to have its OWN + * XXX move nonblocker - so that measnurement needs to have its OWN * state engine OR cannot be compared to http. */ if (!ssl) @@ -880,23 +896,17 @@ static void start_connect(struct connection * c) again: gettimeofday(&c->start, 0); if (connect(c->fd, (struct sockaddr *) & server, sizeof(server)) < 0) { - if (errno == EINPROGRESS) { - c->state = STATE_CONNECTING; - } - else { + if (errno != EINPROGRESS) { what = "CONNECT"; - goto bad; + goto _bad; }; } - else { - /* connected first time */ - c->state = STATE_CONNECTING; - } + c->state = STATE_CONNECTING; #ifdef USE_SSL - /* XX no proper freeing in error's */ + /* XXX no proper freeing in error's */ /* - * XXXX no proper choise of completely new connection or one which reuses + * XXX no proper choise of completely new connection or one which reuses * (older) session keys. Fundamentally unrealistic. */ if (ssl) { @@ -904,34 +914,35 @@ again: if (!(c->ssl = SSL_new(ctx))) { fprintf(stderr, "Failed to set up new SSL context "); ERR_print_errors_fp(stderr); - goto bad; + goto _bad; }; SSL_set_connect_state(c->ssl); if ((e = SSL_set_fd(c->ssl, c->fd)) == -1) { fprintf(stderr, "SSL fd init failed "); ERR_print_errors_fp(stderr); - goto bad; + goto _bad; }; if ((e = SSL_connect(c->ssl)) == -1) { fprintf(stderr, "SSL connect failed "); ERR_print_errors_fp(stderr); - goto bad; + goto _bad; }; if (verbosity >= 1) fprintf(stderr, "SSL connection OK: %s\n", SSL_get_cipher(c->ssl)); } #endif -#if USE_SSL +#ifdef USE_SSL if (ssl) nonblock(c->fd); #endif FD_SET(c->fd, &writebits); return; -bad: +_bad: ab_close(c->fd); err_conn++; - if (bad++ > 10) { + bad++; + if (bad > 10) { err("\nTest aborted after 10 failures\n\n"); } goto again; @@ -995,10 +1006,10 @@ static void read_connection(struct connection * c) char respcode[4]; /* 3 digits and null */ gettimeofday(&c->beginread, 0); -#if USE_SSL +#ifdef USE_SSL if (ssl) { r = SSL_read(c->ssl, buffer, sizeof(buffer)); - /* XXX fundamwentally worng .. */ + /* XXX fundamentally worng .. */ if (r < 0 && SSL_get_error(c->ssl, r) == SSL_ERROR_WANT_READ) { r = -1; errno = EAGAIN; @@ -1172,7 +1183,8 @@ static void test(void) fd_set sel_read, sel_except, sel_write; long i; int connectport; - char * url_on_request, * host; + char * connecthost; + char * url_on_request; /* There are four hostname's involved: * The 'hostname' from the URL, the @@ -1182,11 +1194,15 @@ static void test(void) */ if (isproxy) { /* Connect to proxyhost:proxyport - * And set Host: to the hostname of - * the proxy - whistl quoting the - * full URL in the GET/POST line. + * And set Host: to the hostname and + * if not default :port of the URL. + * See RFC2616 - $14.23. But then in + * $5.2.1 it says that the Host: field + * when passed on MUST be ignored. So + * perhaps we should NOT send any + * when we are proxying. */ - host = proxyhost; + connecthost = proxyhost; connectport = proxyport; url_on_request = fullurl; } @@ -1197,11 +1213,11 @@ static void test(void) * header; and do not quote a full * URL in the GET/POST line. */ - host = hostname; + connecthost = hostname; connectport = port; url_on_request = path; } - + if (!use_html) { printf("Benchmarking %s (be patient)%s", hostname, (heartbeatres ? "\n" : "...")); @@ -1210,10 +1226,11 @@ static void test(void) { /* get server information */ struct hostent *he; - he = gethostbyname(host); + he = gethostbyname(connecthost); if (!he) { char theerror[1024]; - sprintf(theerror, "Bad hostname: %s\n", host); + ap_snprintf(theerror, sizeof(theerror), + "Bad hostname: %s\n", connecthost); err(theerror); } server.sin_family = he->h_addrtype; @@ -1231,35 +1248,37 @@ static void test(void) /* setup request */ if (posting <= 0) { - sprintf(request, "%s %s HTTP/1.0\r\n" - "User-Agent: ApacheBench/%s\r\n" - "%s" "%s" "%s" - "Host: %s\r\n" - "Accept: */*\r\n" - "%s" "\r\n", - (posting == 0) ? "GET" : "HEAD", - url_on_request, - VERSION, - keepalive ? "Connection: Keep-Alive\r\n" : "", - cookie, auth, - host, hdrs); + ap_snprintf(request, sizeof(request), + "%s %s HTTP/1.0\r\n" + "User-Agent: ApacheBench/%s\r\n" + "%s" "%s" "%s" + "Host: %s%s\r\n" + "Accept: */*\r\n" + "%s" "\r\n", + (posting == 0) ? "GET" : "HEAD", + url_on_request, + VERSION, + keepalive ? "Connection: Keep-Alive\r\n" : "", + cookie, auth, + hostname,colonport, hdrs); } else { - sprintf(request, "POST %s HTTP/1.0\r\n" - "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", - url_on_request, - VERSION, - keepalive ? "Connection: Keep-Alive\r\n" : "", - cookie, auth, - host, postlen, - (content_type[0]) ? content_type : "text/plain", hdrs); + ap_snprintf(request, sizeof(request), + "POST %s HTTP/1.0\r\n" + "User-Agent: ApacheBench/%s\r\n" + "%s" "%s" "%s" + "Host: %s%s\r\n" + "Accept: */*\r\n" + "Content-length: %d\r\n" + "Content-type: %s\r\n" + "%s" + "\r\n", + url_on_request, + VERSION, + keepalive ? "Connection: Keep-Alive\r\n" : "", + cookie, auth, + hostname, colonport, postlen, + (content_type[0]) ? content_type : "text/plain", hdrs); } if (verbosity >= 2) @@ -1332,14 +1351,14 @@ static void test(void) static void copyright(void) { if (!use_html) { - printf("This is ApacheBench, Version %s\n", VERSION " <$Revision: 1.8 $> apache-1.3"); + printf("This is ApacheBench, Version %s\n", VERSION " <$Revision: 1.9 $> apache-1.3"); printf("Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n"); printf("Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/\n"); printf("\n"); } else { printf("<p>\n"); - printf(" This is ApacheBench, Version %s <i><%s></i> apache-1.3<br>\n", VERSION, "$Revision: 1.8 $"); + printf(" This is ApacheBench, Version %s <i><%s></i> apache-1.3<br>\n", VERSION, "$Revision: 1.9 $"); printf(" Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br>\n"); printf(" Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/<br>\n"); printf("</p>\n<p>\n"); @@ -1350,7 +1369,7 @@ static void copyright(void) static void usage(char *progname) { fprintf(stderr, "Usage: %s [options] [http" -#if USE_SSL +#ifdef USE_SSL "[s]" #endif "://]hostname[:port]/path\n", progname); @@ -1380,7 +1399,7 @@ static void usage(char *progname) fprintf(stderr, " -S Do not show confidence estimators and warnings.\n"); fprintf(stderr, " -g filename Output collected data to gnuplot format file.\n"); fprintf(stderr, " -e filename Output CSV file with percentages served\n"); -#if USE_SSL +#ifdef USE_SSL fprintf(stderr, " -s Use httpS instead of HTTP (SSL)\n"); #endif fprintf(stderr, " -h Display usage information (this message)\n"); @@ -1400,7 +1419,7 @@ static int parse_url(char * purl) if (strlen(purl) > 7 && strncmp(purl, "http://", 7) == 0) purl += 7; else -#if USE_SSL +#ifdef USE_SSL if (strlen(purl) > 8 && strncmp(purl, "https://", 8) == 0) { purl += 8; ssl = 1; @@ -1426,7 +1445,18 @@ static int parse_url(char * purl) strcpy(hostname, h); if (p != NULL) port = atoi(p); - return 0; + + if (( +#ifdef USE_SSL + (ssl != 0) && (port != 443)) || ((ssl == 0) && +#endif + (port != 80))) + { + ap_snprintf(colonport,sizeof(colonport),":%d",port); + } else { + colonport[0] = '\0'; + } + return 0; } /* ------------------------------------------------------- */ @@ -1479,12 +1509,12 @@ int main(int argc, char **argv) proxyhost[0] = '\0'; optind = 1; while ((c = getopt(argc, argv, "n:c:t:T:p:v:kVhwix:y:z:C:H:P:A:g:X:de:Sq" -#if USE_SSL +#ifdef USE_SSL "s" #endif )) > 0) { switch (c) { -#if USE_SSL +#ifdef USE_SSL case 's': ssl = 1; break; diff --git a/usr.sbin/httpd/src/support/apxs.pl b/usr.sbin/httpd/src/support/apxs.pl index efa8d7597e4..fd3dc92360d 100644 --- a/usr.sbin/httpd/src/support/apxs.pl +++ b/usr.sbin/httpd/src/support/apxs.pl @@ -112,6 +112,12 @@ my $opt_a = 0; my $opt_A = 0; my $opt_q = 0; +# default for DSO file extension +my $dso_ext = "so"; +if ($^O eq "cygwin") { + $dso_ext = "dll"; +} + # this subroutine is derived from Perl's getopts.pl with the enhancement of # the "+" metacharater at the format string to allow a list to be build by # subsequent occurance of the same option. @@ -270,6 +276,7 @@ if ($opt_g) { my $data = join('', <DATA>); $data =~ s|%NAME%|$name|sg; $data =~ s|%TARGET%|$CFG_TARGET|sg; + $data =~ s|%DSO_EXT%|$dso_ext|sg; my ($mkf, $src) = ($data =~ m|^(.+)-=#=-\n(.+)|s); @@ -340,14 +347,14 @@ if ($opt_c) { if ($opt_o eq '') { if ($#srcs > -1) { $dso_file = $srcs[0]; - $dso_file =~ s|\.[^.]+$|.so|; + $dso_file =~ s|\.[^.]+$|.$dso_ext|; } elsif ($#objs > -1) { $dso_file = $objs[0]; - $dso_file =~ s|\.[^.]+$|.so|; + $dso_file =~ s|\.[^.]+$|.$dso_ext|; } else { - $dso_file = "mod_unknown.so"; + $dso_file = "mod_unknown.$dso_ext"; } } else { @@ -452,7 +459,7 @@ if ($opt_i or $opt_e) { my @cmds = (); my $f; foreach $f (@args) { - if ($f !~ m|\.so$|) { + if ($f !~ m|\.$dso_ext$|) { print STDERR "apxs:Error: file $f is not a DSO\n"; exit(1); } @@ -592,20 +599,20 @@ APACHECTL=apachectl #LIB=-Lmy/lib/dir -lmylib # the default target -all: mod_%NAME%.so +all: mod_%NAME%.%DSO_EXT% # compile the DSO file -mod_%NAME%.so: mod_%NAME%.c +mod_%NAME%.%DSO_EXT%: mod_%NAME%.c $(APXS) -c $(DEF) $(INC) $(LIB) mod_%NAME%.c # install the DSO file into the Apache installation # and activate it in the Apache configuration install: all - $(APXS) -i -a -n '%NAME%' mod_%NAME%.so + $(APXS) -i -a -n '%NAME%' mod_%NAME%.%DSO_EXT% # cleanup clean: - -rm -f mod_%NAME%.o mod_%NAME%.so + -rm -f mod_%NAME%.o mod_%NAME%.%DSO_EXT% # simple test test: reload @@ -637,7 +644,7 @@ stop: ** for the URL /%NAME%, as follows: ** ** # %TARGET%.conf -** LoadModule %NAME%_module libexec/mod_%NAME%.so +** LoadModule %NAME%_module libexec/mod_%NAME%.%DSO_EXT% ** <Location /%NAME%> ** SetHandler %NAME% ** </Location> diff --git a/usr.sbin/httpd/src/support/httpd.exp b/usr.sbin/httpd/src/support/httpd.exp index 359f6dba649..a337b18a26b 100644 --- a/usr.sbin/httpd/src/support/httpd.exp +++ b/usr.sbin/httpd/src/support/httpd.exp @@ -106,6 +106,7 @@ ap_dummy_mutex ap_each_byterange ap_error_log2stderr ap_escape_html +ap_escape_logitem ap_escape_path_segment ap_escape_quotes ap_escape_shell_cmd @@ -129,6 +130,7 @@ ap_fini_vhost_config ap_fnmatch ap_force_library_loading ap_get_basic_auth_pw +ap_get_chunk_size ap_get_client_block ap_get_gmtoff ap_get_list_item @@ -142,6 +144,7 @@ ap_get_server_version ap_get_time ap_get_token ap_get_virthost_addr +ap_getline ap_getparents ap_getword ap_getword_conf @@ -348,6 +351,7 @@ ap_strcasecmp_match ap_strcasestr ap_strcmp_match ap_stripprefix +ap_strtol ap_sub_req_lookup_file ap_sub_req_lookup_uri ap_sub_req_method_uri |
