0

I have a PHP website running as an App on IIS.

The app is using a specific Identity that runs all php-cgi.exe processes under NetworkService user that has access to the AD server.

There's also another .NET app in the IIS where it's using the same identity and can log into the AD using the class System.Web.Security.FormsAuthentication and uses Forms Authentication in the Authentication settings in IIS. I tried copying the settings over but to no avail.

The .NET code:

...
using System.Web.Security.Membership.ValidateUser;
...

public ActionResult Login(Login model, string route)
{
    if (Membership.ValidateUser(model.Username, model.Password)) {
        FormsAuthentication.SetAuthCookie(model.Username);
        return Redirect(route);
    }

    return RedirectHome();
}

My code running on IIS with PHP CGI, impersonate is on on IIS level and php.ini level:

public function login()
{
    $ldapHost = 'ldap://spacemudd-ad';

    // PHP should use server's (iis) credentials when connecting. (impersonate)
    $connection = ldap_connect($ldapHost);

    // This always fails.
    //
    // "ldap_bind(): Unable to bind to server: Can't contact LDAP server"
    //
    // I believe due to the php-cgi.exe not sending the request
    // to the AD server through the IdentityPool's user (NetworkService)
    // even though in the TaskManager, the php-cgi.exe shows the owner is
    // NetworkService?
    //
    $ldapBind = ldap_bind($connection);

    // TODO: Search the AD directory for the user to be authenticated.
}

php.ini configuration:

fastcgi.impersonate = 1

ref. questions:


Update 24-11-2018: The sysadmin gave me these information:

config.md:

 <add name="ADConnectionString" connectionString="LDAP://spacelantern-central/DC=spacelantern,DC=com" />

    <membership defaultProvider="ADMembershipProvider">
      <providers>
        <clear />
        <add name="ADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider" connectionStringName="ADConnectionString" attributeMapUsername="sAMAccountName" />
      </providers>
    </membership>

code.md:

if (Membership.ValidateUser("userid", "password"))
{
    // 
}
Shafiq al-Shaar
  • 1,292
  • 14
  • 22

1 Answers1

0

I suspect you have two problems. First, this:

ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, $ldapPort);

What is the value in $ldapPort? The name of that variable suggests that it contains the TCP port to connect to, but that is not what LDAP_OPT_PROTOCOL_VERSION is for.

LDAP_OPT_PROTOCOL_VERSION is for the LDAP version to use when communicating. For AD, you can set it to 3, since AD supports LDAPv3:

ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, 3);

Second, if you need to connect to a different port than the default (389), then you need to pass it in the call to ldap_connect:

$connection = @ldap_connect($ldapHost, $ldapPort);
Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84
  • Actually using the port-parameter in ldap_connect is deprecated for quite a while. You should use an URI as the only parameter to ldap_connect like this: "ldap://ldap.example.com:port". That's the only way to also specify usage of ldaps-protocol – heiglandreas Nov 21 '18 at 05:02
  • @heiglandreas [The documentation](http://php.net/manual/en/function.ldap-connect.php) doesn't say anything about it being deprecated. Although it does say that the port is "Not used when using LDAP URIs". So you can either do `ldap_connect($ldapHost, $ldapPort)` or `ldap_connect("LDAP://" . $ldapHost . ":" . $ldapPort)`. – Gabriel Luci Nov 21 '18 at 13:21
  • Internally `ldap_connect` creates an LDAP_URI when only host and port are provided. So when you provide a host and a port only that involves more work to be done. It's only still available to be backwards compatible. But you are right, the documentation should be adapted! – heiglandreas Nov 21 '18 at 15:40
  • @GabrielLuci Hey Gabriel, Thank you for the reply. I tinkered a lot with the issue today. I updated my question as I have now better understood my situation. – Shafiq al-Shaar Nov 21 '18 at 21:00
  • `ldap_bind()` does not use impersonation when connecting. [The documentation](http://php.net/manual/en/function.ldap-bind.php) says "The bind_rdn can also be left empty for an anonymous bind." So it's trying to connect anonymously, and AD is saying no. – Gabriel Luci Nov 21 '18 at 21:58
  • But don't you have to authenticate the user's password? You would have to do that with `ldap_bind()` anyway. – Gabriel Luci Nov 21 '18 at 21:58
  • @GabrielLuci Apparently the anonymous bind would in fact use the server's username, the domain user. [This answer to this question references it.](https://stackoverflow.com/questions/25039083/php-ldap-binding-ad-with-the-servers-user-account). Though, the `REMOTE_USER` variable in `$_SERVER` is always the user that is running the IIS instance.. and I seem to be unable to change it to login through a different user. FYI, I don't have a username/password for the administer AD. This privilege is given to the NetworkService domain account on Windows. – Shafiq al-Shaar Nov 22 '18 at 15:57
  • Are you sure that person is right? There is no reference to that behaviour in the documentation. Try using any username and password (even your own if you have an account) and test to see if it works that way. – Gabriel Luci Nov 22 '18 at 16:41
  • @GabrielLuci The funny thing is... it says `can't connect to LDAP` not even invalid credentials. So in a way, the AD server is not even accepting a connection to be made to authenticate. While the .NET app is supposedly connecting to the AD server by impersonating the NetworkService domain user. – Shafiq al-Shaar Nov 23 '18 at 21:56
  • Well that's different then. There are 4 LDAP ports that AD can use. Maybe not all 4 are open. Look at your `ActiveDirectoryMembershipProvider` settings in the web.config of your ASP.NET app, specifically the connection string for AD. What does it say? – Gabriel Luci Nov 23 '18 at 23:49
  • Or, if you're using one of the encrypted ports (636 or 3269) then maybe the certificate is not trusted. – Gabriel Luci Nov 23 '18 at 23:53
  • @GabrielLuci Hey Gabriel. Thanks. I updated my answer with `ADMembershipProvider` details. This is really puzzling. – Shafiq al-Shaar Nov 24 '18 at 07:43
  • Use `LDAP://spacelantern-central` as your `$ldapHost` – Gabriel Luci Nov 24 '18 at 12:37