#!/usr/bin/perl -w

# AUTHOR: Samuel Muñoz Hidalgo
# CONTACT: samuel.mh@gmail.com
# LAST REVISION: 4 June 2009
# DESCRIPTION: PERL connector for the in Eduroam integrated identity metasystem USSO project


use LWP::Simple;


# needed programs: zenity,gksu,iwconfig,ifconfig,...,


#-------------CONFIGURACION----------------------

#----> USER SPECIFIC
$LANG = `echo \$LANG`;

$username = undef;
$password = undef;
$iface = undef;
$driver = undef;
$ssid='INFOCARD';

#----> GENERAL
$DM_path='/usr/bin/digitalme';
$WPA_SUPPLICANT_path = '/home/infocard/wpa_supplicant-0.6.8/wpa_supplicant/./wpa_supplicant';
$IFCONFIG_path = '/sbin/ifconfig';
$IWCONFIG_path = '/sbin/iwconfig';


$WPA_SUPPLICANT_CONF_file = '/tmp/WPASup_eduroam.conf';
$IC_file = '/tmp/IC-eduroam.crd';

$DM_pipe = '/tmp/DMpipe';
$WPA_pipe = '/tmp/DMpipe';
$WIFI_DRIVERS = 'hostap hermes madwifi MADWIFI atmel wext ndiswrapper broadcom ipw  wired  bsd  ndis ';
$CONF_CA_CERT = "-----BEGIN CERTIFICATE-----
MIIDdTCCAt6gAwIBAgIJANFANyG/ki7+MA0GCSqGSIb3DQEBBQUAMIGEMQswCQYD
VQQGEwJFUzEPMA0GA1UECBMGTWFkcmlkMRowGAYDVQQHFBFBbGNhbOEgZGUgSGVu
YXJlczEMMAoGA1UEChMDVUFIMRMwEQYDVQQLFAphdXRvbeF0aWNhMSUwIwYDVQQD
ExxGQUtFIENBIEZPUiBURVNUSU5HIFBVUlBPU0VTMB4XDTA5MDUxNzE3MDA1OFoX
DTEwMDYyMTE3MDA1OFowgYQxCzAJBgNVBAYTAkVTMQ8wDQYDVQQIEwZNYWRyaWQx
GjAYBgNVBAcUEUFsY2Fs4SBkZSBIZW5hcmVzMQwwCgYDVQQKEwNVQUgxEzARBgNV
BAsUCmF1dG9t4XRpY2ExJTAjBgNVBAMTHEZBS0UgQ0EgRk9SIFRFU1RJTkcgUFVS
UE9TRVMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOBM+ryQe57VEhXeCpfY
m++b4qwxlwg0emBIw0ocxGVqGovdAtfOvx0WnPySq4LJqvtlhLpn+HfiRINsBMAb
vEJU31Bu7eN2QOPdiOECzomaXk09F1goESvaRYK7c3gaxPUBTVGGknX19oYkXesk
x+BqJze0mxZn8ebFf/iZ9ATpAgMBAAGjgewwgekwHQYDVR0OBBYEFCHR6w3uzhJO
qW1YQMCga0AzDAaeMIG5BgNVHSMEgbEwga6AFCHR6w3uzhJOqW1YQMCga0AzDAae
oYGKpIGHMIGEMQswCQYDVQQGEwJFUzEPMA0GA1UECBMGTWFkcmlkMRowGAYDVQQH
FBFBbGNhbOEgZGUgSGVuYXJlczEMMAoGA1UEChMDVUFIMRMwEQYDVQQLFAphdXRv
beF0aWNhMSUwIwYDVQQDExxGQUtFIENBIEZPUiBURVNUSU5HIFBVUlBPU0VTggkA
0UA3Ib+SLv4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQDc+u0ow99i
TcV9uAMreI9ROSSZHyreVSb8pkNz/SOODNvfqeIfK+0bCFEXWtMVEEuYbtQ9vqCX
eFjtZqNai5vCYzzPeud9G1ri3ONgIk9htZETtwF5pwDRTesDtKLfmoaqHfzmpN6j
mj3VxaLvCb11QQv+Rgp/G6RfDl4f4Zs79Q==
-----END CERTIFICATE-----";


#-------------DICTIONARY ----------------------

if ($LANG =~ /ES/i){ #SPANISH (Castellano)
	$D_W_TITLE = '"Conector InfoCard para Eduroam"';
}else{	            #DEFAULT ENGLISH
	$D_W_TITLE = '"Eduroam InfoCard Connector"';
}



#------------- FUNCIONES ----------------------
sub checkcert {
	if ($CA_cert eq $CONF_CA_CERT){
		return 1;
	} else {
		return undef;
	}
}



#-------------- Extraer el CardId de una tarjeta autoemitida ----------------------

system "mknod  $DM_pipe p";

system 'zenity --info --title='.$D_W_TITLE.' --text="Por favor, seleccione una InfoCard autoemitida."';
$got_cert = undef;
while(!$got_cert){
	defined ($DM_pid = fork) or die "ERROR: Cannot fork: $!";
	if (!$DM_pid){
		#hijo
		open STDERR, ">>$DM_pipe" or die "ERROR: Cannot redirect";
		exec ("$DM_path", "--loglevel=debug") or die ;
	}
	
	open LOG, "$DM_pipe";
	
	#Verificar que tiene cargado  el certificado de una CA que autentique a mi STS
	$status = 0;
	$CA_cert = '';
	while ($status<2) {
		while (!defined($_=<LOG>)) {}
		if (/Importing .* card/){ #Fin de los certificados
			kill (9, $DM_pid);
			close LOG;
			system "rm $DM_pipe";
			$q_cert = system 'zenity --question --title='.$D_W_TITLE.' --text="ERROR: debes importar el certificado de la Autoridad de certificación en el DigitalMe.\n Â¿Quieres que lo haga por ti?"';
			if($q_cert) { #NADA
				die "ERROR: DigitalMe could not found your STS certificate"
			} else {
				#system 'zenity --info --title="Conector InfoCard para Eduroam" --text="Importando el certificado en el ca-bundle"';
				system "gksu -D $D_W_TITLE \"echo '$CONF_CA_CERT'>>/usr/share/digitalme/certs/ca-bundle.crt\"";
				$status = 3;
			}
		}elsif ($status==0) {
			if(/(-----BEGIN CERTIFICATE-----)/) {
				$CA_cert = "$1\n";
				$status = 1;
			}
		} elsif ($status==1){
			if(/(-----END CERTIFICATE-----)/) {
				$CA_cert .= $1;
				if (&checkcert){ #es el certificado
					$status = 2;
					$got_cert = 1;
				} else {
					$status = 0;
				}
			} else {
				$CA_cert .= $_;
			}
		}
	}
}


sleep 1;

#Buscar el ic:CardId de una Infocard autoemitida
$status = 0;
$card_ID = '';
while ($status!=2) {
	while (!defined($_=<LOG>)) {}
	chomp;
	if ($status==0) {
		if(/Importing unmanaged token card .../) {
			$status = 1;
		}
	} elsif ($status==1){
		if(/Private Id \(seed = .*obj = (urn:uuid:\w{8}-(\w{4}-){3}\w{12})\).*/) {
			$status = 2;
			$card_ID = $1;
		} elsif (/(Importing managed token card ...)|(Certificate verification callback)/) {
			$status = 0;
		}
	}
}


kill (9, $DM_pid);
close LOG;
system "rm $DM_pipe";



#Credenciales de autenticación
while(!defined($username)){chomp($username = `zenity --entry --title=$D_W_TITLE --text="Introduzca su nombre de usuario."`)};
while(!defined($password)){chomp($password = `zenity --entry --title=$D_W_TITLE --hide-text --text="Introduzca su contraseña."`)};

#Interfaz de conexión, sacado de iwconfig
while(!defined($iface)){
	@ifaces_tmp = `gksu $IWCONFIG_path 2>&1`;
	foreach (@ifaces_tmp){
		if (/^(\w+).*IEEE 802.11 .*/){
			push @ifaces, $1;
		}
	}

	if (@ifaces>1){
	while(!defined($iface)){chomp($iface = `zenity --title=$D_W_TITLE --list --text="Por favor, seleccione su tarjeta WiFi" --column=Interfaz  @ifaces`)};
	} elsif (@ifaces == 1) {
		$iface = $ifaces[0];
	} else {
		die "Not Wifi interface found."
	}
}

#Driver para el suplicante
while(!defined($driver)){chomp($driver = `zenity --title=$D_W_TITLE --list --text="Por favor, seleccione su controlador de tarjeta WiFi" --column=driver  $WIFI_DRIVERS`)};

# 
print "Usuario:\t$username\nPassword:\t$password\nCard ID:\t$card_ID\nDriver: \t$driver\nInterfaz:\t$iface\n";


# print "Usuario:\t$username\nDriver: \t$driver\nInterfaz:\t$iface\n";




#------------- LLAMADA AL SUPLICANTE ----------------------
#Archivo de configuración
$WPA_SUPPLICANT_CONF = "
eapol_version=1
ap_scan=1
fast_reauth=1
card_ID=$card_ID

network={
	ssid=\"$ssid\"
	scan_ssid=1
	key_mgmt=WPA-EAP
	pairwise=CCMP TKIP
	group=CCMP TKIP
	eap=PEAP
	phase1=\"peaplabel=0\"
	phase2=\"auth=MSCHAPV2\"
	identity=\"$username\"
	password=\"$password\"
# 	ca_cert=\"/etc/apache2/ssl/CA.crt\"
}
";


system "mknod  $WPA_pipe p";

defined ($WPA_pid = fork) or die "ERROR: Cannot fork: $!";

if (!$WPA_pid){
		#hijo
	open STDERR, ">>$WPA_pipe" or die "ERROR: Cannot redirect";
	system "echo '$WPA_SUPPLICANT_CONF' > $WPA_SUPPLICANT_CONF_file ";
	print "Lanzando suplicante\n";
	exec "gksu \"$IFCONFIG_path $iface up ; $WPA_SUPPLICANT_path -dd -K -D$driver -i$iface -c$WPA_SUPPLICANT_CONF_file\"";
}




#------------- CARGAR TARJETA GESTIONADA ----------------------
#Sacar URL de descarga de la InfoCard


$status = 0;
$IC_URL = '';
open WPALOG, $WPA_pipe;


	print 'Parseando tarjeta';

while ($status<3) {
	while (!defined($_=<WPALOG>)) {}
	if(/EAP-TLV: Vendor Specific/) {
		$status = 1;
	}elsif ($status==1){
		if(/VENDOR ID: 0534D48/) {
			$status = 2;
		}		
	}elsif ($status==2){
		if(/DATA: (http.*data=.*iv=.*$')/){
			$status = 3;
			$IC_URL = $1;
			$IC = '';
			system "sleep 4";
			$IC = get($IC_URL);
			if ($IC eq '') {
				print 'ERROR: Could not get your InfoCard.'
			} else {
				open(IC_FILE_HANDLE, ">$IC_file") or die 'cannot create IC file!';
				print IC_FILE_HANDLE $IC;
				close (IC_FILE_HANDLE);
				system "$DM_path $IC_file";
				unlink $IC_file;
			}
		}
	}
}

close WPALOG;

system "rm $WPA_SUPPLICANT_CONF_file";
system "rm $WPA_pipe";

