ClearBox Server™ v1.2 Developer's Guide

Step 8. Authorizing Users

In this step, you will learn how to authorize users. In our example this means that every user has a definite amount of time he can stay connected (e.g., 10 hours total). When user has passed authentication, server extension uses accounting database to calculate how much time user has already spent on-line and returns timeout value which instructs NAS (that is RADIUS or TACACS+ client) to disconnect user after this time elapses. Server extension rejects all users requesting service other than PPP.

1. Implement ITACACSAuthorization and IRADIUSAuthorization interfaces. Right-click CMyFirst class in ClassView, select Implement Interface... from context menu. click Add Typelib, Browse and select tacradserver.tlb from /SDK directory of ClearBox Server installation. Check IRADIUSAuthorizationand ITACACSAuthorization interfaces and click OK.

2. Find GetAutorejectAttributes method and make it return S_OK instead of E_NOTIMPL code.

3. Find GetRequestMatchAttributes method and make it return S_OK instead of E_NOTIMPL code.

4. Find NeedAllAttributes method and change its return code to S_OK.

5. Add UserTimeAllowed protected method to the CMyFirst class with the following declaration:

int CMyFirst::UserTimeAllowed(BSTR user)
{
	USES_CONVERSION;

	CCommand<CDynamicAccessor> cmd;
	TCHAR cmdBuf[200];
	_stprintf(cmdBuf,
		_T("select SUM(elapsed) from Accounting where \
		UserID in (select ID from Users where Name='%s')"),W2T(user));

	HRESULT hRes=cmd.Open(m_DB.Session(),cmdBuf);
	if (FAILED(hRes))
		return -1;

	cmd.MoveFirst();

	double elapsedSum=0;
	cmd.GetValue(1,&elapsedSum);

	const int timeLimit=36000; // 10 hours
	return timeLimit-elapsedSum;
}

This method counts number of seconds spent by a user and returns resting time (deducted from 10 hours).

6. Find GetResponseAttributes method and replace its body to the following code.

STDMETHOD(GetResponseAttributes)(LONG tag, USERINFOLITE * userInf, 
	ULONG attrNumIn, RADIUS_ATTRIBUTE * inpAttributes, 
	ULONG * attrNumOut, RADIUS_ATTRIBUTE * * outpAttributes, 
	BSTR * explainString, RADAUTHENREPLY * replyType)
{
	if (attrNumOut == NULL)
		return E_POINTER;
		
	if (outpAttributes == NULL)
		return E_POINTER;
			
	if (explainString == NULL)
		return E_POINTER;
			
	if (replyType == NULL)
		return E_POINTER;

	*replyType=ACCESS_REJECT;

	// "Service-Type"
	int serviceType=0;
	int ind=FindRADAttribute(6,inpAttributes,attrNumIn);
	if (ind!=-1)
		serviceType=inpAttributes[ind].dwValue;

	// 2="Framed"
	if (serviceType!=0 && serviceType!=2)
		return S_OK;

	int timeLeft=UserTimeAllowed(userInf->userName);
	if (timeLeft<=0)
	{
		*explainString=SysAllocString(L"No time left");
		return S_OK;
	}

	if (serviceType==0)
		*attrNumOut=2;
	else
		*attrNumOut=1;

	*outpAttributes=
		reinterpret_cast<RADIUS_ATTRIBUTE*>(
		CoTaskMemAlloc(sizeof(RADIUS_ATTRIBUTE)*(*attrNumOut)));
		
	// "Session-Timeout"
	(*outpAttributes)[0].type=27;
	(*outpAttributes)[0].flags=0;
	(*outpAttributes)[0].valType=RADINT;
	(*outpAttributes)[0].dwValue=timeLeft;

	if (serviceType==0)
	{
		// "Service-Type"
		(*outpAttributes)[1].type=6;
		(*outpAttributes)[1].flags=0;
		(*outpAttributes)[1].valType=RADINT;
		(*outpAttributes)[1].dwValue=2;
	}

	*replyType=ACCESS_ACCEPT;
	return S_OK;
}

7. Find DefaultBehavior method and replace its code with the following lines:

STDMETHOD(DefaultBehavior)(LONG tag, TAC_AUTHORPARAMS * authorParams, BSTR service, 
	BSTR protocol, VARIANT_BOOL * permitMandatory, VARIANT_BOOL * permitOptional)
{
	if (permitMandatory == NULL)
		return E_POINTER;
		
	if (permitOptional == NULL)
		return E_POINTER;

	*permitMandatory=VARIANT_TRUE;
	*permitOptional=VARIANT_TRUE;
		
	return S_OK;
}

8. Find GetAVPairs method in CMyFirst class and make it look like the following code:

STDMETHOD(GetAVPairs)(LONG tag, TAC_AUTHORPARAMS * authorParams, BSTR service, 
	BSTR protocol, ULONG * outpSize, AVPAIR * * outpPairs, 
	BSTR * explainString, BYTE * tacacsStatus)
{
	if (outpSize == NULL)
		return E_POINTER;
			
	if (outpPairs == NULL)
		return E_POINTER;
			
	if (explainString == NULL)
		return E_POINTER;
			
	if (tacacsStatus == NULL)
		return E_POINTER;

	*tacacsStatus=0x10; //TAC_PLUS_AUTHOR_STATUS_FAIL

	if (wcscmp(L"ppp",service)!=0)
		return S_OK;
	if (protocol==NULL || wcscmp(L"lcp",protocol)!=0)
	{
		*tacacsStatus=0x1; //TAC_PLUS_AUTHOR_STATUS_PASS_ADD
		return S_OK;
	}

	int timeLeft=UserTimeAllowed(authorParams->user);
	if (timeLeft<=0)
	{
		*explainString=SysAllocString(L"No time left");
		return S_OK;
	}

	*outpSize=1;
	*outpPairs=
		reinterpret_cast<AVPAIR*>(
			CoTaskMemAlloc(sizeof(AVPAIR)));
	(*outpPairs)[0].access=A_PERMIT;
	(*outpPairs)[0].mandType=M_MANDATORY;
	(*outpPairs)[0].attribute=SysAllocString(L"timeout");

	WCHAR wbuff[11];
	_itow(timeLeft,wbuff,10);
	(*outpPairs)[0].value=SysAllocString(wbuff);

	*tacacsStatus=0x1; //TAC_PLUS_AUTHOR_STATUS_PASS_ADD
	return S_OK;
}

Go to the next step.


© 2001-2003 XPerience Technologies. www.xperiencetech.com

Created by chm2web html help conversion utility.