Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

163 lines
5.1 KiB

/*
* S E C U R I T Y . C P P
*
* Url security checks. While these would seem to only apply to HttpEXT,
* all impls. that care about ASP execution should really think about this.
*
* Bits stolen from the IIS5 project 'iis5\infocom\cache2\filemisc.cxx' and
* cleaned up to fit in with the DAV sources.
*
* Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
*/
#include "_davprs.h"
// This function takes a suspected NT/Win95 short filename and checks
// if there's an equivalent long filename.
//
// For example, c:\foobar\ABCDEF~1.ABC is the same as
// c:\foobar\abcdefghijklmnop.abc.
//
// If there is an equivalent, we need to FAIL this path, because our metabase
// will NOT have the correct values listed under the short paths!
// If there is no equivalent, this path can be allowed through, because it
// might be a real storage entitiy (not an alias for a real storage entity).
//
// NOTE: This function should be called unimpersonated - the FindFirstFile()
// must be called in the system context since most systems have traverse
// checking turned off - except for the UNC case where we must be impersonated
// to get network access.
//
SCODE __fastcall
ScCheckIfShortFileName (
/* [in] */ LPCWSTR pwszPath,
/* [in] */ const HANDLE hitUser)
{
WIN32_FIND_DATAW fd;
LPCWSTR pwsz;
BOOL fUNC = FALSE;
// Skip forward to find the first '~'
//
if (NULL == (pwsz = wcschr(pwszPath, L'~')))
return S_OK;
//$ REVIEW: this is not sufficient for DavEX, but it is unclear that
// this function applies there. Certainly the FindFirstFile() call
// will fail at this time.
//
fUNC = (*pwszPath == L'\\');
Assert (!fUNC || (NULL != hitUser));
// We actually need to loop in case multiple '~' appear in the filename
//
do
{
// At this point, pwsz should be pointing to the '~'
//
Assert (L'~' == *pwsz);
// Is the next char a digit?
//
pwsz++;
if ((*pwsz >= L'0') && (*pwsz <= L'9'))
{
WCHAR wszTmp[MAX_PATH];
const WCHAR * pwchEndSeg;
const WCHAR * pwchBeginSeg;
HANDLE hFind;
// Isolate the path up to the segment with the
// '~' and do the FindFirstFile with that path
//
pwchEndSeg = wcschr (pwsz, L'\\');
if (!pwchEndSeg)
{
pwchEndSeg = pwsz + wcslen (pwsz);
}
// If the string is beyond MAX_PATH then we fail it.
// urls this long don't need to have '~N' in them.
//
// Also check that our buffer is big enough to handle anything
// that gets through this check.
//
// NOTE: We are assuming that other code outside this function
// will catch paths that are larger than MAX_PATH and FAIL them.
//
//$ REVIEW: the MAX_PATH restriction is very important because
// the call to FindFirstFile() will fail if the path is larger
// than MAX_PATH. Should we ever decide to support larger paths
// in HttpEXT, this code will have to change.
//
Assert (MAX_PATH == CElems(wszTmp));
if ((pwchEndSeg - pwszPath) >= MAX_PATH)
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
// Make a copy of the string up to this point in the path
//
wcsncpy (wszTmp, pwszPath, pwchEndSeg - pwszPath);
wszTmp[pwchEndSeg - pwszPath] = 0;
// If we are not accessing a unc, then we need to revert
// for our call to FindFirstFile() -- see comment above.
//
if (!fUNC)
{
safe_revert (const_cast<HANDLE>(hitUser));
hFind = FindFirstFileW (wszTmp, &fd);
}
else
hFind = FindFirstFileW (wszTmp, &fd);
if (hFind == INVALID_HANDLE_VALUE)
{
// If the FindFirstFile() fails to find the file then
// the filename cannot be a short name.
//
DWORD dw = GetLastError();
if ((ERROR_FILE_NOT_FOUND != dw) && (ERROR_PATH_NOT_FOUND != dw))
return HRESULT_FROM_WIN32(dw);
return S_OK;
}
// Make sure the find context gets closed.
//
FindClose (hFind);
// Isolate the last segment of the string which should be
// the potential short name equivalency
//
pwchBeginSeg = wcsrchr (wszTmp, '\\');
Assert (pwchBeginSeg);
pwchBeginSeg++;
// If the last segment doesn't match the long name then
// this is the short name version (alias) of the path -- so
// fail this function.
//
if (_wcsicmp (fd.cFileName, pwchBeginSeg))
{
DebugTrace ("Dav: Url: refers to shortname for file\n");
Assert (!_wcsicmp (fd.cAlternateFileName, pwchBeginSeg));
return E_DAV_SHORT_FILENAME;
}
}
} while (NULL != (pwsz = wcschr (pwsz, L'~')));
return S_OK;
}
SCODE __fastcall
ScCheckForAltFileStream (
/* [in] */ LPCWSTR pwszPath)
{
// Avoid the infamous ::$DATA bug
//
if (wcsstr (pwszPath, L"::"))
return E_DAV_ALT_FILESTREAM;
return S_OK;
}