diff options
Diffstat (limited to 'src/etc/inc/digest_sasl_client.inc')
-rw-r--r-- | src/etc/inc/digest_sasl_client.inc | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/etc/inc/digest_sasl_client.inc b/src/etc/inc/digest_sasl_client.inc new file mode 100644 index 0000000..924887d --- /dev/null +++ b/src/etc/inc/digest_sasl_client.inc @@ -0,0 +1,135 @@ +<?php +/* + * digest_sasl_client.php + * + * @(#) $Id: digest_sasl_client.php,v 1.1 2005/10/27 05:24:15 mlemos Exp $ + * + */ + +define('SASL_DIGEST_STATE_START', 0); +define('SASL_DIGEST_STATE_RESPOND_CHALLENGE', 1); +define('SASL_DIGEST_STATE_DONE', 2); + +class digest_sasl_client_class +{ + var $credentials=array(); + var $state=SASL_DIGEST_STATE_START; + + Function unq($string) + { + return(($string[0]=='"' && $string[strlen($string)-1]=='"') ? substr($string, 1, strlen($string)-2) : $string); + } + + Function H($data) + { + return md5($data); + } + + Function KD($secret, $data) + { + return $this->H($secret.':'.$data); + } + + Function Initialize(&$client) + { + return(1); + } + + Function Start(&$client, &$message, &$interactions) + { + if($this->state!=SASL_DIGEST_STATE_START) + { + $client->error='Digest authentication state is not at the start'; + return(SASL_FAIL); + } + $this->credentials=array( + 'user'=>'', + 'password'=>'', + 'uri'=>'', + 'method'=>'', + 'session'=>'' + ); + $defaults=array(); + $status=$client->GetCredentials($this->credentials,$defaults,$interactions); + if($status==SASL_CONTINUE) + $this->state=SASL_DIGEST_STATE_RESPOND_CHALLENGE; + Unset($message); + return($status); + } + + Function Step(&$client, $response, &$message, &$interactions) + { + switch($this->state) + { + case SASL_DIGEST_STATE_RESPOND_CHALLENGE: + $values=explode(',',$response); + $parameters=array(); + for($v=0; $v<count($values); $v++) + $parameters[strtok(trim($values[$v]), '=')]=strtok(''); + + $message='username="'.$this->credentials['user'].'"'; + if(!IsSet($parameters[$p='realm']) + && !IsSet($parameters[$p='nonce'])) + { + $client->error='Digest authentication parameter '.$p.' is missing from the server response'; + return(SASL_FAIL); + } + $message.=', realm='.$parameters['realm']; + $message.=', nonce='.$parameters['nonce']; + $message.=', uri="'.$this->credentials['uri'].'"'; + if(IsSet($parameters['algorithm'])) + { + $algorithm=$this->unq($parameters['algorithm']); + $message.=', algorithm='.$parameters['algorithm']; + } + else + $algorithm=''; + + $realm=$this->unq($parameters['realm']); + $nonce=$this->unq($parameters['nonce']); + if(IsSet($parameters['qop'])) + { + switch($qop=$this->unq($parameters['qop'])) + { + case "auth": + $cnonce=$this->credentials['session']; + break; + default: + $client->error='Digest authentication quality of protection '.$qop.' is not yet supported'; + return(SASL_FAIL); + } + } + $nc_value='00000001'; + if(IsSet($parameters['qop']) + && !strcmp($algorithm, 'MD5-sess')) + $A1=$this->H($this->credentials['user'].':'. $realm.':'. $this->credentials['password']).':'.$nonce.':'.$cnonce; + else + $A1=$this->credentials['user'].':'. $realm.':'. $this->credentials['password']; + $A2=$this->credentials['method'].':'.$this->credentials['uri']; + if(IsSet($parameters['qop'])) + $response=$this->KD($this->H($A1), $nonce.':'. $nc_value.':'. $cnonce.':'. $qop.':'. $this->H($A2)); + else + $response=$this->KD($this->H($A1), $nonce.':'. $this->H($A2)); + $message.=', response="'.$response.'"'; + if(IsSet($parameters['opaque'])) + $message.=', opaque='.$parameters['opaque']; + if(IsSet($parameters['qop'])) + $message.=', qop="'.$qop.'"'; + $message.=', nc='.$nc_value; + if(IsSet($parameters['qop'])) + $message.=', cnonce="'.$cnonce.'"'; + $client->encode_response=0; + $this->state=SASL_DIGEST_STATE_DONE; + break; + case SASL_DIGEST_STATE_DONE: + $client->error='Digest authentication was finished without success'; + return(SASL_FAIL); + default: + $client->error='invalid Digest authentication step state'; + return(SASL_FAIL); + } + return(SASL_CONTINUE); + } +}; + +?>
\ No newline at end of file |