authentProtect (v 0.8 beta) : source code step by step


  This source code is the main file "authentProtect.cpp".


/*
  AuthentProtect v0.8
  Copyright (C) 2002  Bob - Firstcodings
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

  Bob <bob@firstcodings.com>
*/

#include "stdafx.h"
#include "authentProtect.h"

#include <iostream.h>
#include <fstream.h>
// needed to handle config file

CWinApp theApp;

CAuthentProtectFilter theFilter;

CAuthentProtectFilter::CAuthentProtectFilter() { }
CAuthentProtectFilter::~CAuthentProtectFilter() { }

char deniedLogins[65536];
// will receive list of denied logins separated by ':'

BOOL CAuthentProtectFilter::GetFilterVersion(PHTTP_FILTER_VERSION pVer)
{
	// this method is called once in the life of the "inetinfo.exe" process
	CHttpFilter::GetFilterVersion(pVer);
	_tcscpy(pVer->lpszFilterDesc, FILTER_DESCRIPTION);
	// the ids_filter string resource has been deleted !

	pVer->dwFlags &= ~(SF_NOTIFY_ORDER_MASK | SF_NOTIFY_SECURE_PORT | SF_NOTIFY_NONSECURE_PORT);
	pVer->dwFlags |= SF_NOTIFY_AUTHENTICATION | SF_NOTIFY_ORDER_LOW | SF_NOTIFY_SECURE_PORT | SF_NOTIFY_NONSECURE_PORT;
	// default is priority low and SSL/nonSSL request
	sprintf (deniedLogins, "%c%s%c%s%c", LOGIN_NAME_SEPARATOR, "administrator", LOGIN_NAME_SEPARATOR, "administrateur", LOGIN_NAME_SEPARATOR);
	// default will deny login 'administrator' (and 'administrateur' for french ;)

	char sysDirectory[236];
	char confFile [312];
	GetSystemDirectory (sysDirectory, 236);
	sprintf (confFile, "%s%s", sysDirectory, "\\inetsrv\\authentProtect.conf");
	// build the path to the config file

	ifstream ifs(confFile, ios::nocreate);
	// try to open config file
	if (ifs)
	{
		// config file is opened
		char strLine[MAX_CONFIGFILE_LINE_SIZE];
		deniedLogins[0] = LOGIN_NAME_SEPARATOR; deniedLogins[1] = '\0';
		while (ifs.getline(strLine, MAX_CONFIGFILE_LINE_SIZE))
		{
			strLower(strLine);
			// lines are read, and then case lowered

			if (strncmp (strLine, CONF_RUN_PRIORITY, szConfRunPriority - 1) == 0)
			{
				// the line begins with "run priority "
				pVer->dwFlags &= ~(SF_NOTIFY_ORDER_LOW | SF_NOTIFY_ORDER_MEDIUM | SF_NOTIFY_ORDER_HIGH);
				if (strcmp (strLine + szConfRunPriority - 1, "low") == 0) pVer->dwFlags |= SF_NOTIFY_ORDER_LOW;
				else if (strcmp (strLine + szConfRunPriority - 1, "medium") == 0) pVer->dwFlags |= SF_NOTIFY_ORDER_MEDIUM;
				else if (strcmp (strLine + szConfRunPriority - 1, "high") == 0) pVer->dwFlags |= SF_NOTIFY_ORDER_HIGH;
				else pVer->dwFlags |= SF_NOTIFY_ORDER_DEFAULT;
				// the priority is low, medium or high (default is low if config file is wrong)
			}
			
			if (strncmp (strLine, CONF_RUN_OPTIONS, szConfRunOptions - 1) == 0)
			{
				// the line begins with "run options "
				pVer->dwFlags &= ~(SF_NOTIFY_SECURE_PORT | SF_NOTIFY_NONSECURE_PORT);
				if (strstr (strLine + szConfRunOptions - 2, " ssl") != NULL) pVer->dwFlags |= SF_NOTIFY_SECURE_PORT;
				if (strstr (strLine + szConfRunOptions - 2, " nossl") != NULL) pVer->dwFlags |= SF_NOTIFY_NONSECURE_PORT;
				if (! ((pVer->dwFlags | SF_NOTIFY_SECURE_PORT) || (pVer->dwFlags | SF_NOTIFY_NONSECURE_PORT)))
					pVer->dwFlags |= SF_NOTIFY_SECURE_PORT | SF_NOTIFY_NONSECURE_PORT;
				// the option is SSL and/or nonSSL request (default is both if config file is wrong)
			}
			
			if (strncmp (strLine, CONF_DENYLOGIN, szConfDenyLogin - 1) == 0)
			{
				// the line begins with "denylogin "
				sprintf (strLine, "%s%c", strLine + szConfDenyLogin - 1, LOGIN_NAME_SEPARATOR);
				strcat (deniedLogins, strLine);
				// add this login to the list of denied ones (separated by ':')
			}
		}
		ifs.close();
	}
	// no 'else' here beacause default values are already set

	return TRUE;
}

DWORD CAuthentProtectFilter::OnAuthentication(CHttpFilterContext* pCtxt, PHTTP_FILTER_AUTHENT pAuthent)
{
	if ( !*pAuthent->pszUser ) return SF_STATUS_REQ_NEXT_NOTIFICATION;
	// anonymous login are not handled here

	char loginNameToCompare[MAX_LOGIN_NAME_SIZE + 3];

	sprintf (loginNameToCompare, "%c%s%c", LOGIN_NAME_SEPARATOR, strLower(pAuthent->pszUser), LOGIN_NAME_SEPARATOR);
	// set "loginNameToCompare" to login name (case lowered) set by browser between separators

	if (strstr (deniedLogins, loginNameToCompare) != NULL)
		pAuthent->pszUser[0] = pAuthent->pszPassword[0] = '\0';
	// if login belongs to the list of denied logins, set login to anonymous (authentication will fail)

	return SF_STATUS_REQ_NEXT_NOTIFICATION;
	// next please !
}

char* CAuthentProtectFilter::strLower (char* str)
{
	// simple function to convert string to lowercase
	if (str == NULL) return NULL;

	char *pchar = str;

	while (*pchar)
	{
		(*pchar) = tolower(*pchar);
		pchar++;
	}
	return str;
}

// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CAuthentProtectFilter, CHttpFilter)
	//{{AFX_MSG_MAP(CAuthentProtectFilter)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif	// 0