Regarding to a recent post I put here about Kerberos and Apache, there is a way to replace Kerberos when the Active Directory cannot be properly configured to accept Kerberos connections. You can simulate the NTLM auth process with the browser by 6 steps in PHP :
function get_login() {
/*
step: | type:
-------|----------------|------------------------------------
1 | C --> S | GET ...
-------|----------------|------------------------------------
2 | C <-- S | 401 Unauthorized
| | WWW-Authenticate: NTLM
-------|----------------|------------------------------------
3 | C --> S | GET ...
| | Authorization: NTLM
| | <base64-encoded type-1-message>
-------|----------------|------------------------------------
4 | C <-- S | 401 Unauthorized
| | WWW-Authenticate: NTLM
| | <base64-encoded type-2-message>
-------|----------------|------------------------------------
5 | C --> S | GET ...
| | Authorization: NTLM
<base64-encoded type-3-message>
-------|----------------|------------------------------------
6 | C <-- S | 200 Ok
-------|----------------|------------------------------------
*/
$headers = apache_request_headers();
if($headers['Authorization'] == NULL) { // step 1
header( "HTTP/1.1 401 Unauthorized" ); // step 2
header( "WWW-Authenticate: NTLM" );
exit;
};
if(isset($headers['Authorization'])
&& substr($headers['Authorization'],0,5) == 'NTLM ') {
// step 3 to 6
$chaine=$headers['Authorization'];
$chaine=substr($chaine, 5); // type1 message
$chained64=base64_decode($chaine);
if(ord($chained64{8}) == 1) { // step 3
// check NTLM flag "0xb2",
// offset 13 in type-1-message :
if (ord($chained64[13]) != 178) {
echo "Please use NTLM compatible browser";
return null;
}
$retAuth = "NTLMSSP";
$retAuth .= chr(0).chr(2).chr(0).chr(0);
$retAuth .= chr(0).chr(0).chr(0).chr(0);
$retAuth .= chr(0).chr(40).chr(0).chr(0);
$retAuth .= chr(0).chr(1).chr(130).chr(0);
$retAuth .= chr(0).chr(0).chr(2).chr(2);
$retAuth .= chr(2).chr(0).chr(0).chr(0);
$retAuth .= chr(0).chr(0).chr(0).chr(0);
$retAuth .= chr(0).chr(0).chr(0).chr(0).chr(0);
$retAuth64 =base64_encode($retAuth);
$retAuth64 = trim($retAuth64);
header( "HTTP/1.1 401 Unauthorized" ); // step 4
header( "WWW-Authenticate: NTLM $retAuth64" );
exit;
}
else if(ord($chained64{8}) == 3) { // step 5
$lenght_domain = (ord($chained64[31])*256 + ord($chained64[30]));
$offset_domain = (ord($chained64[33])*256 + ord($chained64[32]));
$domain = substr($chained64, $offset_domain, $lenght_domain);
$lenght_login = (ord($chained64[39])*256 + ord($chained64[38]));
$offset_login = (ord($chained64[41])*256 + ord($chained64[40]));
$login = substr($chained64, $offset_login, $lenght_login);
$lenght_host = (ord($chained64[47])*256 + ord($chained64[46]));
$offset_host = (ord($chained64[49])*256 + ord($chained64[48]));
$host = substr($chained64, $offset_host, $lenght_host);
}
}
$login = preg_replace("/(.)(.)/","$1",$login);
$domain = preg_replace("/(.)(.)/","$1",$domain);
$login = strtolower($login);
$domain = strtoupper($domain);
return array($login,$domain); // step 6 : accept
}
Warning : this code must be exectuted not only for the auth process when you want to login the user, but for each HTTP request to your application (so on each page).
It is very important to put HTTP 1.1 protocole in HTTP headers because HTTP 1.0 does not support Keep-alive connection and so NTLM auth. For some unknown reasons, even if some Apache versions change automatically the protocole version to 1.1 in your headers, other versions don't (for example 2.2.3 can do it and 2.2.9 can't).
Finally, keep in mind that this code is not as secure as Kerberos Apache module, because this code will never check Active Directory permission to accept the user. This function is just to retrieve login and domain, you have to make the account check yourself.
Good luck !
After few months developing a little try under Android API, I wanted to make feedback on benefits of the Google OS. I want to achieve the first version of my project and then make a constructive criticism about Android regarding to other graphical or mobile APIs, like the iPhone.
Since the beginning of the year, I established a personal project to develop a small Android application, quite independent,
using GUI at maximum of its capacities, a database (SQLite) and a few onboard Google Maps onboard. I'll give small screenshots in a way that says enough along on the usefulness of the program, because I do not know yet exactly what I will do with my application.
My first impressions over development were:
- Firstly, the ownership of the GUI as a developer is quite long: you cannot learn to make a good GUI in a week, it takes more time (about 2 months). But when you play well with this API, you have fun. The GUI is certainly more easy to control than the Swing one, my only point of comparison in Java.
- Despite this, the GUI is not as good as the iPhone one: technologically, it lacks important points (difficult to achieve, I know): the multi-touch is not supported at all and will probably never (or only partially, if we can hope?); the fluidity of the scrolls with the finger is not as impressive as on the iPhone and at the same time it lost ergonomism; the sequence of screens and transitions between them are not automatic: you must integrate or develop it by yourself: it has its advantages but also disadvantages: each program will behave differently on transistions, resulting in a loss of landmarks for the user; API adopted by Google is a little too oriented "1 screen means 1 Java class", which is sometimes a strong constraint to generate clear source code.
- The screen resolution of Android is variable! Several resolutions will be possible: this advantage allows manufacturers of phones to have screens of different size depending on the targeted markets: it is good for them. For developers, that's another story! You must design applications with screens nor too rich (to fit on small screens), nor too poor (to avoid empty large screens), or (solution that I had adopted) set up screens for each resolution. This work is long, and if an application does not handle many resolutions (as I saw many applications as ADC Challenge winners...), small screen will not display everything, and therefore the application does not run properly on low resolutions, which are - I presume - being the first resolutions to emerge on the market, given the current technological possibilities.
- Application side, we do what we want, as long as it is possible in Java, and if it is not too heavy to execute : we must not forget that Java is a language interpreted by a JVM, and it is basically heavy and power consumer. On a small phone, we have the computing power of a PC made five years ago. See how Windows Mobile is slow: it will be worse under Android, unless you have a very big phone tht cost a lot (see the dimensions of the HTC Dream / G1, the first android phone to be released, for about $300).
- Synchronization side, between Android / Desktop, is for the moment inexisting: either I missed a big detail in the framework, or it is a huge mistake made by Google: I have not found any tool in the emulator to synchronize laptop with a PC... If every developer must do its own synchronization program, there will be problems quickly. I intend to look at this at the end of my project to analyze the feasibility and simplicity to develop a database sync.
- Finally, as the framework version 0.9 was released recently, I was able to experience a transition of versions with my application. The changes in the API showed me about 550 errors in Eclipse. Classes have disappeared, others are displaced or have become private. Many methods have been renamed (without any logical intention), and Google Maps API has changed a lot. I had to fully rewrite the classes of my application using MAPS. For 550 errors, 30 hours were needed to bring my application up to version 0.9 (the gain is still significant in terms of fluidity, features ...).
It's a big news, Android finally opened up the Android SDK v0.9, and Eclipse plugins that comes with.
You can find information on the following sites :
- Android Developers Blog
- Android developers Google Groupes
- Mobile Android (fr)
- Download page on code.google.com
In few days, I will add a post to comment the migration of an Android application from M5 version to 0.9beta. I can say today that for a little application like mine, more than an hundred of errors appeared in my project with the new SDK (moved/removed API classes, deprecated methods, etc...)...
Good luck for migrations!
This week I had to make an eZpublish web site with an SSO authentication under eZpublish (NTLM). An SSO login handler is required. This login handler is executed by PHP and so is preceded by Apache authentication, with Kerberos Apache module.
The first problem comes when you want to let Kerberos authenticate the user (to give user data to PHP) or bypass authentication module if Kerberos cannot identify the user, to let eZpublish authenticate the user itself, with a classical form or another login handler : this parameter is not possible under Apache Auth modules, with a classical configuration like this:
<Directory /var/www/ezpublish>
AuthType Kerberos
KrbAuthRealms WASCOU.ORG
KrbServiceName HTTP
Krb5Keytab /root/wascou.keytab
KrbMethodNegotiate on
KrbMethodK5Passwd off
Require valid-user
Options All
</Directory>
The "Require valid-user" line will disallow site access until the user is not authenticated under Apache Kerberos module. This is the problem for users that need to be logged in with the classical form on eZpublish. Unfortunately there is no instruction to tell Kerberos to let a bypass in failure case (like with Basic or Digest modules, the same): Apache will give a HTTP 401 error, which is quite logical.
I suppose you know that eZpublish can call the user/login module from any URL that brings to a protected content: according to the user rights, a login form could be shown, and before this, a SSO login can be called. So there no way to indicate clearly to apache when eZpublish needs to login the user (to activate Kerberos authentication): telling "/user/login" URL is the only login URL is a mistake.
So, the solution is to play with well built Apache and PHP redirections, that the user cannot see, to call Kerberos module only when eZpublish needs it. Firstly, we will replace the above configuration with the following one, contained in a Location section, much more appropriated in our case :
<Location /ntlm/auth>
AuthType Kerberos
KrbAuthRealms WASCOU.ORG
KrbServiceName HTTP
Krb5Keytab /root/wascou.keytab
KrbMethodNegotiate on
KrbMethodK5Passwd off
Require valid-user
Options All
ErrorDocument 401 /user/login
</Location>
Notice that the "/ntlm/auth" URL could bring us to an eZpublish module: this module must exist (you have to create it), but the PHP script behind this will never been executed and could remain empty (Apache and eZpublish will make redirections before this execution, see next step). Also notice the "ErrorDocument 401 /user/login" line, that will redirect the user if Kerberos cannot authenticate the user (and only for the "/ntlm/auth" URL!).
The big tip is here: if Kerberos cannot authenticate the user, it must redirect to an eZpublish page. The "/user/login" is an arbitrary choice, because the SSO login handler will make redirections before the execution of the user/login script (see next step).
Now, you have to make your SSO login handler, playing with all needed redirections, to manage correctly all possible bounds.
The following SSO login handler is a complete example:
function handleSSOLogin() {
$ip = $_SERVER["REMOTE_ADDR"];
$net = $ini->variable( 'NTLMSettings', 'net' );
$mask = $ini->variable( 'NTLMSettings', 'mask' );
// tip: (net & mask) == (ip & mask) : ok!
if ((ip2long($net)&ip2long($mask))==(ip2long($ip)&ip2long($mask))) {
// 2nd case : /ntlm/auth redirected to first URL, to auth under PHP.
if ($_SESSION['ntlm_success']=="success") {
if ( array_key_exists( 'REMOTE_USER', $_SESSION )
&& array_key_exists( 'AUTH_TYPE', $_SESSION ) ) {
$remoteUser = $_SESSION['REMOTE_USER'];
$authType = $_SESSION['AUTH_TYPE'];
eZDebug::writeDebug('#25# user:'.$remoteUser,'');
$loginParts = explode( '@', $remoteUser );
$loginName = $loginParts[0];
// main call of YOUR User handler in NTLM mode
$user = LOGINCLASS::loginUser($loginName);
if ( is_object( $user ) ) {
return $user;
} else {
eZDebug::writeDebug('#36# Unable to fetch user','');
unset($_SESSION['REMOTE_USER']);
unset($_SESSION['AUTH_TYPE']);
}
} else {
eZDebug::writeDebug('#39# No sso auth performed','');
unset($_SESSION['REMOTE_USER']);
unset($_SESSION['AUTH_TYPE']);
}
$_SESSION['ntlm_success'] = "failed";
return false;
}
// first case : sso_handler redirection to /ntlm/auth.
if ($_SERVER['SCRIPT_URL'] == '/ntlm/auth') {
eZDebug::writeDebug('#47# IP on domain, Kerberos OK.','');
if (!$_SESSION['ntlm_url']) {
echo 'Cookies or/and Sessions are not activated.<br/>';
eZExecution::cleanExit();
}
$ntlm_url = $_SESSION['ntlm_url'];
unset($_SESSION['ntlm_url']);
$_SESSION['ntlm_success'] = "success";
$_SESSION['REMOTE_USER'] = $_SERVER['REMOTE_USER'];
$_SESSION['AUTH_TYPE'] = $_SERVER['AUTH_TYPE'];
eZHTTPTool::redirect($ntlm_url);
eZExecution::cleanExit();
} else if ($_SESSION['ntlm_success'] != "failed") {
eZDebug::writeDebug('#59# IP on domain, checking NTLM.','');
$_SESSION['ntlm_url']=$_SERVER['SCRIPT_URL'];
eZHTTPTool::redirect('/ntlm/auth');
eZExecution::cleanExit();
} else {
eZDebug::writeDebug('#64# IP on domain, Kerberos failed.','');
}
} else eZDebug::writeDebug('#67# IP not on domain, Stop.','');
return false;
}
This script will process like this:
- First, a test is executed to ensure we are on the right domain (by mask and IP)
- Then a redirection is done to /ntlm/auth ; we store the original URL typed in the SESSION
- When /ntlm/auth is called, apache Kerberos module will try to authenticate user
- if failed, an Apache redirection (by "ErrorDocument 401" param) is done to /user/login
- in this case, our SSO login handler will redirect to the original URL typed by the user, with a failed state for authentication (stored in the session)
- the next login handler will try an authentication with a form...
- if succeeded, our SSO login handler will store user login (given by Kerberos under $_SESSION['REMOTE_USER']) and will redirect to the original URL typed by the user,
- on this new URL, our SSO login handler will authenticate the given user in the database (you have to implement "LOGINCLASS::loginUser($loginName);" line by yourself)
- in case of success, login process is terminated, the $user is returned.
- in case of failure, false is returned to let next login handler try an authentication with a form...
If you have any question, comment this post!
Good luck!
About two weeks ago, the first ADC is over, and winners are published.
This post will comment few winner applications, positive and negative points on them.
Firstly, I saw in a recent RSS feed that ADC judges are mainly from the Handset Alliance. I think this is quite unfair for some kind of application. Judges are from constructors like HTC, NVidia, Samsung, Telefonica, Motorola, T-mobile *, ASUS, etc... and for a lot of them, they are mobile contructors. By this way, many applications are designed to be winners because of the marketing concept that constructors like to use for selling a mobile. For example, many winners are social networks. I understand that this kind of application will be very used by majority of people (if they have enough money to stay connected to the Internet everytime they use their mobile...), but other applications, that could be really usefull but that are not a very good subject for marketing could be disadvantaged.
A second point that I want to highlight is that in a lot of these winner applications, the user interface is made for a very high resolution. Think that first mobiles using Android won't have such a resolution. In this case, the winner application won't work correctly on many of these phones...
Yet, I was impressed by some of these applications. For example a biometric application called BioWallet that scan eyes for iris based authentication (yes, you will need a very good camera on your mobile now...), or the ability to scan 1D and 2D barcodes.
The past month, I tried the Android SDK, and I enjoyed the easy way to make efficient user interfaces.
The next post I will put on this blog will be about first steps in Android SDK.
The following links talks about the 50 winners of the ADC. See them and imagine what Android will be in few months:
http://www.frandroid.com/369/116-juges-et-46-descriptions-dapplic...
http://code.google.com/android/images/adc1r1_deck.pdf
http://android-developers.blogspot.com/2008/05/android-developer-cha...
http://www.anddev.org/viewtopic.php?p=7911#7911
http://www.mobile-android.fr/?p=74
http://www.netvibes.com/xaviergouley#Android
Hi,
This week, I finished an old personal project on Java platform.
This project, called Jieting Launcher, is a modular engine written in Java, that offers simple interfaces & services between modules. Adding a new module into the application is very easy (like copy a JAR in a folder), and version upgrade is dynamic. This application brings frameworks for developper tasks for Swing, AWT or SWT.
The application is now in beta version, 0.2, and I will follow statistics to know if my idea is appreciated and used.
The given screenshot is an example of my application starting modules, building dependency trees, resolving conflicts between modules and libraries, and finally launching modules. It's a dynamic splash screen: the only UI that is mandatory in the application (all other stuff is in modules).
To make your own module, you just have to follow an Interface, and if you want, include existing other modules (for dependencies), and that's all!
You can access the project through the following link :
SourceForge.net: Jieting launcher
Enjoy!
Hi, today, I want to share a good tip to have access to an object attribute of an unknown class from eZpublish templates. This case is rare, but when you have an object with unknown attribute, or from an unknown PHP class, and you want to access an attribute by its name, if the object does not extends a datatype, the classic "object.attribute" operator in template language cannot work. The problem is that this operator call methods like attributes(), hasAttribute($attr) or attribute($attr) to explore the attributes. In your case, the object has no such methods, you cannot modify the class to add them (for some reasons, for example if the object comes from PHP SOAP), and then you need a wrapper to simulate a datatype.
I propose a DummyDatatype wrapper class, used by a template operator, like this :
class DummyDataType {
var $Object = false;
function DummyDataType($object = false) {
$this->Operators = array( 'ddt' );
$this->NamedOperators = array(
'ddt'=> array( 'attribut' => array(
'type' => 'Object',
'required' => true,
'default' => null))
);
$this->Object = $object;
}
function modify( $tpl, $operatorName, $operatorParameters,
$rootNamespace, $currentNamespace,
&$operatorValue, $namedParameters) {
switch ( $operatorName ) {
case 'ddt':
$this->Object = ($operatorValue != null)?
$operatorValue : $namedParameters['attribut'];
$operatorValue = $this;
break;
default :
$tpl->warning($operatorName,
"Unknown operator '$operatorName'");
break;
}
}
function operatorList() {
return $this->Operators;
}
function namedParameterPerOperator() {
return true;
}
function namedParameterList() {
return $this->NamedOperators;
}
function attributes() {
$obj = $this->Object;
$result = array();
foreach($obj as $key => $value) {
$result[] = $key;
}
return $result;
//TODO: test this in all cases (string,integer,...)
}
function hasAttribute( $attr ) {
if ($this->Object == false) return false;
return isset( $this->Object->$attr );
}
function attribute( $attr ) {
if (isset( $this->Object )) {
if ( isset( $this->Object->$attr ) )
return $this->Object->$attr;
}
eZDebug::writeError("Attribute '$attr' does not exist",
'DummyDataType::attribute');
$attributeData = null;
return $attributeData;
}
}
With this class, used like a template operator in an extension, you can explore an object, whatever his class,
by calling this:
my_object|ddt('my_attribute').0 {* an array *}
my_object|ddt('sub_object')|ddt('a_datatype_object').content...
{* object containing datatype object, with content attribute *}This class could be useful for some rare cases, but is a smart solution, so keep a bookmark on it ;)
User interface addict? Mobile phone user? Disappointed by the iPhone and its capacities/price?
Today, I wish to share my passion for Android, the user interface of my future mobile phone. Android is like an operating system on a mobile phone, but it is an open source, easy to program, and maintained by the giant Google.
Android is only at the stage of its development, it is thus still difficult to know what will be the final result, but it promises a lot, because built by the best Java developers from all over the world, and leads to creativity by a challenge of $10'000'000...
It runs on Java under an embeded and enhanced JVM, itself running over a linux kernel. Since few months, the SDK is available, with an emulator; many developers communities were formed; the challenge increased creativity and numbers of program tries. Soon, a first giant step will be made by google in the mobile phone world.
I can only advise you to go to throw a glance, as well on the Google workshops as on Youtube to see some basic demonstrations, as “how to create an application like a contact list in about 5 minutes and 15 code lines".
Next Android steps:
- 14th April 2008: Challenge deadline, end of the first step,
- 28th/29th May 2008: Google I/O, for much more details about Android
Some interesting links:
- http://code.google.com/android/
- http://code.google.com/p/apps-for-android/
- http://android-developers.blogspot.com/
- http://www.openhandsetalliance.com/whats_new.html
- http://www.mobile-android.fr/
- http://www.anddev.org/
- http://www.frandroid.com/
RSS/Atom Feeds:
Welcome to you!
This first post symbolizes the starting of my blog, about computer sciences, web technologies, computer HMI and other technological subjects.
Thanks to Wascou for lodging for this blog, we will make a pot together on a common subject - eZpublish, tool on which we both work - for unspecified duration.

Add comment