From 6b74535451f10511f4b3b9506133b8defed4b835 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andreas=20=C3=85kre=20Solberg?= <andreas.solberg@uninett.no>
Date: Sat, 17 Jan 2009 12:40:05 +0000
Subject: [PATCH] Improvements to the YubiKey authentication module. Removed
 the username field, added dictionaries and templates etc.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@1155 44740490-163a-0410-bde0-09ae8108e29a
---
 .../authYubiKey/lib/Auth/Source/YubiKey.php   | 121 ++++++++++++++++--
 .../templates/default/yubikeylogin.php        |  50 ++++++++
 modules/authYubiKey/www/resources/logo.jpg    | Bin 0 -> 7737 bytes
 modules/authYubiKey/www/resources/yubikey.jpg | Bin 0 -> 3318 bytes
 modules/authYubiKey/www/yubikeylogin.php      |  39 ++++++
 5 files changed, 196 insertions(+), 14 deletions(-)
 create mode 100644 modules/authYubiKey/templates/default/yubikeylogin.php
 create mode 100644 modules/authYubiKey/www/resources/logo.jpg
 create mode 100644 modules/authYubiKey/www/resources/yubikey.jpg
 create mode 100644 modules/authYubiKey/www/yubikeylogin.php

diff --git a/modules/authYubiKey/lib/Auth/Source/YubiKey.php b/modules/authYubiKey/lib/Auth/Source/YubiKey.php
index 71b8a3cdf..9262ac680 100644
--- a/modules/authYubiKey/lib/Auth/Source/YubiKey.php
+++ b/modules/authYubiKey/lib/Auth/Source/YubiKey.php
@@ -40,13 +40,29 @@
  * @package simpleSAMLphp
  * @version $Id$
  */
-class sspmod_authYubiKey_Auth_Source_YubiKey extends sspmod_core_Auth_UserPassBase {
+class sspmod_authYubiKey_Auth_Source_YubiKey extends SimpleSAML_Auth_Source {
 
-      /**
-       * The client id/key for use with the Auth_Yubico PHP module.
-       */
-      private $yubi_id;
-      private $yubi_key;
+	/**
+	 * The string used to identify our states.
+	 */
+	const STAGEID = 'sspmod_authYubiKey_Auth_Source_YubiKey.state';
+
+	/**
+	 * The number of characters of the OTP that is the secure token.
+	 * The rest is the user id.
+	 */
+	const TOKENSIZE = 32;
+
+	/**
+	 * The key of the AuthId field in the state.
+	 */
+	const AUTHID = 'sspmod_authYubiKey_Auth_Source_YubiKey.AuthId';
+
+	/**
+	 * The client id/key for use with the Auth_Yubico PHP module.
+	 */
+	private $yubi_id;
+	private $yubi_key;
 
 	/**
 	 * Constructor for this authentication source.
@@ -71,6 +87,84 @@ class sspmod_authYubiKey_Auth_Source_YubiKey extends sspmod_core_Auth_UserPassBa
 	}
 
 
+	/**
+	 * Initialize login.
+	 *
+	 * This function saves the information about the login, and redirects to a
+	 * login page.
+	 *
+	 * @param array &$state  Information about the current authentication.
+	 */
+	public function authenticate(&$state) {
+		assert('is_array($state)');
+
+		/* We are going to need the authId in order to retrieve this authentication source later. */
+		$state[self::AUTHID] = $this->authId;
+
+		$id = SimpleSAML_Auth_State::saveState($state, self::STAGEID);
+
+		$url = SimpleSAML_Module::getModuleURL('authYubiKey/yubikeylogin.php');
+		SimpleSAML_Utilities::redirect($url, array('AuthState' => $id));
+	}
+	
+	
+	/**
+	 * Handle login request.
+	 *
+	 * This function is used by the login form (core/www/loginuserpass.php) when the user
+	 * enters a username and password. On success, it will not return. On wrong
+	 * username/password failure, it will return the error code. Other failures will throw an
+	 * exception.
+	 *
+	 * @param string $authStateId  The identifier of the authentication state.
+	 * @param string $otp  The one time password entered-
+	 * @return string  Error code in the case of an error.
+	 */
+	public static function handleLogin($authStateId, $otp) {
+		assert('is_string($authStateId)');
+		assert('is_string($otp)');
+
+		/* Retrieve the authentication state. */
+		$state = SimpleSAML_Auth_State::loadState($authStateId, self::STAGEID);
+
+		/* Find authentication source. */
+		assert('array_key_exists(self::AUTHID, $state)');
+		$source = SimpleSAML_Auth_Source::getById($state[self::AUTHID]);
+		if ($source === NULL) {
+			throw new Exception('Could not find authentication source with id ' . $state[self::AUTHID]);
+		}
+
+
+		try {
+			/* Attempt to log in. */
+			$attributes = $source->login($otp);
+		} catch (SimpleSAML_Error_Error $e) {
+			/* An error occured during login. Check if it is because of the wrong
+			 * username/password - if it is, we pass that error up to the login form,
+			 * if not, we let the generic error handler deal with it.
+			 */
+			if ($e->getErrorCode() === 'WRONGUSERPASS') {
+				return 'WRONGUSERPASS';
+			}
+
+			/* Some other error occured. Rethrow exception and let the generic error
+			 * handler deal with it.
+			 */
+			throw $e;
+		}
+
+		$state['Attributes'] = $attributes;
+		SimpleSAML_Auth_Source::completeAuth($state);
+	}
+	
+	/**
+	 * Return the user id part of a one time passord
+	 */
+	public static function getYubiKeyPrefix($otp) {
+		$uid = substr ($otp, 0, strlen ($otp) - self::TOKENSIZE);
+		return $uid;
+	}
+
 	/**
 	 * Attempt to log in using the given username and password.
 	 *
@@ -84,9 +178,8 @@ class sspmod_authYubiKey_Auth_Source_YubiKey extends sspmod_core_Auth_UserPassBa
 	 * @param string $password  The password the user wrote.
 	 * @return array  Associative array with the users attributes.
 	 */
-	protected function login($username, $password) {
-		assert('is_string($username)');
-		assert('is_string($password)');
+	protected function login($otp) {
+		assert('is_string($otp)');
 
 		require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/libextinc/Yubico.php';
 
@@ -94,16 +187,16 @@ class sspmod_authYubiKey_Auth_Source_YubiKey extends sspmod_core_Auth_UserPassBa
 
 		try {
 			$yubi = &new Auth_Yubico($this->yubi_id, $this->yubi_key);
-			$auth = $yubi->verify($password);
-			
-			$attributes = array('uid' => array($username), 'otp' => array($password));
+			$auth = $yubi->verify($otp);
+			$uid = self::getYubiKeyPrefix($otp);
+			$attributes = array('uid' => array($uid));
 		} catch (Exception $e) {
-		  	SimpleSAML_Logger::info('YubiKey:' . $this->authId . ': Validation error (user ' . $username . ' otp ' . $password . '), debug output: ' . $yubi->getLastResponse());
+		  	SimpleSAML_Logger::info('YubiKey:' . $this->authId . ': Validation error (otp ' . $otp . '), debug output: ' . $yubi->getLastResponse());
 
 			throw new SimpleSAML_Error_Error('WRONGUSERPASS', $e);
 		}
 
-		SimpleSAML_Logger::info('YubiKey:' . $this->authId . ': YubiKey otp ' . $password . ' for user ' . $username . ' validated successfully: ' . $yubi->getLastResponse());
+		SimpleSAML_Logger::info('YubiKey:' . $this->authId . ': YubiKey otp ' . $password . ' validated successfully: ' . $yubi->getLastResponse());
 
 		return $attributes;
 	}
diff --git a/modules/authYubiKey/templates/default/yubikeylogin.php b/modules/authYubiKey/templates/default/yubikeylogin.php
new file mode 100644
index 000000000..6632a19b6
--- /dev/null
+++ b/modules/authYubiKey/templates/default/yubikeylogin.php
@@ -0,0 +1,50 @@
+<?php
+$this->data['icon'] = 'lock.png';
+$this->data['header'] = $this->t('{authYubiKey:yubikey:header}');
+$this->data['autofocus'] = 'otp';
+
+$this->includeAtTemplateBase('includes/header.php');
+
+?>
+<div id="content">
+
+<?php
+if ($this->data['errorcode'] !== NULL) {
+?>
+	<div style="border-left: 1px solid #e8e8e8; border-bottom: 1px solid #e8e8e8; background: #f5f5f5">
+		<img src="/<?php echo $this->data['baseurlpath']; ?>resources/icons/bomb.png" style="float: left; margin: 15px " />
+		<h2><?php echo $this->t('{login:error_header}'); ?></h2>
+		<p><b><?php echo $this->t('{errors:title_' . $this->data['errorcode'] . '}'); ?></b></p>
+		<p><?php echo $this->t('{errors:descr_' . $this->data['errorcode'] . '}'); ?></p>
+	</div>
+<?php
+}
+?>
+
+	<img style="float: right" src="<?php echo(SimpleSAML_Module::getModuleURL('authYubiKey/resources/logo.jpg')); ?>" />
+	<img style="clear: right; float: right" src="<?php echo(SimpleSAML_Module::getModuleURL('authYubiKey/resources/yubikey.jpg')); ?>" />
+
+
+	<h2 style=""><?php echo $this->t('{authYubiKey:yubikey:header}'); ?></h2>
+
+	<form action="?" method="post" name="f">
+
+		<p><?php echo $this->t('{authYubiKey:yubikey:intro}'); ?></p>
+	
+		<p><input id="otp" style="border: 1px solid #ccc; background: #eee; padding: .5em; font-size: medium; width: 70%; color: #aaa" type="text" tabindex="2" name="otp" /></p>
+
+
+
+
+<?php
+foreach ($this->data['stateparams'] as $name => $value) {
+	echo('<input type="hidden" name="' . htmlspecialchars($name) . '" value="' . htmlspecialchars($value) . '" />');
+}
+?>
+
+	</form>
+
+<?php
+
+$this->includeAtTemplateBase('includes/footer.php');
+?>
\ No newline at end of file
diff --git a/modules/authYubiKey/www/resources/logo.jpg b/modules/authYubiKey/www/resources/logo.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..3b7e7f360ddb176fd383a8bea0d6b500fff95cf5
GIT binary patch
literal 7737
zcmb7IWmp_bv))}`k>D1Bv$(qicXx*nU~zX%kU($<!QCOa1P=s)y99TF1q}pUEXZB*
zo%7xM_rCMYOg+<GJvBYm^>)?c!s9vsTTxa)761eS0rKzz@VEhZC*xyl1puh10GI#(
z015yJhzme~OF;Mm01^X`{>lJ=B9P?2vL=w>pFSV}Alw#!_)i~0`27j+k)O2xxr6dR
z|Mmc~<RSbk1E5b`AD01A0MHYFf3F}A0s<Hj0S;s&Bt$R@G78GmiHe5t3>6g}4F%;H
z)-!YrOgK=VVdG$7;ylSugFLCjwZMpoU`$jL)TbW*KRk8=a8LkHAPWKz0s!Fv5paNy
zy#P}9hakY`3qE820*s7;gopt8+X{aSf9?Oa0RSKbFftGk3FUDKfDUf}VIyF}Cu6Pi
zNgL5nD}&SLwcBWO86|qPlbrGAv%=-X?GG5y{YKo&f5%4=OAS@E%V@&oge_dUh!{*A
z%<C+09IN^rHCh{@3XQYW_}@I}RFzM@EL7V0=w!@XFFbPcMRDims%z2y_w!4#`l{P;
zE~nJKE#{v-=W2yxeVf(WX&&^6cj@J4H-Yx$)9+*ZCx1)jk<r!vv1TQyb-)S`cdyH7
z&-YvnR8z5rbu-@_48J-0&hpNB3^|umz{Yn46xdKTlu%k(p*UUOE}J?=g8QAYXyi>o
z5ti^?+x`d1v-^iY1L?gg_6(kHLc|A^^~_>m!OXAYd&ki?cM8gKpZXnJ7{4~FP1{X1
z>xk5|mUxO9%n%vTNI4sUxaqb%u7^!(4j%!#vF(!!qOph4?#5juFqq3r<S^G**@Voi
zuNsE%ubpWbOJ;2xKi_bPJlVbcVB|@~=OAbGD&wNv*<s^k!&)U2?c!yb)#-OkPV#{0
zvTEg41GV}517$_7jKt>UiU_B|ZP+D2P?9o|hJD))uD*LlpGov;)2CS%K7E7uj@*Mh
zJbDSSlRQvbg7WDp91yN!dbNn$wX&;ofejxT3dJmwW|LVr+MU#UCTT09@m)t_f6Iq}
zaO^)MiF3#2SLD6#p49#eEVu_TV?X&f5CjGy{^KYJh#({&7=X)%gNIK@$t#XcAfXPS
z<=}+73<}(#fJmT6K+A9YIR`z@66^Kl5r~+Jj;j~qRBopCDzE?0$zs1G)qeUmz9ojq
z32}#pTzFlc)I-Q3HVN7q!`AOs8k{ScKwKAR>TZXKnEf9N=XYO!XMFqVbx%wGyA3wK
zQU+xcGbP?`pET(+cyHs{oGfp-6cn>%|2^st1pNJB{S%S6f402Rs@tiFm2zUpx`v-u
z$Rl7N8RK@CM7N#nId90V-r`&9j9vTFnuhteC8_??m~BaK?(@M@4n;o0QmpO)O_{d0
zP8ye0h1WIZoKap{HMVCX`ky-&bV4!Ex6lk1al2si+$y_zfx`?DU|WZs=tltIe6(kM
zNQl2>2h(>O`?Ah32LV8rN0ag5PRr7r{Sohv{p~f6*(-WJj`fT+UfW$>A+>3@kBwdl
zyL?7fhD@5Lp?VI_Y0h|^?D7Ya$4UiyjH=jFBu*E#&KxBTfK6(2m2kV4c1D(k=gzk(
z|7*G4O4fo>&@a;2{48xpF_mG_*(Iv1*RGPivsvS=F~$QmIy)7@0c&H`KKD$}G<y>g
zk9)`GoH4^T%pv8zKBTz@+x`{2i+rP}$XPpDe<x$Aww?E5Yu}`~)mu75$cqr2Zk<<u
zO?9^a3DY|_@OZOlZHFcE;j6Cj*{0n*0YsNz4yihDmC094Q16g=D)Z8{pBgK=vQMx@
ziHq(_ZfVQCSU9Y5@Os`+Fm5i4F;(BnQD>4Pbby8T(&!6erL(%@>(bFTJ!jdTlCzWB
zeZDN}m-T)%h6>Ye-5=zNUqi2ViMLClZX51gKca{jHwN#{k%qK)*l&LOJo7Vyxu9mm
zyeCHKav4*rWUurQ&`2eVeFxS^<7OBbB6acJg2W=;MGwO4tI;cZI3aWAnVL;noUo*K
z`(@1(>HWHo0Phs^2qa|FWrI<BL1p4@?8D_aWkU1t6p8@>@Nk;AKPv;@iQw!&7bRyy
zE4BV%C0}Z=d1N~!7gRS!nubGMfnx}d64ESqGRE06f()a8uNZ0^IJ<y=2#8NS^dA60
zIGhOBxKxx7aS0AdjlU}e9+t&`u<0(|oTNKEm51jl+%(e;<+jn1&54Q9%@^La9f(?%
z#^{sy3&+>qnsoK^@nk<ZTniH|_Flc@am~sU)B0%XAT>$CE=QqDo0AIBX7pvXP>f$%
zm=DI2kyUe}6|3zrq;RKmovn=GJX?GZ7AC^wpgj$QTPT79=TI;L2n`wei67wrf&d7J
zNMIaXDo%+mWNbVQsH<C0d@Vi!goBG`628hM^EXat#Wf4+{@M<Dvi%RtX#cK`fc-T<
zf$w{1BfW4Sw@c$Ufc`QY<BIu$JpIS)XQjOCnsUmJq@!B^;kWQCk3Z?#TD++PRpYvg
zDgAiQ>9D414wv!d?IJ7tMcC?k%0{fu>B<ix_Whh`cIG|{@)Xm$VyouV=l~2&^hZsU
z)i<P}OikIW-SmS(M^3D2W5paNBkqX5aOkcY4<}}e<_IB^FPGJ2Vs|n|M_SAZvdB^~
z<h5(-i9QMW+as>2#?6Z8rrTm>N4JRrvsBA%8qTVn!}B3OR20;xsg>qkCHn{$&6{;I
z=Q-Ia&N!%9+3gc&z8|2)0z##2d^?->W-eeWQxrsm>NBn<@0qu$rt!12;t#|+GU@Wv
z6Vk|<9|5oZmV%PcIErZvYgF@Lx4ePZd50g4RCD)Zg{X%<QN*+!edOD~`$=}$Ot`+g
zO@7(Tk3vOWM>vnt5$SAym=n0w{zd5KDm#0lysnThFgn*=B7X@wL3YPSXxj=h-6RY;
zf{MH$EYM8k_l_<Zs*o-kCSNNY<wvG9PPuUC>4-HAXAbj8UBmcroAC-%I#?tix5KhA
zOeUn%V8dm%lpPUmXa?<vAVt_}6Ub^(t!_#Rx-~rlz)90u{M^r#UKN_==f2gQ+DjYc
zq3U)eeHE>gXQ$wv?1u7LBw@m%a?YG!SOyg5NpHMyhanWil*~rf?WGScu&AAIjed3I
zBTKeXKCIw6auE^u(PsC4i2$aCcpNWD0G$k+EfYYE(!M!#8S|R&=+RBrbVv2mV+C^p
z)0zrf3Iirp#64h(&AQk#?IH)w$T+RDHPf+<>=%2M0(~LmR`FBnX9Il)+S-l|_uWaj
zY(6*A8-0H1%!-kK{eFC`wlt~Klka3$qbTNpt0hC357SWp;CZr3C=lP6R&iIztybsG
z@nSNb&7{Jg0@D=pkH3Lt^StKjADSG0Wcu)j3^2y85@v;&i#2O?>x9$|N}BEDKG@*<
zs$1e$pk^$5ZQdsDmI?Gb-iLYk>Jf)CB7D1sgo1>M@}DIR1R(%$5OJ~bs34qN5>IQ#
zy%vd*nx~6KTv9VAK5=pbpIb^@%Pb+EBl!J4Gzk`i(`5E~hFKjuPTZ6f>CeHPVJ-?C
z65JaE5{%RuAF;5R`p(5dC-9nR-&J^AC02}x5nC0xnvE}WfZdg!+(t$Za|N^Gf}Fuk
zOq#D*@2+YnMK;8;m(AQhnUL66_)FOETx)3~9XV0$%jHip_B)uGm#a0an;pFY9-KJH
zC@Rej!dAj6vz6X*yHZ%Vs-)4!7)0Mr&Ip1|Ly6|D)8(+Uke7{ra$R?PvUt@ecCnUQ
zFFC>ypPb3I{-04i$srtF6k$$++-8>Ad!#$<v4ncRtQwt7Lt8)HGqbdgatHb>UhUb^
zdVWC0?XN=A+!VZlv=6@OyJuiI9SZ-o$sp`d9Ug={7fxLGhvwQQOwt+hyThhz=i7Z<
ziR~mCZ~y%2$NHR)5v|n6%{eh@Q9nE>TpP^(^bBf7oLhezZL{b5WPadXTV+f~{bFa2
zr#ePwW(8+VeN!}^WVI3b!-*h=|MZS+@fOu0@kNHMl{?Lc-VEmOj~t}MLV$`$j?p*V
z#Iu_ao6MS=r0jRJcy1iS{uy_+(4c37E3^JiM9s4;#bFkVkW+99zjMN%L(c*1b{e|&
zzN&1?)mqD3E!6xgL+fQ!IJm?N{rj>;7X|B5cR{eIBx@)Ij)&Zuvj|ZxLEC}omd!uE
zk4I?v4IR30gBjkz$VsWNbI|1b-?`lSHUUusna5(qF~W*`+h0AiiQA-=m^|m0*~Uf-
zj}{9FBAQ^`7(@mGgqkIXlOb`ZoX>7YA~jk#mVXeC4%JRpGdW0|W!EffZs|Ly%pC1b
z_{mHlOMfWD+icF3TXFp7kA_7iox0)s-_j?he_FiKCg<<m>$*})FEvTezupVhS$YAS
zbaP-PaI&YkDkPu~NO%PNx|j_9nCo+6)5W+|fjpN%$xiv>V}lJ^!J*2#QkSi$4_i~d
z7iOU7y5svL3Z3{ZCx+P+o-oYXhDj@aGbfdQUyVu4=KpG^S><h3`qvBMS2Xs65@QPZ
zipH{hp!^<;7TM`3J1mlQ57R#-qqCdOb6B^@M5tve7;>=!6oiGCt#FN29hjMy1OkgY
zh-XD-d=3K+60sPT+OXvJt31pF<E>TW_3m?Vatkf_Ag{BA3-_Yr@k!e(L_opSok-zT
zd{o~e76ete$!S*R+QaMLJKwjo%ccVMfDd@*UOJ5$vF)b$biBQXVqtB$bDunWp|b`<
zpaDxZh(f+6noP<qeQ(i8dCLOEEu-f`TBC^)J@F-857Q&SYrn?k+GoD_s&d5FTG+x7
zr;nt_(u5E8cAVmVhRE8|N}?fl6)fRHFZ|l~kIdVblu2Go9p2cFfT^13-glyvQd{C4
zx(f3)Kfi1?9@0d4{#xbzy>*J@SFFEb9QuQ|yyw%mdUDoZJz+f?B?+`Y+{!*@T(RhF
zWW@3jCN~!yJvdk-2UBjUmD5DN&tI3Js}0_9s0eV^5O=PO!~H5KVl$b>{IU)+H*2JA
zbF>XhzY?Eg^OVV=PyZ{QdFOm#K2er*=@FHq`Hw%1`|^4Ir{OB{!oX#X9`0K`tOyTk
zmhYbaS^Wi>uU>wG#(g_xIM*w@`l*&&x@xaiXi5|#zLFTo_Xyw@c>~2Ypu<Mue4%Q_
zjn>2CdMlNB6f@1t%x?J$d)T3yj`BWv@6P)ut&G;|qk#1)RZEqA?@+AGhG_)HSxD13
zz2h4qb8?^EIj*c4^Uj6C-A~Hnm%HX}0WK$s>?F~|A;MoGW8CcV2e0@W%Y~0<oWk}_
z8`JIl_ZN%RX{_Q_?i=cPzQjo7t;`MiHH_gWhVWm?Tp`_7=+Qx~Mn9=U<zxg)o-5Hv
z1lKo?FZF(9bMyg;`;cf`sKr=FwU8*gMfofzjF_u$j5`|1xE<ZLF^t!#g(pRGOJ0sG
zYe;3dRyYjN)%%ezX^$Q|7w!Cf1Tey5KNB`Q!2uy6Aw6Z)|Jga=0I0AzpMri+d_HAu
z*W`(~`soJ8zsZmo)gxdvuT8nHL^5K^%<b}`$oHq)8@*jorri%d%A7UlHvzE^2}ohm
z;W7b*n_-}DxPf4Be^}RyqJEY8M*C@CV^%j&<H6Yg3IJ92qO-JjgbfLA3IMGSzHMbF
zGK+Z`#L;Zz8xVUjYM8o`pL32M=Sr`YUX2Z}cBH+&HdPnH4|-9!1w1nrV<>{QK07wy
z3w<`&nAmtO3F3Om^WrxYl-tL<avVtT&{nX%>UEoXD(h+G<F9Gdue;PfzF_z{VC)c9
zYDPXp;m`4Xs=c0HZ+XgA?5%%5)4~}LqjN_X64CP#p;jD6!Cg3{FebFRv`X5{#$i6Z
zUj`hmJbTSuWPo>LX*dyeu(VFI@mq_GH?)N`L#B(sqmiV5RbaKRGAKf1H44#1>>$b?
zi`Y&VeQr@Oz~3O=)?x3$&S&l|t-kve>(G%QhkZ0V`Gur>>x_+ft8t>jpXFb$ri-(v
zJ7pmyc0ZyPMNbNyjnjDLkqFn|4D}f*|0%s^-%&BJkQJp(!u8*h(&RPqK}_76fG4i~
zy;m-lJFcxb2cIurl`P0*D44c7z6x?Z5hO@R4fJvf@5t-Na~Ij&#rm;kQq?5fA?Jr1
zOt!}VdA)q{0;~1pdax-LIpW)}Tan+%4oc^X3biz;g6Bv|O&`HT+~9@{E5i7*)Ek&S
z@S*CrXV(KhhHl|kh~27p*A61Ek3F(8t&q0ix5KojQ|8a+D1QuUUVB*6Kw>E6>uBZ$
zn}J5eEUHsiJ8<xuhKuOj=f*JjR{=9uHSWBMq#<<XpOnxQCwKjH9WPOirBwOk>ig_<
zCA&_bN|LICaixGbbP7+t?bx?M-}}VPR1m}~9&+jPUBWQ1v|n}*ksTn;yA#J}y;iyx
zsg;nFpYHV4#I#x=Rt{SwFj|$B%I5ki9z1BN@d2Q?ONtndJ^1;$qF9OQC?Us@<Uul+
zxLj|EF@y@-K{?U=8pa(FGMycmdr|yu3$k*zQQ%JUc37_Q*gtV69{+7YmM6I+%wGd9
zE;xod)Yn9Nb-L~m@G)Zu2B#Le*Cr3FhTT6lnoVAhr(08!iMnikRr*vSiFH&!y#&#}
z7)5SS=9tqA^s&(Th~y?szcw>^7_*?#8c1j2&Q(17XHqe_sj22uUBxkt1tMvb;dyk&
z_am(WMfK4Yn(;|F&fgil7;}a1zqvV&M)OSkKDu~~TkWlICdc8d7b||kZJIw5oC=jl
z8&2FXN}}Ae&+&*5!BsZ^HE%0vh+>nNNvjzS8pPg-4Vt^6^hh_*O;Zim+vL(nVW1Kq
zX($VZUEDGV9}8^tC%P0!mYIcb1!JZozlqlm=N-S%9_ROa7rbgG50L=t&Q~d1ls3s%
zjP>(dd~HN|X26-!pE4TD(p$GPr?cXX`cMLo5`U{~f6I~ZLK_@7MTq8q1%Ui$I_hW9
z&@WL7F!=}o4?)yW9vVU(G9wJz4S<A=xVDcQ)-T3db;2VKL==Bg0loutzXRkwiBAwr
zVJ<h({*V0c6#*W@D4z0Dc!v6a>V7~RY${F;aY_l-lfQxMDL2KwX=ftM>>;4~8StW;
z7J?cgBFho+lcoUG*`f@C&y7mVCNJ#|!X9=ij~*J+#=84U(zcv%H>!mlZz11^eQDeX
z_obIe@m)jt;1HNK6S*UyHht*|G?Wwr*GitTCiWIpONKx#uj9BY5+g!P4{jGD&QtXW
zUIax1{+pHJPyskKB%ndquK67CwI`I~U6UK9e=U5<K(QYz7?|*r_R{+^p)^#KJ2j%g
z;t-U=xCJ@uYz(Vz1o33qk&D;QSgXF%IfwrAe8{&AxEHygR@8TR>HcP2xH#hT8e=)^
zv}$*sL;JZp0dqNL`<4kwRgpFU3a*0d*UMQ;CN$DPs?F)9cU#f4)U+bmRQn)V==E!2
zH={!jgXA~({d)E&?AOd{p%eSt>0BQo1$dHVWTl!gfcv4|{YwNt!rU7{BBlG5bIx)F
zZXzOyC6zBz2cf4oy!yf&F87CHYAw6gH_5-BnS9<AxBl}{B7ondCx95?*q4aiS6GF7
z_jLJ`_q_E7zuW@erk#>3cnWVzX2Q3#4DI*mI5%%!P!8<AI-@z|?Fjkv{t(vgKf!+N
z74c+QQYK)}uQTl6U+dLDD5e4+;sFcriMCYrUgi-p=bvpT=BZk}Qi!>1zv|Vu^av!>
z1~#p7yRJeSCG`IG+WsZ!_4;|o5e`#wx(eHP7kTU264M9*{-W*+GJ_pJT91VnFlK{J
zA?}q0p6J9@a8Gg48BM<WVA%M3@+G2eJ+|qV&0x9>tC+8RR>Bon>C4iPNZH;6FXo(z
zUKjx>Z!~!He7=cic9gQuonBYX{`-XD30HO3uTZA3FR_cuf~81u^<Yt)OEv8{JLlzU
zKmG%WDB7ih=i`Ngw4e1lEm+1zc<=}Z7gULeTx8j#ZTj9tx)k!6V{(>oy75dQqa&<)
z&&Kc}0=pAHyU8O2^P2oKNF10t+1uU31(9Q)U4vff6CMUC!5xm_iOk{d_EZA@UowB<
za%?!6Q|8y6aEPmKbp4mgu^(J7CB`UUgNMSBR6$a~n&bg&^R+~@l(kODMy#hTXq`&2
zxtlJ)z_cROJt9HAFUkHdtNFzW2+PZPu%#nn8Q2QLq(Nap{N@#cMYPgIWwdF<0EHJJ
z$N&;Yg~ZR6rgb5{dkpqDFU%YmuO{tDI2mP!m_)R~(w+GH`~(0wk{E1b(DkI5iqL5=
z#V3sEb-*yXoWtovNr<E-4q@no7XD%<k_%&UjSL#Wiz5T$Q_{&SAO91~d<*-`vqA&Y
zQ2G?1cZDprU}?`%EzTVG8seGbO=Yjq_zjs~-a+cuqAXV_NL1h6Qn+%TjkZ$GGG98m
z%kDI`#?3b{FN#a%(j9dkv71#KRFrR5pp}IYOVyEk-d6p{&0jtHV}gLVp_781aH>v+
zw^yJws+HviRIU%tR<YwIFlC9DDw^_}@u5i!xt8E)%&F^y`XIT;HbUO8)PQ@$YvozN
z3Z^PPw3}IYc)~t7Ob}X?Lbuw%hGUIAfR0azM&wCo!8|{RWSE|L5HQS#p&Os8NLf7<
zbFXd2J#TOr>B{l}c&C`~-i+v{8$LvS@D7TN7VC746=fd%P=>dtzYKN29XP0~zQPoA
zF`l;XHTNk^eV4pm8vH#vFVfe**zjKWSZ(6>jekw}9{*l?oYlIdms;7Rk^YbQM?fGV
z9<E*w9_`-SPa!*Kkij7o#UF=W2&(ZPMi)}@q7J9Yi|~R>>hsrtBQexp_dJY$Z<MB{
zv1=#LT{Onj`yy;pq_9dd11M^THN^{Cz(NA&;zsc=5ujdxQ@wEWXnLv@EYaNZ)x9^^
zB1r)V*P`>CAj&uV>Vfw88QGmU{)GeGs9`R>k@hXWRyDJ%SS5?<1hnW~69-fP`d!<l
zf0+G$m&~+7Bvs0>{i{F3(9R<vZ0G8H0xQRP48YDLo<oep5A*${JxP<i1{Dkd-kL=r
z{12UYq;gU}qZPv^5b7vc;y7Xm7lW1Xxg>GFjf6M8G$Pbaem$ET>W49?6{`>#Ce+7;
zJ2m_WXkXLe=p(G(W}SPs{4OuR-6{9o@ZK}sHfo60Hl4u75ImeB+#yO|aaD;bh?Tfx
zOk|<F5oo>zYU-9xcbO8C1}n}P3MgL})$YgfatG$C6vm!u?H3OAL7gLV(s>Gexh7RT
zFb2Lw%S^4uT(&#;GqeZ?r$Do|^>pke!*KgozJB31B&zHJ0)K74=&9Uk&PJkRoDeT)
znmRHd98QVDLXJB?><m%BP3a-#Y(=?5YR)^;yOZqDhGFB7WMWx>&($Z2>pr9COU}F(
ziCYL8-0Qs(WR9Tb5mcUFqKcH@eo?eY`?-XYzOLB3Qq~3WMzJZfQ_6_l?Vueaty^A}
z^2c~$h?_2aBXT;K%7URXHIhJXcW(HLf`QQ;r{rD<W<V|@fE{$Cc}!?^f+LkJSgU#@
zr$eokq1#3pGeMhjBWGapst+R?p{>0Xf0XL-*?Vx%IcSz=bOZ&;Jh)UDFkkL-Ae-_c
z(EN+oFRs&PAwZEC;X8vp#9{h;ygurL+2<!`JqN+Uc}Yx8=t6gC3-hQrEuia%p)$k)
z?#M60{K$$y`n1JWJy7h#w^O3CEt=wJXgHR(u)}#FDX8Yo99=}eS-2&2%okY(hqG?8
z36jie7_(B`VeH3E++(GzWAY5#L{8eyIxR=l=r8=0z@41WXc1DuGr^RK?mjH2As(_t
zTWhlfK%xWO3bhUKay!;K3oxN=#2IdI9a5Yp@nn{O>MoseU@dJ(DrH0}4x%?hOZ5vB
zI@G9TFIz{<F(gxm7znkJ_gu6TOK2|&CFApHGjwVoWH^PlcthI?HJY2vk;N)LDS<oT
zv)E-mhTAjtt~{c5#nM{AMK*OAm_`oQya*DsmIL2jD3TG`;D@M>G4g)N-uJ$ji@?qg
disUcuMVf8ls+1o>mt_$DGx$O7F86Wqe*ky}(C+{M

literal 0
HcmV?d00001

diff --git a/modules/authYubiKey/www/resources/yubikey.jpg b/modules/authYubiKey/www/resources/yubikey.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..f3c8d0bd96f6752de7f5dbaa22be933e261da6cc
GIT binary patch
literal 3318
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
N{vAgzLU%ZM{69oy(Z>J)

literal 0
HcmV?d00001

diff --git a/modules/authYubiKey/www/yubikeylogin.php b/modules/authYubiKey/www/yubikeylogin.php
new file mode 100644
index 000000000..3c281507f
--- /dev/null
+++ b/modules/authYubiKey/www/yubikeylogin.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * This page shows a username/password login form, and passes information from it
+ * to the sspmod_core_Auth_UserPassBase class, which is a generic class for
+ * username/password authentication.
+ *
+ * @author Olav Morken, UNINETT AS.
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+
+if (!array_key_exists('AuthState', $_REQUEST)) {
+	throw new SimpleSAML_Error_BadRequest('Missing AuthState parameter.');
+}
+$authStateId = $_REQUEST['AuthState'];
+
+if (array_key_exists('otp', $_REQUEST)) {
+	$otp = $_REQUEST['otp'];
+} else {
+	$otp = '';
+}
+
+if (!empty($otp)) {
+	/*  attempt to log in. */
+	$errorCode = sspmod_authYubiKey_Auth_Source_YubiKey::handleLogin($authStateId, $otp);
+} else {
+	$errorCode = NULL;
+}
+
+$globalConfig = SimpleSAML_Configuration::getInstance();
+$t = new SimpleSAML_XHTML_Template($globalConfig, 'authYubiKey:yubikeylogin.php');
+$t->data['stateparams'] = array('AuthState' => $authStateId);
+$t->data['errorcode'] = $errorCode;
+$t->show();
+exit();
+
+
+?>
\ No newline at end of file
-- 
GitLab