<?php /* * sasl.php * * @(#) $Id: sasl.php,v 1.11 2005/10/31 18:43:27 mlemos Exp $ * */ define("SASL_INTERACT", 2); define("SASL_CONTINUE", 1); define("SASL_OK", 0); define("SASL_FAIL", -1); define("SASL_NOMECH", -4); class sasl_interact_class { var $id; var $challenge; var $prompt; var $default_result; var $result; }; /* {metadocument}<?xml version="1.0" encoding="ISO-8859-1" ?> <class> <package>net.manuellemos.sasl</package> <version>@(#) $Id: sasl.php,v 1.11 2005/10/31 18:43:27 mlemos Exp $</version> <copyright>Copyright © (C) Manuel Lemos 2004</copyright> <title>Simple Authentication and Security Layer client</title> <author>Manuel Lemos</author> <authoraddress>mlemos-at-acm.org</authoraddress> <documentation> <idiom>en</idiom> <purpose>Provide a common interface to plug-in driver classes that implement different mechanisms for authentication used by clients of standard protocols like SMTP, POP3, IMAP, HTTP, etc.. Currently the supported authentication mechanisms are: <tt>PLAIN</tt>, <tt>LOGIN</tt>, <tt>CRAM-MD5</tt>, <tt>Digest</tt> and <tt>NTML</tt> (Windows or Samba).</purpose> <usage>.</usage> </documentation> {/metadocument} */ class sasl_client_class { /* Public variables */ /* {metadocument} <variable> <name>error</name> <type>STRING</type> <value></value> <documentation> <purpose>Store the message that is returned when an error occurs.</purpose> <usage>Check this variable to understand what happened when a call to any of the class functions has failed.<paragraphbreak /> This class uses cumulative error handling. This means that if one class functions that may fail is called and this variable was already set to an error message due to a failure in a previous call to the same or other function, the function will also fail and does not do anything.<paragraphbreak /> This allows programs using this class to safely call several functions that may fail and only check the failure condition after the last function call.<paragraphbreak /> Just set this variable to an empty string to clear the error condition.</usage> </documentation> </variable> {/metadocument} */ var $error=''; /* {metadocument} <variable> <name>mechanism</name> <type>STRING</type> <value></value> <documentation> <purpose>Store the name of the mechanism that was selected during the call to the <functionlink>Start</functionlink> function.</purpose> <usage>You can access this variable but do not change it.</usage> </documentation> </variable> {/metadocument} */ var $mechanism=''; /* {metadocument} <variable> <name>encode_response</name> <type>BOOLEAN</type> <value>1</value> <documentation> <purpose>Let the drivers inform the applications whether responses need to be encoded.</purpose> <usage>Applications should check this variable before sending authentication responses to the server to determine if the responses need to be encoded, eventually with base64 algorithm.</usage> </documentation> </variable> {/metadocument} */ var $encode_response=1; /* Private variables */ var $driver; var $drivers=array( "Digest" => array("digest_sasl_client_class", "notices.digest_sasl_client.inc" ), "CRAM-MD5" => array("cram_md5_sasl_client_class", "notices.cram_md5_sasl_client.inc" ), "LOGIN" => array("login_sasl_client_class", "notices.login_sasl_client.inc" ), "NTLM" => array("ntlm_sasl_client_class", "notices.ntlm_sasl_client.inc" ), "PLAIN" => array("plain_sasl_client_class", "notices.plain_sasl_client.inc" ), "Basic" => array("basic_sasl_client_class", "notices.basic_sasl_client.inc" ) ); var $credentials=array(); /* Public functions */ /* {metadocument} <function> <name>SetCredential</name> <type>VOID</type> <documentation> <purpose>Store the value of a credential that may be used by any of the supported mechanisms to process the authentication messages and responses.</purpose> <usage>Call this function before starting the authentication dialog to pass all the credential values that be needed to use the type of authentication that the applications may need.</usage> <returnvalue>.</returnvalue> </documentation> <argument> <name>key</name> <type>STRING</type> <documentation> <purpose>Specify the name of the credential key.</purpose> </documentation> </argument> <argument> <name>value</name> <type>STRING</type> <documentation> <purpose>Specify the value for the credential.</purpose> </documentation> </argument> <do> {/metadocument} */ Function SetCredential($key,$value) { $this->credentials[$key]=$value; } /* {metadocument} </do> </function> {/metadocument} */ /* {metadocument} <function> <name>GetCredentials</name> <type>INTEGER</type> <documentation> <purpose>Retrieve the values of one or more credentials to be used by the authentication mechanism classes.</purpose> <usage>This is meant to be used by authentication mechanism driver classes to retrieve the credentials that may be neede.</usage> <returnvalue>The function may return <tt>SASL_CONTINUE</tt> if it succeeded, or <tt>SASL_NOMECH</tt> if it was not possible to retrieve one of the requested credentials.</returnvalue> </documentation> <argument> <name>credentials</name> <type>HASH</type> <documentation> <purpose>Reference to an associative array variable with all the credentials that are being requested. The function initializes this associative array values.</purpose> </documentation> </argument> <argument> <name>defaults</name> <type>HASH</type> <documentation> <purpose>Associative arrays with default values for credentials that may have not been defined.</purpose> </documentation> </argument> <argument> <name>interactions</name> <type>ARRAY</type> <documentation> <purpose>Not yet in use. It is meant to provide context information to retrieve credentials that may be obtained interacting with the user.</purpose> </documentation> </argument> <do> {/metadocument} */ Function GetCredentials(&$credentials,$defaults,&$interactions) { Reset($credentials); $end=(GetType($key=Key($credentials))!="string"); for(;!$end;) { if(!IsSet($this->credentials[$key])) { if(IsSet($defaults[$key])) $credentials[$key]=$defaults[$key]; else { $this->error="the requested credential ".$key." is not defined"; return(SASL_NOMECH); } } else $credentials[$key]=$this->credentials[$key]; Next($credentials); $end=(GetType($key=Key($credentials))!="string"); } return(SASL_CONTINUE); } /* {metadocument} </do> </function> {/metadocument} */ /* {metadocument} <function> <name>Start</name> <type>INTEGER</type> <documentation> <purpose>Process the initial authentication step initializing the driver class that implements the first of the list of requested mechanisms that is supported by this SASL client library implementation.</purpose> <usage>Call this function specifying a list of mechanisms that the server supports. If the <argumentlink> <argument>message</argument> <function>Start</function> </argumentlink> argument returns a string, it should be sent to the server as initial message. Check the <variablelink>encode_response</variablelink> variable to determine whether the initial message needs to be encoded, eventually with base64 algorithm, before it is sent to the server.</usage> <returnvalue>The function may return <tt>SASL_CONTINUE</tt> if it could start one of the requested authentication mechanisms. It may return <tt>SASL_NOMECH</tt> if it was not possible to start any of the requested mechanisms. It returns <tt>SASL_FAIL</tt> or other value in case of error.</returnvalue> </documentation> <argument> <name>mechanisms</name> <type>ARRAY</type> <inout /> <documentation> <purpose>Define the list of names of authentication mechanisms supported by the that should be tried.</purpose> </documentation> </argument> <argument> <name>message</name> <type>STRING</type> <out /> <documentation> <purpose>Return the initial message that should be sent to the server to start the authentication dialog. If this value is undefined, no message should be sent to the server.</purpose> </documentation> </argument> <argument> <name>interactions</name> <type>ARRAY</type> <documentation> <purpose>Not yet in use. It is meant to provide context information to interact with the end user.</purpose> </documentation> </argument> <do> {/metadocument} */ Function Start($mechanisms, &$message, &$interactions) { if(strlen($this->error)) return(SASL_FAIL); if(IsSet($this->driver)) return($this->driver->Start($this,$message,$interactions)); $no_mechanism_error=""; for($m=0;$m<count($mechanisms);$m++) { $mechanism=$mechanisms[$m]; if(IsSet($this->drivers[$mechanism])) { if(!class_exists($this->drivers[$mechanism][0])) require_once(dirname(__FILE__)."/".$this->drivers[$mechanism][1]); $this->driver=new $this->drivers[$mechanism][0]; if($this->driver->Initialize($this)) { $this->encode_response=1; $status=$this->driver->Start($this,$message,$interactions); switch($status) { case SASL_NOMECH: Unset($this->driver); if(strlen($no_mechanism_error)==0) $no_mechanism_error=$this->error; $this->error=""; break; case SASL_CONTINUE: $this->mechanism=$mechanism; return($status); default: Unset($this->driver); $this->error=""; return($status); } } else { Unset($this->driver); if(strlen($no_mechanism_error)==0) $no_mechanism_error=$this->error; $this->error=""; } } } $this->error=(strlen($no_mechanism_error) ? $no_mechanism_error : "it was not requested any of the authentication mechanisms that are supported"); return(SASL_NOMECH); } /* {metadocument} </do> </function> {/metadocument} */ /* {metadocument} <function> <name>Step</name> <type>INTEGER</type> <documentation> <purpose>Process the authentication steps after the initial step, until the authetication iteration dialog is complete.</purpose> <usage>Call this function iteratively after a successful initial step calling the <functionlink>Start</functionlink> function.</usage> <returnvalue>The function returns <tt>SASL_CONTINUE</tt> if step was processed successfully, or returns <tt>SASL_FAIL</tt> in case of error.</returnvalue> </documentation> <argument> <name>response</name> <type>STRING</type> <in /> <documentation> <purpose>Pass the response returned by the server to the previous step.</purpose> </documentation> </argument> <argument> <name>message</name> <type>STRING</type> <out /> <documentation> <purpose>Return the message that should be sent to the server to continue the authentication dialog. If this value is undefined, no message should be sent to the server.</purpose> </documentation> </argument> <argument> <name>interactions</name> <type>ARRAY</type> <documentation> <purpose>Not yet in use. It is meant to provide context information to interact with the end user.</purpose> </documentation> </argument> <do> {/metadocument} */ Function Step($response, &$message, &$interactions) { if(strlen($this->error)) return(SASL_FAIL); return($this->driver->Step($this,$response,$message,$interactions)); } /* {metadocument} </do> </function> {/metadocument} */ }; /* {metadocument} </class> {/metadocument} */ ?>