<?php
/*
* AUTHOR: Samuel Muñoz Hidalgo
* EMAIL: samuel.mh@gmail.com
* LAST REVISION: 24-APR-09
* DESCRIPTION:
* Will send cards to other applications via web.
* Symmetric cryptography and IP filtering are available.
*/
/*
* DESCRIPTION: used to encode the data attribute sent GET method
* TAKEN FROM: http://es2.php.net/manual/es/function.base64-encode.php#63543
*/
function urlsafe_b64encode($string) {
$data = base64_encode($string);
$data = str_replace(array('+','/','='),array('-','_',''),$data);
return $data;
}
/*
* DESCRIPTION: used to decode the data attribute sent GET method
* TAKEN FROM: http://es2.php.net/manual/es/function.base64-encode.php#63543
*/
function urlsafe_b64decode($string) {
$data = str_replace(array('-','_'),array('+','/'),$string);
$mod4 = strlen($data) % 4;
if ($mod4) {
$data .= substr('====', $mod4);
}
return base64_decode($data);
}
/*CASE 1 AND 2
* -Has Organization
* -And chains to a trusted root CA
* -NOTE: Based on V1.0, written for compatibility with DigitalMe PPID calculation
*/
function calculate_RP_PPID_Seed_2_2007 ($certs) {
$check_cert = openssl_x509_read(file_get_contents($certs[0]));
$array = openssl_x509_parse($check_cert);
openssl_x509_free($check_cert);
$OrgIdString = ('|O="'.$array['subject']['O'].'"|L="'.$array['subject']['L'].'"|S="'.$array['subject']['ST'].'"|C="'.$array['subject']['C'].'"|');
$numcerts = sizeof($certs);
for($i=1;$i<$numcerts;$i++){
$check_cert = openssl_x509_read(file_get_contents($certs[$i]));
$array = openssl_x509_parse($check_cert);
openssl_x509_free($check_cert);
$tmpstring = '|ChainElement="CN='.$array['subject']['CN'].', OU='.$array['subject']['OU'].', O='.$array['subject']['O'].', L='.$array['subject']['L'].', S='.$array['subject']['ST'].', C='.$array['subject']['C'].'"';
$OrgIdString = $tmpstring.$OrgIdString;
}
$OrgIdBytes = iconv("UTF-8", "UTF-16LE", $OrgIdString);
$RPPPIDSeed = hash('sha256', $OrgIdBytes,TRUE);
return $RPPPIDSeed;
}
/*
* DESCRIPTION: Calculate the PPID for a card
* INPUT: card ID, and RP certificates
* OUTPUT: PPID asociated to a Relying Party
*/
function calculate_PPID($cardid, $rp_cert) {
$CardIdBytes = iconv("ISO-8859-1", "UTF-16LE", $cardid);
$CanonicalCardId = hash('sha256', $CardIdBytes,TRUE);
$RPPPIDSeed = calculate_RP_PPID_Seed_2_2007($rp_cert);
$PPID = hash('sha256', $RPPPIDSeed.$CanonicalCardId,TRUE);
return $PPID;
}
/*
*
* INPUT: VOID
* OUPUT: String with the invoked URL
*/
function curPageURL() {
$pageURL = 'http';
if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
$pageURL .= "://";
if ($_SERVER["SERVER_PORT"] != "80") {
$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
} else {
$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
}
return $pageURL;
}
//TAD
/*
* INPUT: String (attribute length + attribute not begginning with a number) n times , number of attributes
* OUPUT: Array with attributes in order
*/
function parse_attributes($parsing_string, $num_attrs){
for ($i=0 ; $i<$num_attrs ; $i++) {
if (preg_match('/^[\d]*/', $parsing_string, $res)){
if (!($output[$i] = substr($parsing_string,strlen($res[0]),$res[0]))){
return null;
}
$parsing_string = substr($parsing_string, strlen($res[0])+strlen($output[$i]));
} else {
return null;
}
}
return $output;
}
/*
* Enable downloading an specific card, store Radius request
* INPUT: username, cardid, and radius request time
* OUTPUT; uuid of the stored request
*/
function enable_download($username, $cardid){
//almacenar existencia
//Add Timestamp to response
$time = 'x'.time(); //Cannot start with a number
$uuid = uniqid();
$handle = fopen(SimpleSAML_Utilities::getTempDir() . "/$uuid",'w');
if ($handle) {
fwrite($handle, strlen($username).$username.strlen($cardid).$cardid.strlen($time).$time);
fclose ($handle);
return $uuid;
} else {
return false;
}
}
/*
* Disable downloading an specific card, should be called when ending a request = Infocard is Issued
*
*/
function disable_download($uuid){
unlink("/tmp/$uuid");
}
/*
* ¿Should I generate a card?
*
*/
function is_card_enabled($uuid, $delivery_time){
$now = time();
$filename = SimpleSAML_Utilities::getTempDir() . "/$uuid";
//File check
if (!file_exists($filename)) return false; //File doesn't exist
//Time check
$handle = fopen($filename,'r');
if ($handle) {
$data = fread($handle, filesize($filename));
fclose ($handle);
$parsed_data = parse_attributes($data, 3);
$parsed_data[2] = substr($parsed_data[2],1); //Extracting numeric value
$time = $parsed_data[2];
$endtime = $time + $delivery_time;
if (($now<=$time)||($now>$endtime)) return false; //Incorrect time
return $parsed_data;
} else {
return false; //Could not read the file
}
}
/*
* Check if the user is in the connected table
* Update the row with the created Infocard card_ID
*/
function DB_update_connected_user ($username, $DB_params){
$card_id = sspmod_InfoCard_UserFunctions::generate_card_ID($username);;
$dbconn = pg_connect('host='.$DB_params['DB_host'].' port='.$DB_params['DB_port'].' dbname='.$DB_params['DB_dbname'].' user='.$DB_params['DB_user'].' password='.$DB_params['DB_password']);
$result = pg_fetch_all(pg_query_params($dbconn, 'SELECT * FROM connected_users WHERE name = $1', array("$username")));
if ($result[0]){
pg_update($dbconn, 'connected_users', array('card_id'=>$card_id), array('name'=>$username));
return true;
} else {
return false;
}
}
$config = SimpleSAML_Configuration::getInstance();
$autoconfig = $config->copyFromBase('logininfocard', 'config-login-infocard.php');
$configuredIP = $autoconfig->getValue('configuredIP');
//RADIUS Request - Send One Time URL
if ( (strcmp($_GET['ident'],'RADIUS')==0) && (($configuredIP == null) || ($_SERVER['REMOTE_ADDR'] == $configuredIP)) ){
/* Load the configuration. */
$key = $autoconfig->getValue('symmetric_key');
$internalkey = hash('sha256', $autoconfig->getValue('internal_key'));
$encrequest = urlsafe_b64decode($_GET['data']);
if (!$encrequest) throw new SimpleSAML_Error_NotFound('The URL wasn\'t found in the module.');
// Encryption
if ($key!=null) {
$iv = urlsafe_b64decode($_GET['iv']);
if (!$iv) throw new SimpleSAML_Error_NotFound('The URL wasn\'t found in the module.');
$enckey = hash('sha256', $key);
$request = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, pack("H*",$enckey), $encrequest, MCRYPT_MODE_CBC, $iv);
} else {
$request = $encrequest;
}
//Parse Attributes (username lenght + username + cardid length + cardid)
$parsed_request = parse_attributes($request, 2);
//Enable card for downloading (username+cardid+time)
$response = enable_download($parsed_request[0],$parsed_request[1]);
if(!$response) throw new SimpleSAML_Error_NotFound('FUNCTION enable_download, error accessing directory');
// Encrypt response for myself
$response = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, pack("H*",$internalkey), $response, MCRYPT_MODE_CBC, $iv);
$response = preg_replace('/\?.*/','',curPageURL()).'?data='.urlsafe_b64encode($response).'&iv='.urlsafe_b64encode($iv);
// Encrypt response for RADIUS
if ($key!=null){
$encresponse = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, pack("H*",$enckey), $response, MCRYPT_MODE_CBC, $iv);
} else {
$encresponse = $response;
}
// Send URL
print base64_encode($encresponse);
} else { //Client Resquest- Send InfoCard
//Get Attributes
$encrequest = urlsafe_b64decode($_GET['data']);
$iv = urlsafe_b64decode($_GET['iv']);
if ((!$encrequest)||(!$iv)) throw new SimpleSAML_Error_NotFound('The URL wasn\'t found in the module.');
/* Load the configuration. */
$internalkey = hash('sha256', $autoconfig->getValue('internal_key'));
$certificates = $autoconfig->getValue('certificates');
$ICconfig['InfoCard'] = $autoconfig->getValue('InfoCard');
$ICconfig['InfoCard']['issuer'] = $autoconfig->getValue('tokenserviceurl');//sspmod_InfoCard_Utils::getIssuer($sts_crt);
$ICconfig['tokenserviceurl'] = $autoconfig->getValue('tokenserviceurl');
$ICconfig['mexurl'] = $autoconfig->getValue('mexurl');
$ICconfig['sts_key'] = $autoconfig->getValue('sts_key');
$ICconfig['certificates'] = $autoconfig->getValue('certificates');
$ICconfig['UserCredential'] = $autoconfig->getValue('UserCredential');
$IC_lifetime_delivery = $autoconfig->getValue('IC_lifetime_delivery');
$DB_params = $autoconfig->getValue('DB_params');
// Encryption
$request = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, pack("H*",$internalkey), $encrequest, MCRYPT_MODE_CBC, $iv);
$parsed_request = is_card_enabled($request, $IC_lifetime_delivery);
if ($parsed_request && DB_update_connected_user($parsed_request[0], $DB_params)) {
// Calculate PPID
$ppid = base64_encode(calculate_PPID($parsed_request[1], $certificates));
// Create InfoCard
$ICdata = sspmod_InfoCard_UserFunctions::fillICdata($parsed_request[0],$ICconfig['UserCredential'],$ppid);
$IC = sspmod_InfoCard_STS::createCard($ICdata,$ICconfig);
disable_download($request);
//Send Infocard
print ($IC);
} else {
throw new SimpleSAML_Error_NotFound('The URL wasn\'t found in the module.');
}
}
?>
|