I'm looking for a way to authenticate users through LDAP with PHP (with Active Directory being the provider). Ideally, it should be able to run on IIS 7 (adLDAP does it on Apache). Anyone had done anything similar, with success?
Edit: I'd prefer a library/class with code that's ready to go... It'd be silly to invent the wheel when someone has already done so.
Importing a whole library seems inefficient when all you need is essentially two lines of code...
$ldap = ldap_connect("ldap.example.com");
if ($bind = ldap_bind($ldap, $_POST['username'], $_POST['password'])) {
// log them in!
} else {
// error message
}
You would think that simply authenticating a user in Active Directory would be a pretty simple process using LDAP in PHP without the need for a library. But there are a lot of things that can complicate it pretty fast:
You must validate input. An empty username/password would pass otherwise.
You should ensure the username/password is properly encoded when binding.
You should be encrypting the connection using TLS.
Using separate LDAP servers for redundancy in case one is down.
Getting an informative error message if authentication fails.
It's actually easier in most cases to use a LDAP library supporting the above. I ultimately ended up rolling my own library which handles all the above points: LdapTools (Well, not just for authentication, it can do much more). It can be used like the following:
use LdapTools\Configuration;
use LdapTools\DomainConfiguration;
use LdapTools\LdapManager;
$domain = (new DomainConfiguration('example.com'))
->setUsername('username') # A separate AD service account used by your app
->setPassword('password')
->setServers(['dc1', 'dc2', 'dc3'])
->setUseTls(true);
$config = new Configuration($domain);
$ldap = new LdapManager($config);
if (!$ldap->authenticate($username, $password, $message)) {
echo "Error: $message";
} else {
// Do something...
}
The authenticate call above will:
Validate that neither the username or password is empty.
Ensure the username/password is properly encoded (UTF-8 by default)
Try an alternate LDAP server in case one is down.
Encrypt the authentication request using TLS.
Provide additional information if it failed (ie. locked/disabled account, etc)
There are other libraries to do this too (Such as Adldap2). However, I felt compelled enough to provide some additional information as the most up-voted answer is actually a security risk to rely on with no input validation done and not using TLS.
I do this simply by passing the user credentials to ldap_bind().
http://php.net/manual/en/function.ldap-bind.php
If the account can bind to LDAP, it's valid; if it can't, it's not. If all you're doing is authentication (not account management), I don't see the need for a library.
I like the Zend_Ldap Class, you can use only this class in your project, without the Zend Framework.
PHP has libraries: http://ca.php.net/ldap
PEAR also has a number of packages: http://pear.php.net/search.php?q=ldap&in=packages&x=0&y=0
I haven't used either, but I was going to at one point and they seemed like they should work.
For those looking for a complete example check out http://www.exchangecore.com/blog/how-use-ldap-active-directory-authentication-php/.
I have tested this connecting to both Windows Server 2003 and Windows Server 2008 R2 domain controllers from a Windows Server 2003 Web Server (IIS6) and from a windows server 2012 enterprise running IIS 8.
Related
I'm using a form on my website to send an email using the PEAR mail function. The email will send via gmail as described here - http://www.phpmaniac.net/wiki/index.php/Pear_Mail
I will therefore need to include something like the:
<?php
$smtp_params["host"] = "smtp.gmail.com";
$smtp_params["port"] = "25";
$smtp_params["auth"] = true;
$smtp_params["username"] = "user#gmail.com";
$smtp_params["password"] = "pass";
?>
Is it secure to put my username and password in the script like that? Obviously you wouldn't be able to see server-side script like this using 'View Source', but could you grab the source files via a web clipper or something and read the script that way? Thanks
If someone accidently disbles php parsing on you apache, your file will be served as plain text, so i like to keep passwords in config files outside my docroot... Just in case. Several times when building a new php modual for apche i forgot to copy a php.conf file into my httpd/conf.d/ direcoty and started apache without php. i
In theory, any insecure connection can be snooped. However, in this case it would need to be intercepted between your server and gmails smtp server. Also, even if you securly sent the email to the mail server, you have no certainty that they will connect securely to deliver it or the inteded receipient will securely check their email account.
In this case you just care about your basic auth being snooped. Use gmails secure ssl connection
Be safe by assuming all email communication is not secure. (unless you encrypt the message)
You should certainly use SSL/TLS for the connection - simply because sending passwords in plaintext over an unencrypted channel is a bad idea.
The login data inside your PHP script is safe as long as the PHP interpreter works properly and there are no security holes in your PHP scripts that allow an attacker to view the sourcecode of your PHP files.
Against the risk of misconfiguration causing PHP sourcecode to be visible an easy improvement would be storing the config file outside the document root.
I'd like to access a camera through it's Telnet capability. The problem is, it has Password-protection. This is no problem when doing it via Terminal, as I just use telnet 10.30.blah.blah then enter my password when prompted. But in php, I don't see the opportunity to input a password.
$con = fsockopen("10.30.blah.blah", 25);
$msg = "camera move left";
fwrite($con, $msg);
Anybody have any ideas?
UPDATE: I tried just using fputs to output the password as #Cfreak said, but still to no avail. If I do exactly what the script is trying in terminal, it works. Here's the code now:
$con = fsockopen("10.30.blah.blah", 23, $errno, $errstr, 30);
$pass = "admin";
sleep(5);
fputs($con, $pass);
sleep(5);
$msg = "camera move left";
fputs($con, $msg);
UPDATE: Found that I needed a \r at the end of my $msg variable. Thanks for the help!
You just output it. Some examples I've seen use fputs. You might have to sleep for a second to make sure the prompt comes up. There's actually an example in the comments on the fsockopen manual page: http://php.net/manual/en/function.fsockopen.php
Really though I'd recommend looking for a module that does this. A quick google shows there are several out there. I don't want to recommend a particular one because I haven't used any of them.
It would be a better idea to use proc_open to run telnet rather than trying to implement your own protocol stack (there's more to telnet than just reading and writing from sockets). Indeed, telnet is inherently insecure and should be avoided if at all possible. (basic http authentication without SSL is just as bad).
However unlike SMTP or HTTP, it's not a very complex protocol - and it should be fairly straightforward to implement a simple client using sockets. The code you've provided neither reads the username / password prompt nor writes responses to the socket - so either you've got some very strange ideas about how to login over telnet or the code snippet is irrelevant.
Cfreak said "You might have to sleep for a second to make sure the prompt comes up" - this is not correct - you must wait for the username prompt, the password prompt and the initial CLI prompt before sending a response using telnet. Indeed there is a whole programming language (expect) written to work around this kind of odd behaviour in telnet.
and BTW, telnet runs on port 23 - port 25 is used for SMTP
There is a class implementing loginc over telnet right here :
http://www.dali.net.nz/Telnet.class.php.txt
See function login($username, $password).
Can any one please let me explain step by step implementation for LDAP on my site using PHP
http://www.php.net/manual/en/ldap.installation.php
LDAP support in PHP is not enabled by default. You will need to use the --with-ldap[=DIR] configuration option when compiling PHP to enable LDAP support. DIR is the LDAP base install directory. To enable SASL support, be sure --with-ldap-sasl[=DIR] is used, and that sasl.h exists on the system.
First make sure you have PHP's LDAP extension installed, as #The MYYN suggests. To implement an LDAP-based authentication mechanism I recommend that you use Zend_Auth and its adapter for LDAP. Further operations can be handled with Zend_Ldap.
It seems that your question is still not answered, because you did not choose an answer.
So if you want to know how to authenticate a user, you can do it this way :
$userFound = false;
$ds = ldap_connect('my.ldap.com');
if ($ds)
{
// Anonymous bind
ldap_bind($ds);
// Search the DN of the user
$searchRes = ldap_search($ds, 'ou=people,dc=my_company,dc=com', 'uid=your_user_uid');
$info = ldap_get_entries($ds, $searchRes);
// If the search returned at least one result, try to bind to the server
// using the DN you just get, and the password provided by you user
if ($info['count'] < 0)
$userFound = ldap_bind($ds, $info[0]['dn'], $password);
ldap_close($ds);
}
var_dump($userFound);
Note that, as miku said, you have to install LDAP. It is not installed by default.
This code below checks for the user's credentials against ldap
<?php
$ldaphost = "ldap.domain.com";
$ldapport = 389;
$ds = ldap_connect($ldaphost, $ldapport)
or die("Could not connect to $ldaphost");
if ($ds)
{
$username = "johndoe#domain.com";
$upasswd = "pass";
$ldapbind = ldap_bind($ds, $username, $upasswd);
if ($ldapbind)
{print "Congratulations! $username is authenticated.";}
else
{print "Access Denied!";}
}
?>
My users use Firefox and IE, and I know that can pass their ActiveDirectory credentials seamlessly.
I just want to check the AD group to see if that username is found in there, if so, display the page, otherwise prompt to enter in credentials.
Since our users are already logged into the domain controller, I want to grab their username, check to see if it was found in the specific group, then let them in, otherwise prompt user to input credentials. How is this possible?
You actually do not need to communicate with the Active Directory server from your PP code to achieve what you want given the fact that you use IIS as your web server.
The key word here is Integrated Windows Authentication - that's the wording djn looked for. If this option is turned on (and anonymous access is denied) IIS will check the supplied credentials against the Active Directory and the NTFS filesystem privileges of the requested resources. You can therefore control access to your files using simple NTFS access control mechanisms.
If your users use IE they even don't have to type in their credentials as this is done automatically via so called SPNEGO (Simple and Protected GSSAPI Negotiation Mechanism) and its underlying mechanisms Kerberos or NTLMSSP depending on what your client and server is capable of processing.
As far as I know Firefox is able to hand over the Windows logon credentials to your server automatically too. You ony have to adjust a configuration option to turn on that feature - don't know if this information is still valid with Firefox 3.5.x.
If you're running Apache on a *nix-system you'll have to resort to some server-side-module to handle a Integrated Windows Authentication-like system. Possible options are (don't know whether they are actually still maintained or stable):
mod_auth_ntlm_winbind
mod_auth_kerb
mod_ntlm
For Apache on Windows there are:
mod_ntlm (outdated; not the same as mod_ntlm above)
mod_auth_sspi (successor of mod_ntlm)
Please be aware that most of these modules seem to be very old.
Working just now on a similar setup: I skipped all of that LDAP stuff having the web server authenticating the client with AD before letting him in (sorry, I can't remember what's this called in the M$ alternate universe).
If the client reaches the PHP script he's in AD and I have his username both in $_SERVER["AUTH_USER"] and in $_SERVER["LOGON_USER"], otherwise he never gets to the script.
This question is in line with this question, I am trying to connect to secure FTP Server and it is not able to connect, wierd part is that I am able to do ssh and connect to the server but when I try to do it from php code using few different approaches but it is not working
Approaches:
FTP Wrappers
ftp_connect & ftp_login
ftp_ssl_connect
ssh2_sftp
ssh2-scp-send & ssh2-scp-receive -- Have not tried this approach yet but recommended in comments portion and so would work on this and will post updates later.
Code for Approach 1:
$ftp_server = "ftp://username:password#192.168.1.1:21/{$log_file_name}";
$opts = array('ftp' => array('overwrite' => TRUE));
$context = stream_context_create($opts);
$put_file = file_put_contents($ftp_server, $response, LOCK_EX,$context);
Here also am not able to connect to secure FTP Server, any suggestions as to why it is not able to connect ?
Code for Approach 2:
ftp_server = 'www.server.com';
$conn_id = ftp_connect($ftp_server) or die ("Cannot connect to host");
//Program dies out here and give error message "Cannot connect to host",
//but why ftp_login does not work here, Any Suggestions ?
$ftp_user_name = "login";
$ftp_user_pass = "password";
// login with username and password
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
// check connection and login result
if ((!$conn_id) || (!$login_result))
{ echo "FTP connection has encountered an error!";
echo "Attempted to connect to $ftp_server for user $ftp_user_name....";
//exit;
} else
{
echo "Connected to $ftp_server, for user $ftp_user_name".".....";
}
Code for Approach 3:
Here am using same code as approach 1 but instead of ftp_connect, am using ftp_ssl_connect
Code for Approach 4:
$connection = ssh2_connect('www.server.com', 22);
ssh2_auth_password($connection, 'login', 'password');
$sftp = ssh2_sftp($connection);
//exit();
$stream = fopen("ssh2.sftp://$sftp/path/to/file", 'r');
Can anyone advise why am I not able to connect to secure FTP Server using above approaches but still am able to do so using ssh ?
Are there any other approaches to connect to secure FTP Server using php ?
UPDATE:
Q1. I tried again using ftp_connect but it just died out and why does it dies out, what are the scenarios in which ftp_connect dies out ?
Q2. Do we have only this approaches to connect to the server or are there any other which we can implement ?
Q3. Is this php language related that it does not support secure FTP Connection ? OR there is any other way of doing this using php, if yes than do provide different approaches as it would be very helpful.
UPDATE 1:
I was trying to google more on the issue and it seems that if ftp_connect does not work than firewall could be one of the reason for it. I am not totally sure if that is the case but I am researching more on it and post an update in here if I find anything useful.
Possible Solution :
Problem
If I remove the "or die" then you get the error:
When running from a webpage:
Warning: ftp_login() expects parameter 1 to be resource, boolean given in /var/www/ftp_test.php on line 28
var_dump($conn_id); returns bool(false).
From command line /usr/bin/php /var/www/ftp_test.php
var_dump($conn_id); returns resource(4) of type (FTP Buffer).
Script completes.
Solution 1
This could be one solution :
Try to turn off selinux and here is the way or Search : How to disable selinux for turning it off temporarily or permanently.
Solution 2
If you don't want to turn off selinux completely, you might get what you need by just setting the httpd_can_network_connect using the setsebool command.
Verify that it was previously set to "off":
getsebool httpd_can_network_connect
Set it to "on":
setsebool httpd_can_network_connect=1
Turn selinux back on:
setenforce 1
Check to be sure php ftp_connect still works when running under httpd.
Set the policy (-P) to "on" so it persists over a reboot:
setsebool -P httpd_can_network_connect=1
Solution 3
There could also be issue with company firewall. Make sure it is configured properly and has access rights set properly.
Solution 4
Another approach is to use cURL : libcurl as it can be used to connect and communicate to many different types of servers with many different types of protocols
Solution 5
There is open source project called PHP Secure Communication Library (phpspeclib) which can be also used to establish secure connection to FTP Server.
Many cheap webhoster will not give you ssh (hence no ftp via ssh aka
sftp) but only ssl-secured ftp aka ftps (see here). You might
have that problem. As others suggested, use filezilla or
another ftp client to test your credits and chosen security method
beforehand.
ftp_ssl_connect() at least under windows will be a long journey,
since you have to compile your own php binaries, see here.
As this php contributor rightfully points out, no secure
connection is secure, as long as you don't know, who you are talking
too, aka „peer certification“ through valid certificates.
phpseclib is probably your best bet. But I haven't figure out, how to
ensure, it uses peer verification (guessing, the truth is in
openssl.conf ...)
So even at the time of writing, I wonder more than ever, if
peer-validated ftps (ftp with ssl/tls authentification) is possible... also see my question here.
As for ´ftp via ssh´ alias ´sftp´: No direct advice, but note, that many cheap 'non-dedicated server' webhosts do not support it (which is bad). Company firewalls might block the relevant ports.
As for 'ftp using ssl/tls' alias 'ftps': Your answer is here. Don't waste time on ftp_ssl_connect() :-)
(Yes, it's poorly documented on the php site, to say the least)
This page has what you seek (I think)
http://kevin.vanzonneveld.net/techblog/article/make_ssh_connections_with_php/
and here are the manual pages
http://php.net/manual/en/book.ssh2.php
I, too, encountered quite a lot of issues when dealing with encrypted connections.
First thing is to check the protocol you are looking to use. Secure FTP is most commonly refearing to FTP over SHH but can also mean SCP, SFTP or FTPS.
One way to figure out is to check connecting using a client like filezilla.
If the protocol is handled via a PHP module, the best approach is indeed, to use it. In this case, you need to make sure that, in addition to the protocol-related one, the OPENSSL module is installed for php.
There are some cases where the module support still won't work. In this case, using the libcurl module is one option. This is the case for instance when you need to use a client certificate.
Unfortunately, here again, you may encounter some problems due to the partial support of libcurl in the php module. One scenario I experimented is when the server certificate is judged invalid by the module.
The last solution I usually use is to run the curl binary from an exec statement, for the later case using the "-k" switch.
I tried the phpseclib library and it works in Windows and Linux.
If you are using composer, just add in your require section :
"phpseclib/phpseclib": "0.3.*#dev"
And then, you can do this : http://phpseclib.sourceforge.net/sftp/examples.html#put