how to add an Active directory authenfication password with PHP? - php

I come to you because I have a little problem with an Active directory server, indeed I can connect to get my users ... when I add a user with the AD software, I assign him a password and this one is enabled for authentication in PHP with a form, nothing abnormal.
The problem is that when I add a user directly with PHP I use this code
$ldapconn=ldap_connect("adress");
$ldapbind=ldap_bind($ldapconn, "local", "test");
$cn = $info["cn"][0] = "test test ";
$info["sn"][0] ="test ";
$info["givenname"][0] ="test ";
$info["displayname"][0] ="test test ";
$info["name"][0] ="test test ";
$info["userprincipalname"][0] = "test #test .test ";
$info["samaccountname"][0] = "ttest ";
$info["objectClass"][0]="top";
$info["objectClass"][1]="person";
$info["objectClass"][2]="organizationalPerson";
$info["objectClass"][3]="user";
$info["objectCategory"][0] ="CN=Person,CN=Schema,CN=Configuration,DC=test
,DC=test ";
$info['userPassword'][0] = "test ";
// add entries
$r = ldap_add($ldapconn,"CN=".$cn.",OU=Utilisateurs,DC=test ,DC=test ", $info);
My user is correctly added but php authentication is not done, my user doesn't have an authentication password but a password that should be used for something else, I read on the net that $info['userPassword'] allows to create a password that is not usable for authentication. Someone would have the exact attribute in order to create this password please.
Thank you in advance for your help.
I also tried with the attribute $info['unicodePwd'] but I get an error message
" Add: Server is unwilling to perform ".

The userPassword attribute sometimes works, but the unicodePwd is the real attribute.
There are a couple caveats:
You have to be connected to AD via an encrypted connection. That means LDAP over SSL (LDAPS). So in your call to ldap_connect, you need to use ldaps://example.com. This can open a can of worms since the SSL certificate sent by the server needs to be trusted by your app. There are some comments on the documentation page that can help there.
The format of the value you assigned to unicodePwd must be:
specified in a UTF-16 encoded Unicode string containing the password surrounded by quotation marks, which has been BER-encoded as an octet string per the Object(Replica-Link) syntax.
There is also an example of this on the documentation page for ldap-mod-replace:
$newPassword = "MyPassword";
$newPassword = "\"" . $newPassword . "\"";
$len = strlen($newPassword);
for ($i = 0; $i < $len; $i++)
$newPassw .= "{$newPassword{$i}}\000";
$newPassword = $newPassw;
$userdata["unicodepwd"] = $newPassword;
$result = ldap_mod_replace($ad, $userDn, $userdata);
if ($result) echo "User modified!" ;
else echo "There was a problem!";
You may have to use ldap_mod_replace to set the password after creating the account first (rather than using $info['unicodepwd'][0] while creating the account). In my experience, I've always had to create the account first, then set the password.
But because of having no password at first, accounts are usually disabled (depending on your policies). So you will likely have to set the userAccountControl attribute to 512 (NORMAL_ACCOUNT) to enable it after you've set the password.

Thanks to you for your answer, I tried with your solution by not putting the'[unicodepwd]' and using "ldap_mod_replace" afterwards but I get an error message "server is unwilling to perform".
I think my server is configured in a specific way.
I found another solution, I use the "Adldap2" tool ( https://adldap2.github.io/Adldap2/#/?id=what-is-adldap2), which contains all the functions necessary to use LDAP with PHP.
I recommend it to anyone who has difficulties with Active directory .
For example, my problem was solved with this code:
enter code include __DIR__ . '/vendor/autoload.php';
$config = [
// Mandatory Configuration Options
'hosts' => ['testServer'],
'base_dn' => 'dc=test,dc=test',
'username' => 'test#test.test',
'password' => 'test',
'account_suffix' => '#test.test',
'port' => 636,
'use_ssl' => true,
];
$ad = new Adldap\Adldap();
$connectionName = 'my-connection';
$ad->addProvider($config, $connectionName);
try {
$provider = $ad->connect($connectionName);
echo"Connection ok <br>" ;
// Great, we're connected!
} catch (Adldap\Auth\BindException $e) {
// Failed to connect.
echo"Connection failed<br>" ;
}
$user = $provider->make()->user([
'cn' => 'test test ',
'userprincipalname' => 'test#test.test',
'accountExpires'=> 132188680854770000
]);
$user->setDn("CN=test tes ,OU=test ,DC=test,DC=test");
$dn = $user->getDn();
$user->setDisplayName('test test ');
$user->setAccountName('ttest');
$user->setFirstName('test');
$user->setLastName('test');
$attribut = $user->getAttributes();
var_dump($attribut);
$user->setEmail('test#test.test');
// Save the new user.
// Enable the new user (using user account control).
if ($user->save()) {
// Enable the new user (using user account control).
$user->setUserAccountControl(66048);
// Set new user password
$user->setPassword('test');
// Save the user.
if($user->save()) {
// The password was saved successfully.
}
}
hope this can helps :)

Related

Changing (not resetting) a users password using PHP LDAP

I'm trying to change a users password inside an Microsoft active directory using php-ldap. The problem is when trying to change the password with ldap_mod_replace it's not changing but resetting the password and that's not what I want, because my users are not permitted to reset their own password.
The active directory is based on a Microsoft server 2016, my application is running on an IIS webserver using PHP 7.2.
// open LDAP connection
$ldap_connection = $this->connectToActiveDirectory();
if (#ldap_bind($ldap_connection, $this->ldap_username . '#' . env('LDAP_DOMAIN', 'localhost'), $request->oldPassword)) {
// LDAP connection established
$dn = $request->userdn; // distinguished name of user
/*
The DC requires that the password value be specified in a UTF-16 encoded Unicode
string containing the password surrounded by quotation marks, which has been BER-encoded
as an octet string per the Object(Replica-Link) syntax.
*/
$newPassword = "\"" .$request->password. "\"";
$utf16Password = ""; // converted password
$passwordLength = strlen($newPassword);
for ($i = 0; $i < $passwordLength; $i++) {
$utf16Password .= "{$newPassword{$i}}\000";
}
$passwordEntry = array('unicodePwd' => $utf16Password);
// Set new password
if(#ldap_mod_replace($ldap_connection, $dn, $passwordEntry)) {
// Successful
} else {
// Error, probably not enough permissions
return back(); // Redirect user to previous page
}
ldap_unbind($ldap_connection); // Close LDAP connection
return redirect('/logout'); // Redirect user to logout
}
I want to change the password and not reset it, and I can't find a solution. Maybe some of you have experienced this problem, I'm thankful for any help!
According to the documentation for the unicodePwd attribute, this is how you do it:
If the Modify request contains a delete operation containing a value Vdel for unicodePwd followed by an add operation containing a value Vadd for unicodePwd, the server considers the request to be a request to change the password. ... Vdel is the old password, while Vadd is the new password.
In short, you need to delete the value and add the value in one LDAP request. In PHP, that means using the ldap_modify_batch function. In fact, in that documentation, there is an example of how to change a password:
<?php
function adifyPw($pw)
{
return iconv("UTF-8", "UTF-16LE", '"' . $pw . '"');
}
$dn = "cn=Jack Smith-Jones,ou=Wizards,dc=ad,dc=example,dc=com";
$modifs = [
[
"attrib" => "unicodePwd",
"modtype" => LDAP_MODIFY_BATCH_REMOVE,
"values" => [adifyPw("Tr0ub4dor&3")],
],
[
"attrib" => "unicodePwd",
"modtype" => LDAP_MODIFY_BATCH_ADD,
"values" => [adifyPw("correct horse battery staple")],
],
];
ldap_modify_batch($connection, $dn, $modifs);

creating a customer login function using the prestashop webservice

I'm currently working on an application that makes use of the prestashop webservice. This means that the application i'm building is an extension of an existing prestashop application. The connection between both applications is through the prestashop webservice
Currently i'm trying to create a login script for thecustomers. The email and password are obtained from the database through the webservice and i'm able to filter the inputs with the existing row's. So when filling in login#test.com. The filter will only obtain the row with that email address.
The problem i'm having is with the password. Prestashop uses a _COOKIE_KEY_ together with anmd5() to encrypt passwords. See this link for more information: link
So i've been trying some different things for a while to check the inputted password with the customers password but i haven't found the solution yet.
Take a look at the code below:
<?php
require_once('./PSWebServiceLibrary.php');
/**
* get information from PrestaShop
*/
$webService = new PrestaShopWebservice($url, $key, $debug);
define('_COOKIE_KEY_', '...');
$email = "login#test.nl";
define('password', "test");
$md5passwd = md5(_COOKIE_KEY_ . password);
$opt = array(
"resource" => "customers",
"display" => "[email , passwd]",
"filter[email]" => "$email"
);
$optPass = array(
"resource" => "customers",
"display" => "[email]",
"filter[email]" => "$email",
"filter[passwd]" => "$md5passwd"
);
$jsonPass = ($webService->get( $optPass ));
//json encode it
$jsonPasswd = json_encode($jsonPass);
echo($jsonPasswd);
if(password_verify($md5passwd, $jsonPasswd)) {
echo "password is valid";
} else {
echo "password is not valid";
}
$jsonUrl = ($webService->get( $opt ));
//json encode it
$json = json_encode($jsonUrl);
echo($json);
As you can see i've been trying out things like the password_verify and the md5() but i can't quite get it. So is there anyone who has done this or who knows how to create a correct login script on the prestashop webservice?
Update -- 12/1/2017
So after doing some research i've come up with a new way of checking the user input. First the code checks the email and if it's true it will continue with checking the password input. But the problem i'm having is with the password and the password encryption of prestashop. I'm not able to compare the two hashes together. The first hash would be the hash from the database were the second hash is the user input password. The input would need a hash() function from prestashop. But i can't quite get to the right hash sequence of prestashop.
I've searched all over the internet for this but couldn't find a decent solution for logging in through the prestashop webservice. The script i've created for logging in is shown below.
require_once('./PSWebServiceLibrary.php');
/**
* get information from PrestaShop
*/
$webService = new PrestaShopWebservice($url, $key, $debug);
$COOKIE_KEY = '_key';
$email = $_REQUEST['email'];
$password = md5('_key' . $_REQUEST['password']);
// The database hash for testing (random)
$passwordString = '$2y$10$UsYrIFQUOr5LBUZBoqSdxODuhbToEc.2QEqfAVB1r\/fhO5EfOyO96';
$opt = array(
'resource' => 'customers',
'filter[email]' => '['.$email.']',
'display' => '[email,lastname,firstname, passwd]'
);
$result = ($webService->get( $opt ));
$json = json_encode($result);
$optUser = array(
'resource' => 'customers',
'filter[email]' => '['.$email.']',
'display' => '[email,lastname,firstname,passwd]'
);
$resultUser = ($webService->get( $optUser ));
$userResult = json_encode($resultUser);
// Check the email
function hasEmail($string, $email)
{
return strpos($string, $email) !== false;
}
// Check the Password
function hasPassword($string, $password)
{
return strpos($string, $password) !== false;
}
if(hasEmail($userResult, $email) == true and hasPassword($userResult, $password) == true) {
session_start();
$_SESSION['user'] = $email;
// redirect is kut.
echo
'<html>
<head>
<meta content="text/html; charset=utf-8">
</head>
</html>';
} else {
// Here, we use single quotes for PHP and double quotes for JavaScript
echo '<script type="text/javascript">';
echo 'alert("Wrong username or password!")';
echo '</script>';
}
Small second question: How would i be able to run a -> go to url in the success statement, Currently the echo "<script></script>"; isn't working and since the header() can't be used i'm having some trouble redirecting on succes.
As always, Thanks in advance!
To generate the cookie key prestashop uses:
array('_COOKIE_KEY_', Tools::passwdGen(56)),
array('_COOKIE_IV_', Tools::passwdGen(8)),
So that cookie key is different everytime. In order to verify if the password is good you should get existing password from database and compare with your user-submitted password:
//CHECK IF THE GIVEN EMAIL MATCHES A ROW IN OUR LEGACY TABLE AND RETRIEVES THE LEGACY PASSWORD
$resultZC = Db::getInstance()->getRow('
SELECT `password`
FROM `zc_legacy_passwords`
WHERE `email` = \''.pSQL($email).'\'
AND `updated` = 0');
if (!$resultZC)
return false; //<- EMAIL NOT FOUND IN NONE OF THE TABLES, SO IT IS AN INVALID LOGIN
//ENCRYPTS THE GIVEN PASSWORD IN ZEN-CART / OSCOMMERCE FORMAT
$salt = substr($resultZC['password'], strrpos($resultZC['password'],':')+1, 2);
$ZCpassword = md5($salt . $passwd) . ':' . $salt;
if ($ZCpassword != $resultZC['password'])
return false; //<- WRONG ZEN-CART/OSCOMMERCE PASSWORD GIVEN
This is the part that you're asking for:
//ENCRYPTS THE GIVEN PASSWORD IN ZEN-CART / OSCOMMERCE FORMAT
$salt = substr($resultZC['password'], strrpos($resultZC['password'],':')+1, 2);
$ZCpassword = md5($salt . $passwd) . ':' . $salt;
where $resultZC['password'] is the password stored in the database and, $passwd is your password
if PrestaShop version is 1.6, the function to encrypt customer passwords is Tools::encrypt($passwd). This method just do this:
return md5(_COOKIE_KEY_.$passwd);
So knowing the _COOKIE_KEY_ you must be able to generate the hash.
_COOKIER_KEY_ is defined in config/settings.inc.php
If PrestaShop version is 1.7, Tools is not used and maybe md5(_COOKIE_KEY_.$passwd) will not match. It is used crypto from Symfony.
However, I guess PrestaShop webservice must have something to check users, in Customer class there is the method getByEmail(...) that is used in both 1.6 and 1.7 versions.
Regards.

Constant Contact API

I'm trying to write a simple Constant Contact script for adding and updating emails. The script is simple enough and should've ran smoothly. But when I start to include 'src/Ctct/autoload.php' the page just returns blank. I tried running it on another server and it works. But on my working server, it returns blank. It uses OAuth authentication from CTCT. I think it's a setting in the server, but I have no control over the server and any changes need to be forwarded to an admin, I just don't know what I need to change.
Here's the code:
require "Scripts/ConstantContact/src/Ctct/autoload.php";
use Ctct\ConstantContact;
use Ctct\Components\Contacts\Contact;
use Ctct\Components\Contacts\ContactList;
use Ctct\Components\Contacts\EmailAddress;
use Ctct\Exceptions\CtctException;
define("APIKEY", "*** Censored Media (18+ only) ***");
define("ACCESS_TOKEN", "*** Censored Media (18+ only) ***");
$cc = new ConstantContact(APIKEY);
// attempt to fetch lists in the account, catching any exceptions and printing the errors to screen
$lists = $cc->getLists(ACCESS_TOKEN);
$action = "Getting Contact By Email Address";
$Email = "asdf#asdf.com";
$FirstName = "Asdf";
$LastName = "Ghjk";
// check to see if a contact with the email addess already exists in the account
$response = $cc->getContactByEmail(ACCESS_TOKEN, $Email);
// create a new contact if one does not exist
if (empty($response->results)) {
$action = "Creating Contact";
$contact = new Contact();
$contact->addEmail($Email);
$contact->addList('1');
$contact->first_name = $FirstName;
$contact->last_name = $LastName;
$returnContact = $cc->addContact(ACCESS_TOKEN, $contact);
// update the existing contact if address already existed
} else {
$action = "Updating Contact";
$contact = $response->results[0];
$contact->addList('1');
$contact->first_name = $FirstName;
$contact->last_name = $LastName;
$returnContact = $cc->updateContact(ACCESS_TOKEN, $contact);
}
// catch any exceptions thrown during the process and print the errors to screen
if (isset($returnContact)) {
echo '<div class="container alert-success"><pre class="success-pre">';
print_r($returnContact);
echo '</pre></div>';
}
print '<p>'.$action.'</p>';
Again, this works on another server I tried, but doesn't work on my working server.
Any help would be appreciated.
Thanks!
Are you running PHP 5.3 or higher on the other server? Also did the domain change at all, if so that may throw an exception resulting in a blank page as your API key is domain specific. Feel free to shoot me an email and I will be glad to help you out with this - mstowe [at] constantcontact.com
-Mike

How to hide/protect password details in php?

I'm making a website in which I'm trying to create a form that will send the user-input to a google spreadsheet in my google docs/drive... I found a Github project that lets people code the php... It includes 2 other php files which are needed for the script. The code is as follows:
My question is, how can I hide my password from this script under $u = / $p = ??
Anyone viewing the code can see my password.. how can I prevent that?
Link to the script's source is : http://www.farinspace.com/saving-form-data-to-google-spreadsheets/
<?php
// Zend library include path
set_include_path(get_include_path() . PATH_SEPARATOR . "$_SERVER[DOCUMENT_ROOT]/ZendGdata-1.8.1/library");
include_once("Google_Spreadsheet.php");
$u = "username#gmail.com";
$p = "password";
$ss = new Google_Spreadsheet($u,$p);
$ss->useSpreadsheet("My Spreadsheet");
$ss->useWorksheet("wks2");
// important:
// adding a leading alpha char prevents errors, there are issues
// when trying to lookup an identifier in a column where the
// value starts with both alpha and numeric characters, using a
// leading alpha character causes the column and its values to be
// seen as a strictly a strings/text
$id = "z" . md5(microtime(true));
$row = array
(
"id" => $id // used for later lookups
, "name" => "John Doe"
, "email" => "john#example.com"
, "comments" => "Hello world"
);
if ($ss->addRow($row)) echo "Form data successfully stored";
else echo "Error, unable to store data";
$row = array
(
"name" => "John Q Doe"
);
if ($ss->updateRow($row,"id=".$id)) echo "Form data successfully updated";
else echo "Error, unable to update spreadsheet data";
?>
You can attempt to hide if from peering eyes using the code below. It would still be discoverable if you tried, but at least it's away from open text view. All it does is add characters to the text and then subtract them before it uses the password.
Run this script using your original password
<?php
$password = "test";
echo "Original Password In Plain Text = $password\n";
$len=strlen($password);
$NewPassword = "";
for( $i = 0; $i <= $len-1; $i++ ) {
$charcode = ord(substr( $password, $i, 1 ));
$NewChar = $charcode+5; $NewLetter = chr($NewChar);
$NewPassword = $NewPassword . $NewLetter;
} echo "Modified Password to Use in Script = $NewPassword\n";
$OrigPassword = "";
for( $i = 0; $i <= $len-1; $i++ ) {
$charcode = ord(substr( $NewPassword, $i, 1 ));
$OrigChar = $charcode-5; $OrigLetter = chr($OrigChar);
$OrigPassword = $OrigPassword . $OrigLetter;
} echo "Convert the Modified back to the Original = $OrigPassword\n";
?>
Add this part to your script with the new password from the above script
$password = "yjxy";
$OrigPassword = "";
for( $i = 0; $i <= $len-1; $i++ ) {
$charcode = ord(substr( $password, $i, 1 ));
$OrigChar = $charcode-5; $OrigLetter = chr($OrigChar);
$OrigPassword = $OrigPassword . $OrigLetter;
} $password = $OrigPassword;
echo "Script thinks this is the password = $password\n";
The best way to hide the password is to save it in external file and then include it in your php script. Your file with this password let's say 'config.php' should be above DOCUMENT_ROOT to make it unaccesible via browser. It's common aproach and for example you can see it in Zend Framework directory structure where only "public" directory is visible for user. The proper CHMOD should be set to this file as well.
Under this link you have ZF directory structure where you can check location of config files.
This question has been asked and answered lots of times here (but not specifically for Google docs). Short answer is that there is nothing you can do.
Longer answer is that you can mitigate the possibility of the credentials being compromised by:
using credentials supplied the user rather than stored in code
using tokens supplied by the user as a means of decrypting credentials stored in your code (but this gets very complicated with lots of users)
storing the credentials in an include file held outside the document root

Wialon remote API login

My code:
<?php
if(isset($_GET['login']) && isset($_GET['login']) && isset($_GET['password'])){
$_login_url = "http://testing.wialon.com/wialon/ajax.html?svc=core/login&params={user:%s,password:%s}";
$login = $_GET['login'];
$password = $_GET['password'];
$handle = fopen(sprintf($_login_url, $login, $password), "r");
$line = fgets($handle);
fclose($handle);
$responce = explode(",",$line);
if(count($responce) < 2) {
echo "Invalid user or password";
} else {
$sessid = explode(":",$responce[1]);
$lastid = str_replace("\"","",$sessid[1]);
echo "http://testing.wialon.com/index.html?sid=".$lastid."";
}
}
?>
when I access this script with the server hosting the script everything works perfectly, The sessions are generated with my IP address.
But when I access it with another computer any user trying to login the script generates session using the servers IP address. can I send the request with the users IP address?
No, you cannot send the request with the users IP address.
However, you might be able to indicate that the request is being performed on behalf of another IP by using the HTTP_X_FORWARDED_FOR request header or similar, but without looking at their documentations (which doesn't seem to be publicly available) I can't be sure of it. You'll need to ask 'em.
This is an old thread but, let me put in my two cents. There are two new wialon athentication methods Token login and by passing the athorization hash . the second method is best suited for maintaining session across servers.
http://sdk.wialon.com/wiki/en/kit/remoteapi/apiref/core/create_auth_hash
http://sdk.wialon.com/wiki/en/kit/remoteapi/apiref/token/token
//get the Token from here http://hosting.wialon.com/login.html?client_id=wialon&access_type=-1&activation_time=0&duration=0&flags=1
// You should have your existing username from wialon with SDK access
$params = "{'token':'$token','operateAs','$username'}";
$baseurl = "http://hst-api.wialon.com/wialon/ajax.html";
$url = "$baseurl?params=".urlencode($params)."&svc=token/login";
$o = json_decode(file_get_contents($url),true);
$sid = $o['eid'];

Categories