📄 default.c
字号:
/*
* default.c -- Default URL handler. Includes support for ASP.
*
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
*
* See the file "license.txt" for usage and redistribution license requirements
*
* $Id: default.c,v 1.9 2003/04/11 18:10:28 bporter Exp $
*/
/******************************** Description *********************************/
/*
* This module provides default URL handling and Active Server Page support.
*
* In many cases we don't check the return code of calls to websWrite as
* it is easier, smaller and non-fatal to continue even when the requesting
* browser has gone away.
*/
/********************************* Includes ***********************************/
#include "wsIntrn.h"
/*********************************** Locals ***********************************/
static char_t *websDefaultPage; /* Default page name */
static char_t *websDefaultDir; /* Default Web page directory */
/**************************** Forward Declarations ****************************/
static void websDefaultWriteEvent(webs_t wp);
/*********************************** Code *************************************/
/*
* Process a default URL request. This will validate the URL and handle "../"
* and will provide support for Active Server Pages. As the handler is the
* last handler to run, it always indicates that it has handled the URL
* by returning 1.
*/
int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
char_t *url, char_t *path, char_t *query)
{
websStatType sbuf;
char_t *lpath, *tmp, *date;
int bytes, flags, nchars;
a_assert(websValid(wp));
a_assert(url && *url);
a_assert(path);
a_assert(query);
/*
* Validate the URL and ensure that ".."s don't give access to unwanted files
*/
flags = websGetRequestFlags(wp);
if (websValidateUrl(wp, path) < 0)
{
/*
* preventing a cross-site scripting exploit -- you may restore the
* following line of code to revert to the original behavior...
*/
/*websError(wp, 500, T("Invalid URL %s"), url);*/
websError(wp, 500, T("Invalid URL"));
return 1;
}
lpath = websGetRequestLpath(wp);
nchars = gstrlen(lpath) - 1;
if (lpath[nchars] == '/' || lpath[nchars] == '\\') {
lpath[nchars] = '\0';
}
/*
* If the file is a directory, redirect using the nominated default page
*/
if (websPageIsDirectory(lpath)) {
nchars = gstrlen(path);
if (path[nchars-1] == '/' || path[nchars-1] == '\\') {
path[--nchars] = '\0';
}
nchars += gstrlen(websDefaultPage) + 2;
fmtAlloc(&tmp, nchars, T("%s/%s"), path, websDefaultPage);
websRedirect(wp, tmp);
bfreeSafe(B_L, tmp);
return 1;
}
/*
* Open the document. Stat for later use.
*/
if (websPageOpen(wp, lpath, path, SOCKET_RDONLY | SOCKET_BINARY,
0666) < 0)
{
/* 10 Dec 02 BgP -- according to
* <http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html>,
* the proper code to return here is NOT 400 (old code), which is used
* to indicate a malformed request. Here, the request is good, but the
* error we need to tell the client about is 404 (Not Found).
*/
/*
* 17 Mar 03 BgP -- prevent a cross-site scripting exploit
websError(wp, 404, T("Cannot open URL %s"), url);
*/
websError(wp, 404, T("Cannot open URL"));
return 1;
}
if (websPageStat(wp, lpath, path, &sbuf) < 0) {
/*
* 17 Mar 03 BgP
* prevent a cross-site scripting exploit
websError(wp, 400, T("Cannot stat page for URL %s"), url);
*/
websError(wp, 400, T("Cannot stat page for URL"));
return 1;
}
/*
* If the page has not been modified since the user last received it and it
* is not dynamically generated each time (ASP), then optimize request by
* sending a 304 Use local copy response
*/
websStats.localHits++;
#ifdef WEBS_IF_MODIFIED_SUPPORT
if (flags & WEBS_IF_MODIFIED && !(flags & WEBS_ASP)) {
if (sbuf.mtime <= wp->since) {
websWrite(wp, T("HTTP/1.0 304 Use local copy\r\n"));
/*
* by license terms the following line of code must
* not be modified.
*/
websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
if (flags & WEBS_KEEP_ALIVE) {
websWrite(wp, T("Connection: keep-alive\r\n"));
}
websWrite(wp, T("\r\n"));
websSetRequestFlags(wp, flags |= WEBS_HEADER_DONE);
websDone(wp, 304);
return 1;
}
}
#endif
/*
* Output the normal HTTP response header
*/
if ((date = websGetDateString(NULL)) != NULL) {
websWrite(wp, T("HTTP/1.0 200 OK\r\nDate: %s\r\n"), date);
/*
* By license terms the following line of code must not be modified.
*/
websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
bfree(B_L, date);
}
flags |= WEBS_HEADER_DONE;
/*
* If this is an ASP request, ensure the remote browser doesn't cache it.
* Send back both HTTP/1.0 and HTTP/1.1 cache control directives
*/
if (flags & WEBS_ASP) {
bytes = 0;
websWrite(wp, T("Pragma: no-cache\r\nCache-Control: no-cache\r\n"));
} else {
if ((date = websGetDateString(&sbuf)) != NULL) {
websWrite(wp, T("Last-modified: %s\r\n"), date);
bfree(B_L, date);
}
bytes = sbuf.size;
}
if (bytes) {
websWrite(wp, T("Content-length: %d\r\n"), bytes);
websSetRequestBytes(wp, bytes);
}
websWrite(wp, T("Content-type: %s\r\n"), websGetRequestType(wp));
if ((flags & WEBS_KEEP_ALIVE) && !(flags & WEBS_ASP)) {
websWrite(wp, T("Connection: keep-alive\r\n"));
}
websWrite(wp, T("\r\n"));
/*
* All done if the browser did a HEAD request
*/
if (flags & WEBS_HEAD_REQUEST) {
websDone(wp, 200);
return 1;
}
/*
* Evaluate ASP requests
*/
if (flags & WEBS_ASP) {
if (websAspRequest(wp, lpath) < 0) {
return 1;
}
websDone(wp, 200);
return 1;
}
#ifdef WEBS_SSL_SUPPORT
if (wp->flags & WEBS_SECURE) {
websDefaultWriteEvent(wp);
} else {
websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
}
#else
/*
* For normal web documents, return the data via background write
*/
websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
#endif
return 1;
}
#ifdef WIN32
static int badPath(char_t* path, char_t* badPath, int badLen)
{
int retval = 0;
int len = gstrlen(path);
int i = 0;
if (len <= badLen +1)
{
for (i = 0; i < badLen; ++i)
{
if (badPath[i] != gtolower(path[i]))
{
return 0;
}
}
/* if we get here, the first 'badLen' characters match.
* If 'path' is 1 character larger than 'badPath' and that extra
* character is NOT a letter or a number, we have a bad path.
*/
retval = 1;
if (badLen + 1 == len)
{
/* e.g. path == "aux:" */
if (gisalnum(path[len-1]))
{
/* the last character is alphanumeric, so we let this path go
* through.
*/
retval = 0;
}
}
}
return retval;
}
static int isBadWindowsPath(char_t** parts, int partCount)
{
/*
* If we're running on Windows 95/98/ME, malicious users can crash the
* OS by requesting an URL with any of several reserved DOS device names
* in them (AUX, NUL, etc.).
* If we're running on any of those OS versions, we scan the URL
* for paths with any of these elements before
* trying to access them. If any of the subdirectory names match one
* of our prohibited links, we declare this to be a 'bad' path, and return
* 1 to indicate this. This may be an overly heavy-handed approach, but should
* prevent the DOS attack.
* NOTE that this function is only compiled in when we are running on Win32,
* and only has an effect when we are running on Win95/98, or ME. On all other
* versions of Windows, we check the version info, and return 0 immediately.
*
* According to http://packetstormsecurity.nl/0003-exploits/SCX-SA-01.txt:
* II. Problem Description
* When the Microsoft Windows operating system is parsing a path that
* is being crafted like "c:\[device]\[device]" it will halt, and crash
* the entire operating system.
* Four device drivers have been found to crash the system. The CON,
* NUL, AUX, CLOCK$ and CONFIG$ are the two device drivers which are
* known to crash. Other devices as LPT[x]:, COM[x]: and PRN have not
* been found to crash the system.
* Making combinations as CON\NUL, NUL\CON, AUX\NUL, ... seems to
* crash Ms Windows as well.
* Calling a path such as "C:\CON\[filename]" won't result in a crash
* but in an error-message. Creating the map "CON", "CLOCK$", "AUX"
* "NUL" or "CONFIG$" will also result in a simple error-message
* saying: ''creating that map isn't allowed''.
*
* returns 1 if it finds a bad path element.
*/
OSVERSIONINFO version;
int i;
version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&version))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -