Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

381 lines
8.5 KiB

/**********************************************************************/
/** Microsoft Windows NT **/
/** Copyright(c) Microsoft Corp., 1993 **/
/**********************************************************************/
/*
security.c
This module manages security for the W3 Service.
FILE HISTORY:
KeithMo 07-Mar-1993 Created.
*/
#include "w3p.hxx"
//
// Private constants.
//
//
// Private globals.
//
//
// Private functions
//
//
// Public functions.
//
BOOL
HTTP_REQ_BASE::SendAuthNeededResp(
BOOL * pfFinished
)
/*++
Routine Description:
Sends an access denied HTTP server response with the accompanying
authentication schemes the server supports
Parameters:
pfFinished - If set to TRUE, indicates no further processing is needed
for this request
Return Value:
TRUE if successful, FALSE on error
--*/
{
CHAR * pszTail;
DWORD cbRespBufUsed;
DWORD cbRespBufLeft;
DWORD cbNeeded;
*pfFinished = FALSE;
if ( !HTTP_REQ_BASE::BuildStatusLine( QueryRespBuf(),
!IsProxyRequest() ? HT_DENIED :
HT_PROXY_AUTH_REQ,
NO_ERROR ))
{
return FALSE;
}
//
// Make sure there's enough size for any ISAPI denial headers plus any
// admin specified access denied message
//
cbRespBufUsed = QueryRespBufCB();
cbRespBufLeft = QueryRespBuf()->QuerySize() - cbRespBufUsed;
cbNeeded = strlen( g_pszAccessDeniedMsg ) +
_strDenialHdrs.QueryCB() +
250; // Other misc headers
if ( cbNeeded > cbRespBufLeft )
{
if ( !QueryRespBuf()->Resize( cbNeeded + cbRespBufUsed ))
{
return FALSE;
}
}
pszTail = QueryRespBufPtr() + cbRespBufUsed;
//
// If this is not the first call, then return the current authentication
// data blob otherwise return the forms of authentication the server
// accepts
//
if ( IsAuthenticating() )
{
pszTail += wsprintf( pszTail,
"%s: %s\r\n",
(IsProxyRequest() ? "Proxy-Authenticate" :
"WWW-Authenticate"),
_strAuthInfo.QueryStr() );
}
else
{
if ( !AppendAuthenticationHdrs( QueryRespBuf(),
&pszTail,
pfFinished ))
{
return FALSE;
}
if ( *pfFinished )
{
return TRUE;
}
}
if ( IsKeepConnSet() )
{
if ( !IsProxyRequest() )
{
strcat( pszTail,
"Connection: keep-alive\r\n");
pszTail += sizeof( "Connection: keep-alive\r\n" ) - sizeof(CHAR);
}
else
{
strcat( pszTail,
"Proxy-Connection: keep-alive\r\n");
pszTail += sizeof( "Proxy-Connection: keep-alive\r\n" ) - sizeof(CHAR);
}
}
//
// Add any additional headers supplied by the filters plus the header
// termination
//
pszTail += wsprintf( pszTail,
"Content-Length: %d\r\n"
"Content-Type: text/html\r\n"
"%s\r\n"
"%s",
strlen( g_pszAccessDeniedMsg ),
_strDenialHdrs.QueryStr(),
g_pszAccessDeniedMsg );
TCP_ASSERT( QueryRespBuf()->QuerySize() > QueryRespBufCB() );
IF_DEBUG( PARSING )
{
TCP_PRINT(( DBG_CONTEXT,
"[SendAuthNeededResp] Sending headers: %s",
QueryRespBufPtr() ));
}
return WriteFile( QueryRespBufPtr(),
QueryRespBufCB(),
NULL,
IO_FLAG_ASYNC );
}
BOOL
HTTP_REQ_BASE::AppendAuthenticationHdrs(
BUFFER * pRespBuf,
CHAR * * ppszTail,
BOOL * pfFinished
)
/*++
Routine Description:
This method adds the appropriate "WWW-Authenticate" strings to the passed
server response string
This routine assumes pRespBuf is large enough to hold the authentication
headers
Parameters:
pRespBuf - Buffer of response headers
ppszTail - End of buffer to append data on to
pfFinished - Set to TRUE if no further processing is needed on this request
Return Value:
TRUE if successful, FALSE on error
--*/
{
CHAR * pchField;
CHAR * pszResp;
CHAR * pszTail;
CHAR * pszRealm = g_pszRealm;
//
// If no realm was supplied in the registry, use the host name
//
if ( !pszRealm )
{
pszRealm = QueryHostAddr();
}
//
// Notify any Access Denied filters the user has been denied access
//
if ( fAnyFilters )
{
if ( !_Filter.NotifyAccessDenied( &_Filter,
_strURL.QueryStr(),
_strPhysicalPath.QueryStr(),
pfFinished ))
{
return FALSE;
}
if ( *pfFinished )
{
return TRUE;
}
}
pszTail = *ppszTail;
//
// Send the correct header depending on if we're a proxy
//
if ( !IsProxyRequest() )
pchField = "WWW-Authenticate: ";
else
pchField = "Proxy-Authenticate: ";
if ( g_pTsvcInfo->QueryAuthentication() & INET_INFO_AUTH_NT_AUTH )
{
DWORD i = 0;
//
// For each authentication package the server supports, add a
// WWW-Authenticate header
//
while ( apszNTProviders[i] )
{
pszTail += wsprintf( pszTail,
"%s%s\r\n",
pchField,
apszNTProviders[i++] );
}
}
if ( g_pTsvcInfo->QueryAuthentication() & INET_INFO_AUTH_CLEARTEXT )
{
pszTail += wsprintf( pszTail,
"%sBasic realm=\"%s\"\r\n",
pchField,
pszRealm );
}
TCP_ASSERT( (pszTail - (CHAR *)pRespBuf->QueryPtr() ) <
(LONG) pRespBuf->QuerySize() );
*ppszTail = pszTail;
return TRUE;
}
BOOL
HTTP_REQ_BASE::ExtractClearNameAndPswd(
CHAR * pch,
STR * pstrUserName,
STR * pstrPassword,
BOOL fUUEncoded
)
/*++
Routine Description:
This method breaks a string in the form "username:password" and
places the components into pstrUserName and pstrPassword. If fUUEncoded
is TRUE, then the string is UUDecoded first.
Parameters:
pch - Pointer to <username>:<password>
Return Value:
TRUE if successful, FALSE on error
--*/
{
STR strDecoded;
CHAR * pchtmp;
pch = SkipWhite( pch );
if ( fUUEncoded )
{
if ( !uudecode( pch,
&strDecoded ))
{
return FALSE;
}
pch = strDecoded.QueryStrA();
}
pchtmp = SkipTo( pch, TEXT(':') );
if ( *pchtmp == TEXT(':') )
{
*pchtmp = TEXT('\0');
if ( !_strUserName.Copy( pch ) ||
!_strPassword.Copy( pchtmp + 1 ))
{
return FALSE;
}
}
return TRUE;
}
HANDLE
HTTP_REQ_BASE::QueryPrimaryToken(
HANDLE * phDelete
)
/*++
Routine Description:
This method returns a non-impersonation user token handle that's
usable with CreateProcessAsUser.
Parameters:
phDelete - If returned as non-null, the caller is responsible for calling
CloseHandle on this value when done using the returned value.
Return Value:
The primary token handle if successful, FALSE otherwise
--*/
{
*phDelete = NULL;
if ( !QueryVrootImpersonateHandle() )
{
return _tcpauth.QueryPrimaryToken();
}
//
// This is an impersonation token so dupe it to a primary token
//
if ( !DuplicateTokenEx( QueryVrootImpersonateHandle(),
TOKEN_ALL_ACCESS,
NULL,
SecurityImpersonation,
TokenPrimary,
phDelete ))
{
TCP_PRINT(( DBG_CONTEXT,
"[QueryPrimaryToken] DuplicateToken failed, error %lx\n",
GetLastError() ));
return NULL;
}
return *phDelete;
}