Question

We are developing a web application that uses forms authentication and the ActiveDirectoryMembershipProvider to authenticate users against the Active Directory. We soon found out that the provider does not allow a blank/empty password to be specified, even though this is perfectly legal in the Active Directory (provided a preventative password policy is not in place).

Courtesy of reflector:

private void CheckPassword(string password, int maxSize, string paramName)
{
    if (password == null)
    {
        throw new ArgumentNullException(paramName);
    }
    if (password.Trim().Length < 1)
    {
        throw new ArgumentException(SR.GetString("Parameter_can_not_be_empty", new object[] { paramName }), paramName);
    }
    if ((maxSize > 0) && (password.Length > maxSize))
    {
        throw new ArgumentException(SR.GetString("Parameter_too_long", new object[] { paramName, maxSize.ToString(CultureInfo.InvariantCulture) }), paramName);
    }
}

Short of writing our own custom Provider, is there any way to override this functionality using the magic of .NET?

Was it helpful?

Solution

I don't beleive you could change this behaviour without creating a derived class and overiding every method that calls the private CheckPassword method. I would not recomend this option however, i would recomend that you review your design and question whether it is approriate to allow blank passwords in your application. Whilst they are valid in AD it is unusual for this to be allowed in practice and it does impact other things in a windows network, e.g. i think the default settings for network file shares disallow any user with a blank password from connecting to the share.

OTHER TIPS

You could perhaps look at using impersonation but i don't know if you will have the same issue. If it's to authorise a user, then you could use impersonation to try and "impersonate" the user on the machine. I don't know if it helps but I was doing something similar to this the other week. Have put the code below if any of this helps.. :)

using System;  
using System.Runtime.InteropServices;  

public partial class Test_Index : System.Web.UI.Page {  
protected void Page_Load(object sender, EventArgs e)
{        
    IntPtr ptr = IntPtr.Zero;
    if (LogonUser("USERNAME", "", "LEAVE-THIS-BLANK", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, ref ptr))
    {
        using (System.Security.Principal.WindowsImpersonationContext context = new System.Security.Principal.WindowsIdentity(ptr).Impersonate())
        {
            try
            {
                // Do do something
            }
            catch (UnauthorizedAccessException ex)
            {
                // failed to do something
            }

            // un-impersonate user out
            context.Undo();
        }
    }
    else
    {
        Response.Write("login fail");
    }
}

#region imports

[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool CloseHandle(IntPtr handle);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr existingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr duplicateTokenHandle);

#endregion

#region logon consts

// logon types 
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;

// logon providers 
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_PROVIDER_WINNT50 = 3;
const int LOGON32_PROVIDER_WINNT40 = 2;
const int LOGON32_PROVIDER_WINNT35 = 1;
#endregion  }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top