Overview

Sorry I've not been around for a while boys and girls - but what with holidays (mine and staffs) etc I have been a busy bunny over the last few months (the bit that wasn't spent in Bali anyway ). So just to make ammends here's a web class I've been writing for web based IIS Webserver administration class that some of you might find interesting.

If you want to use the class then download the attached iiscls.inc file rather than cutting and pasting the code below - I've cut it up some to get it to fit on the page.

NOTE: This script has to be run from an admin account.

Usage

**This class exposes the following properties

TraceOn - Boolean.
Set Trace on = true if you require debug info sent to the response object
ie. on screen at runtime. Logging information can also be retreived using the GetTrace Function

ServerName - String
Name of server to perform operation on

**This class exposes the following methods:

GetTrace - Returns Array of log items in : delimited format

DenyIP(svc,ip,subnet) - Add an IP to the deny list for site (Returns Boolean)
NOTE: This implicitly sets IPAllow to Allow by default with exclusions.
svc - service tag
ip - IP to deny eg 127.0.0.1
Subnet - Subnet of ip to deny eg 255.255.255.255
Example usage:
BOOL = denyip 7,"111.111.111.111","255.255.255.255"

AppDebug(svc,booldbg, message) - Set the send detailed error messages property for service (Returns Boolean)
svc - service tag
booldbg - Boolean set to true if debug is on
message - Message to display if booldbg is false
Example usage:
BOOL = appdebug 5,false,errmess - App Debug off
BOOL = appdebug 5,TRUE,"" - App Debug on

AppCreate(svc,frname,isolation) - Creates an IIS Application for the service (Returns Boolean)
svc - service tag
frname - Friendly name (descriptive)
isolation - Application Protection (low - IIS process=0 / medium - pooled=2 / high - isolated=1)
Example usage:
BOOL = appcreate 7,"www.whatever.com",0

MakeSite(IPAddress , PortNum, HostName, RootDirectory) - Creates a new site (Returns service tag or -1 for fail)
IPAddress - IP Address of new service eg 127.0.0.1
PortNum - Port number of new service eg 80
HostName - Host name of new service eg www.whatever.com
RootDirectory - Physical path to root of new service eg c:\webs\sitepath
Example usage:
makesite("127.0.0.1", "80", "www.whatever.com", "c:\webs\sitepath")

DeleteSite(svc) (Returns Boolean)
BOOL = svc - service tag

AddBinding(svc,IpAddress,PortNum,HostName) Add a binding to the specified service (Returns Boolean)
svc - service tag
IpAddress - IP Address of new binding eg 127.0.0.1
PortNum - Port Number of new binding eg 80
HostName - Host Name of new binding eg www.whatever.com
Example usage:
BOOL = AddBinding(160,"195.8.181.206","80","www.123atestsite.co.uk")

BindingsList(svc) - Returns Array of bindings in : delimited format eg svc:IPort:host
svc - filter list by a specific service tag or "" for all

IIBackup(bkupName) - Backup the metabase to $winnt$\system32\inetsvr\metaback\bkupName (boolean)
bkupName - Filename of backup

Sample ASP code

Code:
 
<%

'Create instance of IIS Cls
Set iis = NEW iiscls
'Set traceon (Boolean) for runtime debug
iis.traceon = false
'Set IIS server to localhost
iis.servername = "localhost"

main
WriteDebug

Sub Main
	 
	'***********************************
	'**Make the new site
	newsvc = iis.makesite("127.0.0.1", "80", "www.atestsite.co.uk", "c:\webs\path") 
	'If the makesite function fails (-1) the quit
	if newsvc = -1 then exit sub


	'***********************************
	'**Create an application for our new site
	If not iis.appcreate(newsvc,HostName,0) then exit sub	


	'***********************************
	'**Set the debug message of our new site
	if not iis.AppDebug(newsvc,false, errmess) then exit sub


	'***********************************
	'**Add a binding to the selected site
	if not iis.AddBinding(newsvc,"127.0.0.1","80", & _
	"www.123atestsite.co.uk") then exit sub	


	'***********************************
	'**list bindings on new service
	bind = iis.bindingsList(newsvc)
	for n = 1 to ubound(bind)
		response.write bind(n) & "
"
	next


	'***********************************
	'**Deny IP from site
	if not iis.denyip(newsvc,"111.111.111.111", & _
	"255.255.255.255") then exit sub	


	'***********************************	
	'**Remove binding from service
	if not iis.RemoveBinding(newsvc,"1270.0.1","80", & _
	"www.123atestsite.co.uk") then exit sub	
	
	
	'***********************************
	'**Delete the site we created
	if not iis.deletesite(newsvc) then exit sub

	
	'***********************************
	'**List all services
	bind = iis.bindingsList("")
	for n = 1 to ubound(bind)
		response.write bind(n) & "
"
	next


	'***********************************
	'**Back up metabase
	response.write "<h2>" & "Back up metabase" & "</h2>"
	iis.iibackup("Backupname.md0")

end sub

sub WriteDebug

	response.write "<h1>Debug Log</h1>"
	response.write "<table border = '1'>"
	col = iis.GetTrace
	for y = 0 to ubound(col)
		response.write "<tr>"
		row = split(col(y),"|")
		for x = 0 to ubound(row)
			response.write "<td>" & row(x) & "</td>"
		next 
		response.write "</tr>"
	next
	response.write "</table>"

end sub
The IIS Class File

Code:
<%

'IISCls by ntsa
'6/11/2002
'www.ntsa.org.uk

ary_err = array
Private m_TraceOn
Private m_ServerName

Const MD_BACKUP_SAVE_FIRST = 2   'Backup 
Const MD_BACKUP_FORCE_BACKUP = 4   'Backup 
Const MD_BACKUP_NEXT_VERSION = &HFFFFFFFF   'Backup 

Class IISCls

'______________________________________________
'The code!

'**Public properties

Public Property Let TraceOn(str_TraceOn)

		m_TraceOn = str_TraceOn	 

End Property

Public Property Let ServerName(str_ServerName)

	  m_ServerName = str_ServerName

End Property

'**Private Subs

private sub trace(data)
	
	if m_TraceOn = true then response.write "iiscls.inc|" & _
	data & "
"
	'Add data to log
	redim preserve ary_err(ubound(ary_err)+1)
	ary_err(ubound(ary_err)) = "iiscls.inc|" & data
	
end sub

'***Private Functions	

private function NextSite

	on error resume next
	index = 0
	
	do 
		Index = Index + 1
		Set SiteObj = GetObject("IIS://" & _
		m_ServerName&"/w3svc/" & Index)
		' A web server is already defined at 
		'this position so increment
	loop until Err.Number <> 0 or index = 10000
	
	'Sanity checking
	trace "NextSite|Validating new index"
	if index < 10000 then
		'Make sure the error corresponds with site not '
		found error code
		if err.number = -2147024893 then
			'Error is ok (arse about face though it sounds!)
			trace "NextSite|Validated ok. Availible Site found at " & index
			err.clear
			nextsite = index
		ELSE
			trace "NextSite|An unexpected error occured " & _
			"opening service IIS://"&m_ServerName&"/w3svc/" & Index
			trace "NextSite|Error: " & err.description
			nextsite = -1
		end if
	else
		'Sanity has been lost!
		trace "NextSite|No sites availible (Oh ****!)"
		nextsite = -1
	end if

end function

private function DuplicateBinding(IpAddress,PortNum,HostName)

	trace "DuplicateBinding|Ensuring Binding ("&IpAddress & ":" &_
	PortNum & ":" & HostName&") is unique"
	BindingString = IpAddress & ":" & PortNum & ":" & HostName
	DuplicateBinding = false
	
	on error resume next

	'Get the webserver object
	Set w3svc = GetObject("IIS://" & m_ServerName & "/w3svc")
	'If the webserver loaded ok
	If Err.Number = 0 Then
		'Iterate through the websites
		For Each WebServer in w3svc
			'If the class of the current object is a webserver
			If WebServer.Class = "IIsWebServer" Then
				'Load the bindings
				Bindings = WebServer.ServerBindings
				for n = 0 to ubound(Bindings)
				if trim(cstr(Bindings(n))) = trim(cstr)BindingString)) then
					trace "DuplicateBinding|Found duplicate binding!"
					DuplicateBinding = true
					exit function
					end if
				next
			End If
		Next
	else
		trace "DuplicateBinding|Error opening " & _
		"IIS://" & m_ServerName & "/w3svc - "  &  err.description
	end if

end function

'***Public Functions

Public Function DenyIP(svc,ip,subnet)

	on error resume next

	dnip = ip & ", " & subnet

	trace "DenyIP|Opening service w3svc/" & svc & " security settings"
	Set oService = GetObject("IIS://"& m_ServerName &"/W3SVC")
	Set oServer = oService.GetObject("IIsWebServer", svc)
	Set oVDir = oServer.GetObject("IIsWebVirtualDir", "ROOT")
	Set oIPSecurity = oVDir.IPSecurity
	
	if err.number <> 0 then
		trace "DenyIP|Could not open service w3svc/" & svc & " security settings"
		trace "DenyIP|Error: " & err.description
		DenyIP = false
		exit function
	else
		trace "DenyIP|Opened w3svc/" & svc & " security settings"

		'Set Grant by Default to true if set otherwise
		'NOTE: setting a deny list implicitly calls grant by default.
		
		trace "DenyIP|Checking GrantByDefault is TRUE"
		if oIPSecurity.GrantByDefault = false then 
			trace "DenyIP|GrantByDefault is FALSE - Setting to TRUE"
			oIPSecurity.GrantByDefault = true
		else
			trace "DenyIP|GrantByDefault is already TRUE"
		end if
		
		trace "DenyIP|Loading Deny list array"
		dIPs = oIPSecurity.IPDeny 

		trace "DenyIP|Checking the IP/Subnet is not duplicated"
		'Check the IP/Subnet is not duplicated
		'**TASK - ignore requests within same subnet.
		'**eg adding '192.168.0.1,255.255.255.0' would subsequently proclude
		'**adding '192.168.0.2,255.255.255.255' because the second is already
		'**disallowed by the first - NOT required for current project.

		dup = false
		for n = lbound(dips) to ubound(dips)
			if trim(cstr(dips(n))) = trim(cstr(dnip)) then
				dup = true
				denyIP = false
				trace "DenyIP|This IP/Subnet already exists!"
				exit function
			end if
		next

		'If no duplicate then add new IP to array
		if dup = false then
			trace "DenyIP|IP is good so add it to the Deny Array"
			redim preserve dips(ubound(dips)+1)
			dips(ubound(dips)) = dnip	
			oIPSecurity.IPDeny = dips
			'Write array back to metabase
			trace "DenyIP|Write array back to metabase"
			oVDir.IPSecurity = oIPSecurity
			'Save metabase
			trace "DenyIP|Save metabase"
			oVDir.SetInfo
		end if

		if err.number <> 0 then
			trace "DenyIP|Saving new security info failed"
			trace "DenyIP|Error: " & err.description
			DenyIP = false
		else
			trace "DenyIP|Saved new security info"
			denyIP = true
		end if

	end if
End Function

Public Function AppDebug(svc,booldbg, message)

	AppDebug = false

	on error resume next

	trace "AppDebug|Opening service w3svc/" & svc & " application settings"
	Set oService = GetObject("IIS://"& m_ServerName &"/W3SVC")
	Set oServer = oService.GetObject("IIsWebServer", svc)
	Set oVDir = oServer.GetObject("IIsWebVirtualDir", "ROOT")

	if err.number <> 0 then
		trace "AppDebug|Could not open service w3svc/" & svc & _
		" application settings"
		trace "AppDebug|Error: " & err.description
		AppDebug = false
		exit function
	end if

	oVDir.AspScriptErrorSentToBrowser = booldbg
	trace "AppDebug|Debug is currently set to " & booldbg

	if booldbg = false and len(message) > 0 then
		trace "AppDebug|Setting Error message"
		trace "AppDebug|Error: " & err.description
		oVDir.AspScriptErrorMessage = message
	end if

	trace "AppDebug|Saving metabase"
	' Write info back to Metabase
	oVDir.SetInfo

	if err.number <> 0 then
		trace "AppDebug|Could not save service w3svc/" & svc & _
		" application settings"
		trace "AppDebug|Error: " & err.description
		AppDebug = false
		exit function
	else
		'It all worked!
		AppDebug = true
	end if

End Function

Public Function AppCreate(svc,frname,isolation)

	on error resume next
	trace "AppCreate|Creating application for service w3svc/" & svc 

	Set oService = GetObject("IIS://"& m_ServerName &"/W3SVC")
	Set oServer = oService.GetObject("IIsWebServer", svc)
	Set oVDir = oServer.GetObject("IIsWebVirtualDir", "ROOT")

	if err.number <> 0 then
		trace "AppCreate|Could not open service w3svc/" & svc & _
		" security settings"
		trace "AppCreate|Error: " & err.description
		AppCreate = false
		exit function
	end if

	trace "AppCreate|Setting service w3svc/" & svc & " security settings"
	oVDir.AppCreate True
	' Application Name
	oVDir.AppFriendlyName = frname
	' Application Protection 
	'(low - IIS process=0 / medium - pooled=2 / high - isolated=1)
	oVDir.AppIsolated = isolation
	oVDir.SetInfo
	trace "AppCreate|Saving metabase"

	if err.number <> 0 then
		trace "AppCreate|Could not save service w3svc/" & svc & _
		" security settings"
		trace "AppCreate|Error: " & err.description
		AppCreate = false
		exit function
	else
		AppCreate = true
	end if

End Function

Public function GetTrace

	'response.write "getting trace on " & ubound(ary_err) & " items.
"
	'for n = 1 to ubound(ary_err)
	'	response.write ary_err(n)
	'next

   GetTrace = ary_err

End function

Public function MakeSite(IPAddress , PortNum, HostName, RootDirectory)

	makesite = -1
	on error resume next

	'If the specified binding does not already exist
	if not DuplicateBinding(IPAddress,PortNum,HostName) then 	
		
		index = nextsite
		'Make sure index is not -1
		if index = -1 then
			trace "MakeSite|Failed to find next availible site"
			trace "MakeSite|Quiting"
			exit function
		end if			
		
		'Index is ok
		Set w3svc = GetObject("IIS://" & m_ServerName & "/w3svc")
		Set NewWebServer = w3svc.Create("IIsWebServer", cint(Index))
		If (Err.Number <> 0) Then
			' If call to Create failed then return fail
			TRACE "MakeSite|Failed to create site at index " & index 
			TRACE "MakeSite|error # " & err.number & " - " & err.description 
			MakeSite = -1
		Else
			
			'Site created
			MakeSite = index
			trace "MakeSite|A new site has been created with service tag " & index

			NewBindings = Array(0)
			NewBindings(0) = IpAddress & ":" & PortNum & ":" & HostName
			trace "MakeSite|Adding bindings " & IpAddress & _
			":" & PortNum & ":" & HostName
			NewWebServer.ServerBindings = NewBindings
			trace "MakeSite|Setting server comment"
			NewWebServer.ServerComment = HostName
		'	NewWebServer.KeyType = "IIsWebServer"
			trace "MakeSite|Saving bindings to metabse"
			NewWebServer.SetInfo

			' Now create the root directory object.
			trace "MakeSite|Setting root directory to: '"& rootdirectory &"'"
			Set NewDir = NewWebServer.Create("IIsWebVirtualDir", "ROOT")
			NewDir.Path = RootDirectory
			NewDir.AccessRead = true
			Err.Clear
			trace "MakeSite|Saving root directory Info"
			NewDir.SetInfo

			'Attempting to start new web server..."
			trace "MakeSite|Attempting to start the new service..."
			Err.Clear
			Set NewWebServer = GetObject("IIS://" & m_ServerName & "/w3svc/" & _
			Index)
			NewWebServer.Start
			if err.number <> 0 then
				trace "MakeSite|Could not start server IIS://" & m_ServerName & _
				"/w3svc/" & Index
				trace "MakeSite|" & err.description
			else
				trace "MakeSite|Server started sucsessfully"
			end if
			
		end if
	else
		
		'The Binding already exists!
		Trace "MakeSite|The binding specified alredy exists!"
		MakeSite = -1
	
	end if

	on error goto 0

end function

Public function DeleteSite(svc)

	on error resume next

	Trace "DeleteSite|Deleting service w3svc/" & svc

	Dim WebServiceObj 
	'Get the Web service object, which contains servers. 
	Set WebServiceObj = GetObject("IIS://"& m_ServerName &"/W3SVC") 

	if err.number <> 0 then
		trace "DeleteSite|Could not open IIS://"& m_ServerName &"/w3svc"
		DeleteSite = false
		Exit Function
	end if

	'Delete specified service 
	WebServiceObj.Delete "IIsWebServer", cstr(svc)
	if err.number = 0 then
		Deletesite = true
		Trace "DeleteSite|Service w3svc/" & svc & " deleted"
	else
		deletesite = false
		Trace "DeleteSite|Could not delete service w3svc/" & svc
		trace "DeleteSite|Error: " & err.description
	end if

end function

Public function AddBinding(svc,IpAddress,PortNum,HostName)
	
	on error resume next

	DIM sbind
	trace "AddBinding|Opening bindings for site w3svc/" & svc
	Set obj = GetObject("IIS://"& m_ServerName &"/w3svc/" & svc)
	servbind = Obj.Get("serverbindings")
	if err.number <> 0 then
		trace "AddBinding|Could not open service IIS://"& m_ServerName &"/w3svc/" & svc
		trace "AddBinding|Error: " & err.description
		addbinding = false
		Exit Function
	else
		trace "AddBinding|Opened service IIS://"& m_ServerName &"/w3svc/" & svc
		if not DuplicateBinding(IpAddress,PortNum,HostName) then
			addbinding = true
			REDIM preserve servbind(ubound(servbind) +1)
			'Add new binding to Array
			servbind(ubound(servbind)) = IpAddress & ":" & PortNum & ":" & HostName
			'Write server bindings back to metabase
			Obj.Put "serverbindings", servbind
			'Save Metabase
			obj.setinfo
			trace "AddBinding|Saving to metabase"
		else
			addbinding = false
			trace "AddBinding|Add binding failed"
		end if
	end if

end function

Public function RemoveBinding(svc,IpAddress,PortNum,HostName)
	
	on error resume next
	DIM sbind
	RemoveBinding = false 'Flag to show if delete is ok

	trace "RemoveBinding|Opening bindings for site w3svc/" & svc
	Set obj = GetObject("IIS://"& m_ServerName &"/w3svc/" & svc)
	servbind = Obj.Get("serverbindings")

	if err.number <> 0 then
		trace "RemoveBinding|Could not open service IIS://"& m_ServerName & _
		"/w3svc/" & svc
		trace "RemoveBinding|Error: " & err.description
		RemoveBinding = false
		Exit Function
	else

		trace "RemoveBinding|Opened service IIS://"& m_ServerName &"/w3svc/" & svc
		trace "RemoveBinding|Searching for binding (" &  IpAddress & ":" & PortNum & &
		":" & HostName & ")..."

		bind = array
		'iterate through binding for service tag
		for n = 0 to ubound(servbind)
			b = split(servbind(n),":")
			'Check to see if this is binding to delete
			if IpAddress = b(0) and 	PortNum = b(1) and HostName = b(2) then
				'Found Binding
				trace "RemoveBinding|Found binding - Binding #" & n & _
				" (" & servbind(n) & ") "
				trace "RemoveBinding|Remove binding sucsessful"
				RemoveBinding = true
			else
				trace "RemoveBinding|No Match - Binding #" & n & _
				" (" & servbind(n) & ")"
				'Binding is not deleted
				'Create new value in the array
				redim preserve bind(ubound(bind)+1)
				bind(ubound(bind)) = servbind(n)
			end if

		next
		
		if RemoveBinding = true then
			
			trace "RemoveBinding|Saving changes to metabase"
			'Writing new bindings
			Obj.Put "serverbindings", Bind
			'Save Metabase
			obj.setinfo
		
			'Sanity check
			if err.number <> 0 then
				trace "RemoveBinding|Could not remove w3svc object IIS://" & _
				m_ServerName & "/w3svc/" & svc
				trace "RemoveBinding|Error: " & err.description
				exit function
			end if

		else

			'Nothing to remove
			trace "RemoveBinding|Binding (" &  IpAddress & ":" & PortNum & _
			":" & HostName & ") not found on object IIS://" & m_ServerName & _
			"/w3svc/" & svc
		
		end if

	end if

end function

Public function BindingsList(svc)

	on error resume next			
	trace "BindingsList|Listing Bindings"
	dim bind
	redim bind(0)

	if len(svc) > 0 then 
		'A filter has been selected
		trace "BindingsList|List filtered by service tag " & svc
		trace "BindingsList|Opening w3svc object IIS://" & m_ServerName & _
		"/w3svc/" & svc
		Set obj = GetObject("IIS://"& m_ServerName &"/w3svc/" & svc)
		servbind = Obj.Get("serverbindings")

		if err.number <> 0 then
			trace "BindingsList|Open failed for w3svc object IIS://" & m_ServerName & _
			"/w3svc/" & svc
			trace "BindingsList|Error: " & err.description
			exit function
		end if

		for n = 0 to ubound(servbind)
			redim preserve bind(ubound(bind)+1)
			bind(ubound(bind)) = svc & ":" & servbind(n)
		next

	else

		'No filter has been selected - list all
		trace "BindingsList|Opening w3svc object IIS://" & m_ServerName & "/w3svc"
		Set w3svc = GetObject("IIS://" & m_ServerName & "/w3svc")
		'If the webserver loaded ok
		If Err.Number = 0 Then
			trace "BindingsList|Opened IIS://" & m_ServerName & "/w3svc object"
			'Iterate through the websites
			For Each WebServer in w3svc
				'If the class of the current object is a webserver
				If WebServer.Class = "IIsWebServer" Then
					'Load the bindings
					Bindings = WebServer.ServerBindings
					for n = 0 to ubound(Bindings)
						redim preserve bind(ubound(bind)+1)
						bind(ubound(bind)) = WebServer.name & _
						":" & Bindings(n)
					next
				End If
			Next
		else
		
			trace "BindingsList|Error opening " & "IIS://" & m_ServerName & _
			"/w3svc" & " - " &  err.description
	
		end if
	
	end if

	BindingsList = bind
  
end function

function IIBackup(bkupName)
	
	Dim ComputerObj, iFlags 

	IIBackup = true

	'on error resume next

	trace "Backup|Loading IIS://"& m_ServerName
	'Load the specified server

	Set ComputerObj = GetObject("IIS://" & m_ServerName) 

	if err.number <> 0 then
		trace "Backup|Could not open IIS://"& m_ServerName
		trace "Backup|Error: " & err.description
		IIBackup = false
		exit function
	end if

	trace "Backup|Loaded IIS://"& m_ServerName & " Ok"
	trace "Backup|Backing up metabase to file: " & bkupName
	
	'Make a backup of the metabase to filename bkupName	
	iFlags = (MD_BACKUP_SAVE_FIRST or MD_BACKUP_FORCE_BACKUP) 
	ComputerObj.Backup bkupName, MD_BACKUP_NEXT_VERSION, iFlags 

	if err.number <> 0 then
		trace "Backup|Backup of IIS://"& m_ServerName & " failed"
		trace "Backup|Error: " & err.description
		IIBackup = false
		exit function
	end if

	trace "Backup|Backup of IIS://"& m_ServerName & " ok"

end function

end class

%>
If you enjoyed this then have a look at these:
Cloaked Exploit Scanner Part I and Part II
Google 'exploit' - TCPUtil pt III
Open Source FTP Control
Ending Corporate SPAM
Web based classes
Backing up the IIS metabase.
What port is that?
Building your own IDS tripwire.
Credit card security
Dumping SQL data to a text file
Hunting down skript kiddies
Search Engine submission 'exploit'
Forced shutdown of a remote nt/2k server
Securing an installation of IIS 4. (No, seriously)
Remote DSN Connections, using WinAPIs and the registry
Scripting Internet Connections Under Window$