To use Mixed Windows Authentication one of the step is to set set authentication on one page only to be Windows Integrated, but not “allow anonymous”.(see instructions here and here).
I wanted to do it from Web Setup Project. So I’ve created the class IISMetaDataHelper with the method SetIntegratedSecurityOnly
Sample of the call is
IISMetaDataHelper.SetIntegratedSecurityOnly(Site, VDir, “Admin/Security/WinLogin.aspx”)
Notice that .Net framework doesn’t have classes to handle IISMetaData properties and enum for AuthFlags property value. I’ve created those helper types as well.
Update: it is recommended to call folderRoot.RefreshCache() to make EVERYTHING work
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.DirectoryServices;
using System.Diagnostics;
using System.IO;
using System.Reflection;
//using FSHelperLib;
namespace FSCSharpLib.IISMetadata
{
/// <summary>
//see also IISChameleon.INETMGRHelper
/// Helper methods to access IIS Virtual directories
/// </summary>
/// <remarks>Code samples used are from ASP.NET IIS Chameleon Tool(http://www.123aspx.com/redir.aspx?res=33760 and
/// Creating Virtuals and reading Installed Sites on IIS with .Net(http://west-wind.com/weblog/posts/399.aspx ) </remarks>
public class IISMetaDataHelper
{
//For debugginh it is convinient to use adsutil.vbs http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/d3df4bc9-0954-459a-b5e6-7a8bc462960c.mspx
/*e.g commands
C:InetpubAdminScriptsCscript.exe adsutil.vbs ENUM W3SVC/1/root/vKnowledge/admin/Security/WinLogin.aspx
C:InetpubAdminScriptsCscript.exe adsutil.vbs CREATE W3SVC/1/root/vKnowledge/admin/Security/WinLogin.aspx
C:InetpubAdminScriptsCscript.exe adsutil.vbs SET W3SVC/1/root/vKnowledge/admin/Security/WinLogin.aspx/keyType IISWebFile
C:InetpubAdminScriptsCscript.exe adsutil.vbs delete W3SVC/1/root/vKnowledge/admin/Security/WinLogin.aspx
*/
/// <summary>
/// Concat parts of the path using Site Path in format @”/LM/W3SVC/1″ passed by Web Setup to path accepted by DirectoryEntry
/// </summary>
/// <param name=”SiteMetaPath”>Format @”/LM/W3SVC/1″</param>
/// <param name=”VDirRoot”>e.g vKnowledge</param>
/// <param name=”relPath”>e.g @”admin/Security/WinLogin.aspx”</param>
/// <returns>e.g IIS://localhost/W3SVC/1/root/vKnowledge/admin/Security/WinLogin.aspx</returns>
public static void SetIntegratedSecurityOnly(string SiteMetaPath, String VDirRoot, String relPath)
{
string MetabasePath = IISMetaPath(SiteMetaPath, VDirRoot, relPath);
SetIntegratedSecurityOnly(MetabasePath);
}
/// <summary>
/// Concat parts of the path using Site Path in format @”/LM/W3SVC/1″ passed by Web Setup to path accepted by DirectoryEntry
/// </summary>
/// <param name=”SiteMetaPath”>Format @”/LM/W3SVC/1″</param>
/// <param name=”VDirRoot”>e.g vKnowledge</param>
/// <param name=”relPath”>e.g @”admin/Security/WinLogin.aspx”</param>
/// <returns>e.g IIS://localhost/W3SVC/1/root/vKnowledge/admin/Security/WinLogin.aspx</returns>
public static string IISMetaPath(string SiteMetaPath, String VDirRoot, String relPath)
{
SiteMetaPath = SiteMetaPath.Replace(@”/LM/”, “localhost/”);
return @”IIS://” + SiteMetaPath + @”/root/” + VDirRoot + @”/” + relPath;
}
/// <summary>
/// SetIntegratedSecurityOnly
/// </summary>
/// <param name=”MetabasePath”>e.g IIS://localhost/W3SVC/1/root/vKnowledge/admin/Security/WinLogin.aspx</param>
public static void SetIntegratedSecurityOnly(string MetabasePath)
{
if (MetabasePath != string.Empty)
{
DirectoryEntry entry = null;
if (!DirectoryEntry.Exists(MetabasePath))
{ //Usually files are not explicitly added to the IIS metabase
//See http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic12899.aspx
string sFolderPath = StringHelper.LeftBeforeLast(MetabasePath, @”/”);//metabasePath.Substring(0,metabasePath.LastIndexOf(“/”));
string sEntryName = StringHelper.RightAfterLast(MetabasePath, @”/”);// metabasePath.Substring(metabasePath.LastIndexOf(“/”) + 1);
DirectoryEntry folder = new DirectoryEntry(sFolderPath);
DebugHelper.PrintDirectoryEntryProperties(folder, sFolderPath);
//SchemaClassNames are listed in http://blog.crowe.co.nz/archive/2006/06/01.aspx
string SchemaClassName = “IIsObject”;
//can’t assign “IIsWebFile” directly, causes HRESULT: 0x8000500F exception. E_ADS_SCHEMA_VIOLATION – The attempted action violates the directory service schema rules”.
// see http://groups.google.com.au/group/microsoft.public.adsi.general/browse_frm/thread/3b339d218e673aca/050974e5903530e3
entry = folder.Children.Add(sEntryName, SchemaClassName);
//Fortunately ADSUTIL shows the WARNING: The Object Type of this object was not specified or was specified as IIsObject.
//This means that you will not be able to set or get properties on the object until the KeyType property is set.
entry.Properties[MetabasePropertyNames.keyType].Value = “IIsWebFile”;
folder.CommitChanges();
entry.CommitChanges();
}
//must be created as new, even if entry was just created using Children.Add
entry = new DirectoryEntry(MetabasePath);
DebugHelper.PrintDirectoryEntryProperties(entry, MetabasePath);
AuthFlags nAuthFlags = (AuthFlags)(entry.Properties[MetabasePropertyNames.AuthFlags][0]);
nAuthFlags = nAuthFlags & ~AuthFlags.AuthAnonymous; //clear anonymous
nAuthFlags = nAuthFlags | AuthFlags.AuthNTLM; //Add Integrated
entry.Properties[MetabasePropertyNames.AuthFlags][0] = nAuthFlags;
// Chameleon sets Properties[“AuthNTLM”] and [“AuthAnonymous”] -does it work?
//virtualDirectory.Properties[“AuthNTLM”][0] = parametros.AuthNTLM;
//virtualDirectory.Properties[“AuthAnonymous”][0] = parametros.AuthAnonymous;
entry.CommitChanges();
}
}
}//class
public class MetabasePropertyNames
{// from http://technet2.microsoft.com/WindowsServer/en/Library/271ae19b-853f-4672-b743-5ba126e902db1033.mspx?mfr=true
//TODO add all Properties
public const string AuthFlags = “AuthFlags”;
public const string keyType = “keyType”;
}
[FlagsAttribute()]
public enum AuthFlags
{//from http://technet2.microsoft.com/WindowsServer/en/Library/271ae19b-853f-4672-b743-5ba126e902db1033.mspx?mfr=true
AuthAnonymous=1,
AuthBasic=2,
AuthNTLM = 4,
AuthMD5 = 16,
AuthPassport=64
}
//Possible exceptions from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/adsi/adsi/generic_adsi_error_codes.asp
// 0x80005006 – The property does not exist, or it does not exist at the access location where you are attempting to set it.
//0x8000500C-The data type of the property is different than the data type to which you are attempting to set it.
//0x8000500F exception. E_ADS_SCHEMA_VIOLATION – The attempted action violates the directory service schema rules”.
}
The class uses my DebugHelper class and My StringHelper class
.