Programmatically set IIS Authentication for a page.

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