Yubico Forum
https://forum.yubico.com/

Protecting standard webpages with your Yubikey
https://forum.yubico.com/viewtopic.php?f=5&t=350
Page 1 of 1

Author:  fortean [ Sun Jul 05, 2009 9:23 pm ]
Post subject:  Protecting standard webpages with your Yubikey

Hi, guys,

y'all probably know how to configure Apache to protect arbitrary webpages with a password: add some directives in the httpd.conf (or in a .htaccess file) and add a password file with htpasswd. Next time you surf to that page, a popup appears, requiring you to enter your username and password. Works fine, and the big advantage here is that it even works with the simplest (HTML) webpages.

But what if you'd want to use the Yubikey instead - and in OTP mode?

I wanted to do something like this:

- put some statements in an .htaccess file or Location/Directory container
- surf to the protected page
- the standard popup would appear
- I'd type in my username
- put the cursor in the 'password' field
- and press my Yubikey
- and have access (if the key was valid, of course).

Well, I got it to work 8-)

Just to make sure I did not reinvent wheels: is there anybody else here that figured out how to do this and has documented it? If not, I will try to compose a 'howto' next weekend (I have a very busy week ahead, so won't be able to do so this week).

Author:  James [ Tue Jul 07, 2009 6:22 pm ]
Post subject:  Re: Protecting standard webpages with your Yubikey

If your implementation is different than the "mod_authn_yubikey" Apache module discussed in this thread and at this website, I would be interested in how you did it. I think it's good to have more than one way to do something in the event one of of the techniques no longer works or is no longer maintained.

Author:  fortean [ Fri Jul 10, 2009 7:16 pm ]
Post subject:  Re: Protecting standard webpages with your Yubikey

James wrote:
If your implementation is different than the "mod_authn_yubikey" Apache module discussed in this thread and at this website, I would be interested in how you did it. I think it's good to have more than one way to do something in the event one of of the techniques no longer works or is no longer maintained.


Thanks for the links, James. Well, I don't know about mod_authn_yubikey (yet), will check it out later.

My method uses mod_auth_external. That module can be used to call an external program

Caveat! Caveat!

** WARNING: this is just a proof of concept, you need to consider carefully if you want to use this code
** WARNING: it involves running a setuid binary!
** WARNING: and a very crude session mechanism, that really needs improvement
** WARNING: calling an external program can be a real resource hog

Having said that..

To set mod-auth-external up, I did something like this:

$ wget http://mod-auth-external.googlecode.com ... .11.tar.gz
$ tar xzf mod_auth_external-2.2.11.tar.gz
$ cd mod_auth_external-2.2.11
$ more INSTALL
$ apxs -c mod_auth_external.c
$ apxs -i -a mod_auth_external.la

So, now I had a method to call an external program. The external program is expected to read username and password from stdin, it
has to return true or false to indicate if the username / password combination was correct.

As the yubikey software already comes with 'ykvalidate', I decided to write a little wrapper around it to do just that. However, ykvalidate will not authenticate others than yourself, unless you are root. I decided to change the source code of ykvalidate a bit so it would allow processes that run with the uid of the webserver to access entries of other users: made the program run setuid and made it check for the effective uid instead of the real uid). Recompiled it, su-ed to 'apache', tried to ykvalidate root's yubikey - and it which worked fine. Then I wrote this wrapperscript:


Code:
#!/bin/bash
read username
read yubikey

# in minutes, maximum inactive time
MAXINACTIVE=2

# config
SESSIONS=/etc/yubikey.d/sessions

# sanity
[ -z "$username" ] && exit 1
[ -z "$yubikey" ] && exit 1
[ ${#yubikey} -ne 44 ] && exit 1
[ -d $SESSIONS ] || exit 1

status=1;

if [ -f $SESSIONS/$yubikey ]
then

  # continuation of earlier session
  atim=$(stat -c '%X' $SESSIONS/$yubikey)
  wtim=$(date +%s)
  asec=$[ ( $wtim - $atim ) / 60 ]
  if [ $asec -gt $MAXINACTIVE ]
  then
     #echo "session $yubikey is $asec minutes old, expired" >>/tmp/hk.log
     # remove expired sessions
     rm $SESSIONS/$yubikey
     find $SESSIONS -type f -amin +$MAXINACTIVE -exec rm {} \;
     status=1
  else
     # refresh session
     #echo "session $yubikey is $asec minutes old, refreshed" >>/tmp/hk.log
     touch $SESSIONS/$yubikey
     status=0
  fi

else
  # new session
  #echo "session $yubikey is new" >>/tmp/hk.log
  /usr/local/bin/ykvalidate --user $username $yubikey 2>/dev/null 1>&2
  status=$?
  #echo "session $yubikey status: $status" >>/tmp/h
  [ $status -eq 0 ] && touch $SESSIONS/$yubikey
fi

exit $status



(Note that the session mechanisme is quite crude, this still is a proof of concept, any improvements are welcomed).
(also note that I had to create the various directories and make them owned by apache).

I changed the http configuration for the website to include these rules within it's virtualhost container:

Code:
    AddExternalAuth yubikey /usr/local/bin/ykvalidate_wrapper
    SetExternalAuthMethod yubikey pipe
    <Location /test>
      AuthType Basic
      AuthName Requires_Yubikey
      AuthExternal yubikey
      require valid-user
    </Location>


Next, I restarted my Apache, surfed to http://www.example.com/test and the box popped up, I filled in username and pressed the yubikey button in the 'password' field. Works fine. If you don't do anything for 2 minutes and surf to that same page again, you'll need to redo the authentication.

Page 1 of 1 All times are UTC + 1 hour
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/