📄 auth.cpp
字号:
SEC_WINNT_AUTH_IDENTITY AuthIdentityClient = {
m_wszRemoteUser, wcslen(m_wszRemoteUser),
SECURITY_DOMAIN,SVSUTIL_CONSTSTRLEN(SECURITY_DOMAIN),
wszPassword, wcslen(wszPassword),
0}; // dummy domain needed
memset(&ServerState,0,sizeof(AUTH_STATE));
memset(&ClientState,0,sizeof(AUTH_STATE));
if (!g_pVars->m_hSecurityLib)
myleave(368);
// NTLM auth functions seem to expect that these buffer will be zeroed.
pClientOutBuf = MyRgAllocZ(BYTE,g_pVars->m_cbMaxToken);
if (NULL == pClientOutBuf)
myleave(370);
pServerOutBuf = MyRgAllocZ(BYTE,g_pVars->m_cbMaxToken);
if (NULL == pServerOutBuf)
myleave(371);
ServerState.m_Stage = SEC_STATE_NO_INIT_CONTEXT;
ClientState.m_Stage = SEC_STATE_NO_INIT_CONTEXT;
cbClientBuf = cbServerBuf = g_pVars->m_cbMaxToken;
// Main loop that forges client and server talking.
while (!fDone) {
cbClientBuf = g_pVars->m_cbMaxToken;
if (! SecurityClientContext(&AuthIdentityClient,&ClientState,pServerOutBuf,
cbServerBuf, pClientOutBuf, &cbClientBuf))
{
myleave(372);
}
cbServerBuf = g_pVars->m_cbMaxToken;
if (! SecurityServerContext(&AuthIdentityClient,&ServerState, pClientOutBuf,
cbClientBuf, pServerOutBuf, &cbServerBuf, &fDone,NTLM_PACKAGE_NAME))
{
myleave(373);
}
}
done:
DEBUGMSG_ERR(ZONE_ERROR,(L"HTTPD: Unable to convert Basic Auth to NTLM Auth, err = %d\r\n",err));
if (fDone) {
GetUserAndGroupInfo(&ServerState);
m_AuthLevelGranted = DeterminePermissionGranted(GetUserList(),AUTH_USER);
}
MyFree(pClientOutBuf);
MyFree(pServerOutBuf);
FreeSecContextHandles(&ServerState);
FreeSecContextHandles(&ClientState);
return fDone;
}
// This calls the DC (or goes to registry in local case), either getting a
// data blob to return to client or granting auth or denying.
BOOL SecurityServerContext(
PSEC_WINNT_AUTH_IDENTITY pAuthIdentity,
PAUTH_STATE pAS, // security state info
BYTE *pIn,
DWORD cbIn,
BYTE *pOut,
DWORD *pcbOut,
BOOL *pfDone,
const TCHAR *szPackageName)
{
SECURITY_STATUS ss;
TimeStamp Lifetime;
SecBufferDesc OutBuffDesc;
SecBuffer OutSecBuff;
SecBufferDesc InBuffDesc;
SecBuffer InSecBuff;
ULONG ContextAttributes;
if (SEC_STATE_NO_INIT_CONTEXT == pAS->m_Stage) {
ss = g_pVars->m_SecurityInterface.AcquireCredentialsHandle (
NULL, // principal
(TCHAR *)szPackageName,
SECPKG_CRED_INBOUND,
NULL, // LOGON id
pAuthIdentity,
NULL, // get key fn
NULL, // get key arg
&pAS->m_hcred,
&Lifetime
);
if (SEC_SUCCESS (ss))
pAS->m_fHaveCredHandle = TRUE;
else {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: NTLM AcquireCreds failed: %X\n", ss));
return(FALSE);
}
}
// prepare output buffer
//
OutBuffDesc.ulVersion = 0;
OutBuffDesc.cBuffers = 1;
OutBuffDesc.pBuffers = &OutSecBuff;
OutSecBuff.cbBuffer = *pcbOut;
OutSecBuff.BufferType = SECBUFFER_TOKEN;
OutSecBuff.pvBuffer = pOut;
// prepare input buffer
//
InBuffDesc.ulVersion = 0;
InBuffDesc.cBuffers = 1;
InBuffDesc.pBuffers = &InSecBuff;
InSecBuff.cbBuffer = cbIn;
InSecBuff.BufferType = SECBUFFER_TOKEN;
InSecBuff.pvBuffer = pIn;
ss = g_pVars->m_SecurityInterface.AcceptSecurityContext (
&pAS->m_hcred,
(pAS->m_Stage == SEC_STATE_PROCESSING) ? &pAS->m_hctxt : NULL,
&InBuffDesc,
0, // context requirements
SECURITY_NATIVE_DREP,
&pAS->m_hctxt,
&OutBuffDesc,
&ContextAttributes,
&Lifetime
);
if (!SEC_SUCCESS (ss)) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: NTLM init context failed: %X\n", ss));
return FALSE;
}
pAS->m_fHaveCtxtHandle = TRUE;
// Complete token -- if applicable
//
if ((SEC_I_COMPLETE_NEEDED == ss) || (SEC_I_COMPLETE_AND_CONTINUE == ss)) {
if (g_pVars->m_SecurityInterface.CompleteAuthToken) {
ss = g_pVars->m_SecurityInterface.CompleteAuthToken (&pAS->m_hctxt, &OutBuffDesc);
if (!SEC_SUCCESS(ss)) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: NTLM complete failed: %X\n", ss));
return FALSE;
}
}
else {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: Complete not supported.\n"));
return FALSE;
}
}
*pcbOut = OutSecBuff.cbBuffer;
pAS->m_Stage = SEC_STATE_PROCESSING;
*pfDone = !((SEC_I_CONTINUE_NEEDED == ss) ||
(SEC_I_COMPLETE_AND_CONTINUE == ss));
return TRUE;
}
// Forges the client browser's part in NTLM communication if the browser
// sent a Basic request.
BOOL SecurityClientContext(
PSEC_WINNT_AUTH_IDENTITY pAuthIdentity,
PAUTH_STATE pAS, // NTLM state info
BYTE *pIn,
DWORD cbIn,
BYTE *pOut,
DWORD *pcbOut)
{
SECURITY_STATUS ss;
TimeStamp Lifetime;
SecBufferDesc OutBuffDesc;
SecBuffer OutSecBuff;
SecBufferDesc InBuffDesc;
SecBuffer InSecBuff;
ULONG ContextAttributes;
if (SEC_STATE_NO_INIT_CONTEXT == pAS->m_Stage) {
ss = g_pVars->m_SecurityInterface.AcquireCredentialsHandle (
NULL, // principal
NTLM_PACKAGE_NAME,
SECPKG_CRED_OUTBOUND,
NULL, // LOGON id
pAuthIdentity, // auth data
NULL, // get key fn
NULL, // get key arg
&pAS->m_hcred,
&Lifetime
);
if (SEC_SUCCESS (ss))
pAS->m_fHaveCredHandle = TRUE;
else {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: AcquireCreds failed: %X\n", ss));
return(FALSE);
}
}
// prepare output buffer
//
OutBuffDesc.ulVersion = 0;
OutBuffDesc.cBuffers = 1;
OutBuffDesc.pBuffers = &OutSecBuff;
OutSecBuff.cbBuffer = *pcbOut;
OutSecBuff.BufferType = SECBUFFER_TOKEN;
OutSecBuff.pvBuffer = pOut;
// prepare input buffer
if (SEC_STATE_NO_INIT_CONTEXT != pAS->m_Stage) {
InBuffDesc.ulVersion = 0;
InBuffDesc.cBuffers = 1;
InBuffDesc.pBuffers = &InSecBuff;
InSecBuff.cbBuffer = cbIn;
InSecBuff.BufferType = SECBUFFER_TOKEN;
InSecBuff.pvBuffer = pIn;
}
ss = g_pVars->m_SecurityInterface.InitializeSecurityContext (
&pAS->m_hcred,
(pAS->m_Stage == SEC_STATE_PROCESSING) ? &pAS->m_hctxt : NULL,
NULL,
0, // context requirements
0, // reserved1
SECURITY_NATIVE_DREP,
(pAS->m_Stage == SEC_STATE_PROCESSING) ? &InBuffDesc : NULL,
0, // reserved2
&pAS->m_hctxt,
&OutBuffDesc,
&ContextAttributes,
&Lifetime
);
if (!SEC_SUCCESS (ss)) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: init context failed: %X\n", ss));
return FALSE;
}
pAS->m_fHaveCtxtHandle = TRUE;
// Complete token -- if applicable
//
if ((SEC_I_COMPLETE_NEEDED == ss) || (SEC_I_COMPLETE_AND_CONTINUE == ss)) {
if (g_pVars->m_SecurityInterface.CompleteAuthToken) {
ss = g_pVars->m_SecurityInterface.CompleteAuthToken (&pAS->m_hctxt, &OutBuffDesc);
if (!SEC_SUCCESS(ss)) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: complete failed: %X\n", ss));
return FALSE;
}
}
else {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: Complete not supported.\n"));
return FALSE;
}
}
*pcbOut = OutSecBuff.cbBuffer;
pAS->m_Stage = SEC_STATE_PROCESSING;
return TRUE;
}
// Gets group and user info from NTLM structure after a user has retrieved info.
// Called after a user has been successfully authenticated with either BASIC or NTLM.
// See \winceos\comm\security\authhlp to see ACL algorithm function/description.
void CHttpRequest::GetUserAndGroupInfo(PAUTH_STATE pAuth)
{
PWSTR wsz = NULL;
SecPkgContext_Names pkgName;
pkgName.sUserName = NULL;
#if defined(UNDER_CE)
SecPkgContext_GroupNames ContextGroups;
ContextGroups.msGroupNames = NULL;
int ccGroupNamesLen = 0; // null delimited string; wcslen won't work!
#endif
// If we're called from NTLM request (pAuth != NULL) then we need
// to get the user name if we don't have it. On BASIC request, we
// have m_wszRemoteUser name already.
if ((NULL==m_wszRemoteUser) && ! SEC_SUCCESS(g_pVars->m_SecurityInterface.QueryContextAttributes(&(pAuth->m_hctxt),
SECPKG_ATTR_NAMES, &pkgName)))
{
DEBUGMSG(ZONE_ERROR,(L"HTTPD: QueryContextAttributes failed, cannot determine user name!\r\n"));
goto done; // If we can't get user name, don't bother continuing
}
#if defined(UNDER_CE)
g_pVars->m_SecurityInterface.QueryContextAttributes(&(pAuth->m_hctxt),SECPKG_ATTR_GROUP_NAMES,&ContextGroups);
// Group list is returned to us a NULL delimited list. Need to calculate len of this multi-string, wcslen() is out.
if (ContextGroups.msGroupNames) {
PWSTR szTrav = ContextGroups.msGroupNames;
while (*szTrav) {
szTrav += wcslen(szTrav)+1;
}
ccGroupNamesLen = szTrav - ContextGroups.msGroupNames + 1;
}
#endif
DEBUGMSG(ZONE_AUTH,(L"HTTPD: Admin Users = %s, pkgName.sUserName = %s, group name = %s\r\n",
m_pWebsite->m_wszAdminUsers,pkgName.sUserName,ContextGroups.msGroupNames));
done:
if (pkgName.sUserName) {
DEBUGCHK(m_wszRemoteUser == NULL);
m_wszRemoteUser = MySzDupW(pkgName.sUserName);
g_pVars->m_SecurityInterface.FreeContextBuffer(pkgName.sUserName);
}
#if defined(UNDER_CE)
DEBUGCHK(m_wszMemberOf == NULL);
if (ContextGroups.msGroupNames && (ccGroupNamesLen >1)) {
m_wszMemberOf = MySzAllocW(ccGroupNamesLen);
if (m_wszMemberOf) {
memcpy(m_wszMemberOf,ContextGroups.msGroupNames,ccGroupNamesLen*sizeof(WCHAR));
DEBUGCHK(m_wszMemberOf[ccGroupNamesLen-1] == 0 && m_wszMemberOf[ccGroupNamesLen-2] == 0); // last 2 bytes should = 0.
}
}
if (ContextGroups.msGroupNames)
g_pVars->m_SecurityInterface.FreeContextBuffer(ContextGroups.msGroupNames);
#endif
}
AUTHLEVEL CHttpRequest::DeterminePermissionGranted(const WCHAR *wszUserList, AUTHLEVEL authDefault) {
if (!m_wszRemoteUser) {
DEBUGMSG(ZONE_AUTH,(L"HTTPD: DeterminePermissionGranted returns default level %d because there's no user\r\n",authDefault));
return authDefault;
}
// Administrators always get admin access and access to the page, even if
// they're barred in the VRoot list. If there is a vroot list and we fail
// the IsAccessAllowed test, we set the auth granted to 0 - this
// will deny access. If no VRoot user list is set, keep us at AUTH_USER.
if (m_pWebsite->m_wszAdminUsers && IsAccessAllowed(m_wszRemoteUser,m_wszMemberOf,m_pWebsite->m_wszAdminUsers,FALSE)) {
DEBUGMSG(ZONE_AUTH,(L"HTTPD: DeterminePermissionGranted returns AUTH_ADMIN because %s is in admin user list\r\n",m_wszRemoteUser));
return AUTH_ADMIN;
}
else if (wszUserList && IsAccessAllowed(m_wszRemoteUser,m_wszMemberOf,(WCHAR*)wszUserList,FALSE)) {
DEBUGMSG(ZONE_AUTH,(L"HTTPD: DeterminePermissionGranted returns AUTH_USER because %s is in user list\r\n",m_wszRemoteUser));
return AUTH_USER;
}
else if (wszUserList) {
DEBUGMSG(ZONE_AUTH,(L"HTTPD: DeterminePermissionGranted returns AUTH_PUBLIC because %s was not in user list\r\n",m_wszRemoteUser));
return AUTH_PUBLIC;
}
else {
DEBUGMSG(ZONE_AUTH,(L"HTTPD: DeterminePermissionGranted returns default level permission %d because not in Adminlist/userlist\r\n",authDefault));
return authDefault;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -