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.
 
 
 
 
 
 

295 lines
8.2 KiB

///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) Microsoft Corp. All rights reserved.
//
// FILE
//
// userr.cpp
//
// SYNOPSIS
//
// Defines the class UserRestrictions.
//
///////////////////////////////////////////////////////////////////////////////
#include <ias.h>
#include <userr.h>
#include <TimeOfDay.h>
IASREQUESTSTATUS UserRestrictions::onSyncRequest(IRequest* pRequest) throw ()
{
try
{
IASRequest request(pRequest);
IASREASON result;
if (!checkAllowDialin(request))
{
result = IAS_DIALIN_DISABLED;
}
else if (!checkTimeOfDay(request))
{
result = IAS_INVALID_DIALIN_HOURS;
}
else if (!checkAuthenticationType(request))
{
result = IAS_INVALID_AUTH_TYPE;
}
else if (!checkCallingStationId(request))
{
result = IAS_INVALID_CALLING_STATION;
}
else if (!checkCalledStationId(request))
{
result = IAS_INVALID_CALLED_STATION;
}
else if (!checkAllowedPortType(request))
{
result = IAS_INVALID_PORT_TYPE;
}
else if (!checkPasswordMustChange(request))
{
result = IAS_CPW_NOT_ALLOWED;
}
else
{
result = IAS_SUCCESS;
}
if (result != IAS_SUCCESS)
{
request.SetResponse(IAS_RESPONSE_ACCESS_REJECT, result);
}
}
catch (const _com_error&)
{
pRequest->SetResponse(IAS_RESPONSE_DISCARD_PACKET, IAS_INTERNAL_ERROR);
}
return IAS_REQUEST_STATUS_HANDLED;
}
BOOL UserRestrictions::checkAllowDialin(
IAttributesRaw* request
)
{
PIASATTRIBUTE attr = IASPeekAttribute(
request,
IAS_ATTRIBUTE_ALLOW_DIALIN,
IASTYPE_BOOLEAN
);
return !attr || attr->Value.Boolean;
}
BOOL UserRestrictions::checkTimeOfDay(
IAttributesRaw* request
)
{
AttributeVector attrs;
attrs.load(request, IAS_ATTRIBUTE_NP_TIME_OF_DAY);
if (attrs.empty()) { return TRUE; }
BYTE hourMap[IAS_HOUR_MAP_LENGTH];
memset(hourMap, 0, sizeof(hourMap));
for (AttributeVector::iterator i = attrs.begin(); i != attrs.end(); ++i)
{
IASAttributeUnicodeAlloc(i->pAttribute);
if (!i->pAttribute->Value.String.pszWide) { issue_error(E_OUTOFMEMORY); }
// Convert the text to an hour map.
DWORD dw = IASHourMapFromText(
i->pAttribute->Value.String.pszWide,
TRUE,
hourMap
);
if (dw != NO_ERROR)
{
issue_error(HRESULT_FROM_WIN32(dw));
}
}
SYSTEMTIME now;
GetLocalTime(&now);
DWORD timeOut = ComputeTimeout(now, hourMap);
if (timeOut == 0)
{
return FALSE;
}
if (timeOut != 0xFFFFFFFF)
{
// Add the Session-Timeout attribute to the request.
// it'll be carried over to the response later on.
IASAttribute sessionTimeout(true);
sessionTimeout->dwId = MS_ATTRIBUTE_SESSION_TIMEOUT;
sessionTimeout->Value.itType = IASTYPE_INTEGER;
sessionTimeout->Value.Integer = timeOut;
sessionTimeout.setFlag(IAS_INCLUDE_IN_ACCEPT);
sessionTimeout.store(request);
}
return TRUE;
}
BOOL UserRestrictions::checkAuthenticationType(
IAttributesRaw* request
)
{
// special case for the external Auth provider
PIASATTRIBUTE provider = IASPeekAttribute(
request,
IAS_ATTRIBUTE_PROVIDER_TYPE,
IASTYPE_ENUM
);
_ASSERT(provider != 0);
if (provider->Value.Enumerator == IAS_PROVIDER_EXTERNAL_AUTH)
{
return TRUE;
}
AttributeVector attrs;
attrs.load(request, IAS_ATTRIBUTE_NP_AUTHENTICATION_TYPE);
if (attrs.empty()) {return TRUE;}
PIASATTRIBUTE attr = IASPeekAttribute(
request,
IAS_ATTRIBUTE_AUTHENTICATION_TYPE,
IASTYPE_ENUM
);
DWORD authType = attr ? attr->Value.Enumerator : IAS_AUTH_NONE;
// We bypass the check for BaseCamp extensions.
if (authType == IAS_AUTH_CUSTOM) { return TRUE; }
for (AttributeVector::iterator i = attrs.begin(); i != attrs.end(); ++i)
{
if (i->pAttribute->Value.Integer == authType) { return TRUE; }
}
return FALSE;
}
BOOL UserRestrictions::checkCallingStationId(
IAttributesRaw* request
)
{
return checkStringMatch(
request,
IAS_ATTRIBUTE_NP_CALLING_STATION_ID,
RADIUS_ATTRIBUTE_CALLING_STATION_ID
);
}
BOOL UserRestrictions::checkCalledStationId(
IAttributesRaw* request
)
{
return checkStringMatch(
request,
IAS_ATTRIBUTE_NP_CALLED_STATION_ID,
RADIUS_ATTRIBUTE_CALLED_STATION_ID
);
}
BOOL UserRestrictions::checkAllowedPortType(
IAttributesRaw* request
)
{
AttributeVector attrs;
attrs.load(request, IAS_ATTRIBUTE_NP_ALLOWED_PORT_TYPES);
if (attrs.empty()) { return TRUE; }
PIASATTRIBUTE attr = IASPeekAttribute(
request,
RADIUS_ATTRIBUTE_NAS_PORT_TYPE,
IASTYPE_ENUM
);
if (!attr) { return FALSE; }
for (AttributeVector::iterator i = attrs.begin(); i != attrs.end(); ++i)
{
if (i->pAttribute->Value.Enumerator == attr->Value.Enumerator)
{
return TRUE;
}
}
return FALSE;
}
// If the password must change, we check to see if the subsequent change
// password request would be authorized. This prevents prompting the user for a
// new password when he's not allowed to change it anyway.
BOOL UserRestrictions::checkPasswordMustChange(
IASRequest& request
)
{
if (request.get_Reason() != IAS_PASSWORD_MUST_CHANGE)
{
return TRUE;
}
PIASATTRIBUTE attr = IASPeekAttribute(
request,
IAS_ATTRIBUTE_AUTHENTICATION_TYPE,
IASTYPE_ENUM
);
DWORD cpwType;
switch (attr ? attr->Value.Enumerator : IAS_AUTH_NONE)
{
case IAS_AUTH_MSCHAP:
cpwType = IAS_AUTH_MSCHAP_CPW;
break;
case IAS_AUTH_MSCHAP2:
cpwType = IAS_AUTH_MSCHAP2_CPW;
break;
default:
return TRUE;
}
AttributeVector attrs;
attrs.load(request, IAS_ATTRIBUTE_NP_AUTHENTICATION_TYPE);
for (AttributeVector::iterator i = attrs.begin(); i != attrs.end(); ++i)
{
if (i->pAttribute->Value.Integer == cpwType) { return TRUE; }
}
return FALSE;
}
BOOL UserRestrictions::checkStringMatch(
IAttributesRaw* request,
DWORD allowedId,
DWORD usedId
)
{
AttributeVector attrs;
attrs.load(request, allowedId);
if (attrs.empty()) { return TRUE; }
PIASATTRIBUTE attr = IASPeekAttribute(
request,
usedId,
IASTYPE_OCTET_STRING
);
if (!attr) { return FALSE; }
PCWSTR used = IAS_OCT2WIDE(attr->Value.OctetString);
for (AttributeVector::iterator i = attrs.begin(); i != attrs.end(); ++i)
{
IASAttributeUnicodeAlloc(i->pAttribute);
if (!i->pAttribute->Value.String.pszWide) { issue_error(E_OUTOFMEMORY); }
if (!_wcsicmp(i->pAttribute->Value.String.pszWide, used)) { return TRUE; }
}
return FALSE;
}