Skip to content

Commit

Permalink
Add initial support for TOTP/HOTP keys in Yubikey NEO
Browse files Browse the repository at this point in the history
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
  • Loading branch information
David Woodhouse authored and David Woodhouse committed Nov 12, 2014
1 parent 17a18f1 commit c24046b
Show file tree
Hide file tree
Showing 10 changed files with 536 additions and 6 deletions.
12 changes: 8 additions & 4 deletions Makefile.am
Expand Up @@ -15,7 +15,7 @@ AM_CFLAGS = @WFLAGS@
AM_CPPFLAGS = -DLOCALEDIR="\"$(localedir)\""

openconnect_SOURCES = xml.c main.c
openconnect_CFLAGS = $(AM_CFLAGS) $(SSL_CFLAGS) $(DTLS_SSL_CFLAGS) $(LIBXML2_CFLAGS) $(LIBPROXY_CFLAGS) $(ZLIB_CFLAGS) $(LIBSTOKEN_CFLAGS) $(LIBOATH_CFLAGS) $(LIBPSKC_CFLAGS) $(GSSAPI_CFLAGS) $(INTL_CFLAGS) $(ICONV_CFLAGS)
openconnect_CFLAGS = $(AM_CFLAGS) $(SSL_CFLAGS) $(DTLS_SSL_CFLAGS) $(LIBXML2_CFLAGS) $(LIBPROXY_CFLAGS) $(ZLIB_CFLAGS) $(LIBSTOKEN_CFLAGS) $(LIBOATH_CFLAGS) $(LIBPSKC_CFLAGS) $(GSSAPI_CFLAGS) $(INTL_CFLAGS) $(ICONV_CFLAGS) $(LIBPCSCLITE_CFLAGS)
openconnect_LDADD = libopenconnect.la $(LIBXML2_LIBS) $(LIBPROXY_LIBS) $(INTL_LIBS) $(ICONV_LIBS)

library_srcs = ssl.c http.c auth.c library.c compat.c dtls.c cstp.c \
Expand All @@ -27,12 +27,16 @@ lib_srcs_posix = tun.c
lib_srcs_gssapi = gssapi.c
lib_srcs_iconv = iconv.c
lib_srcs_oath = oath.c
lib_srcs_yubikey = yubikey.c
lib_srcs_stoken = stoken.c

POTFILES = $(openconnect_SOURCES) $(lib_srcs_openssl) $(lib_srcs_gnutls) \
$(library_srcs) $(lib_srcs_win32) $(lib_srcs_posix) $(lib_srcs_gssapi) \
$(lib_srcs_iconv) $(lib_srcs_oath) $(lib_srcs_stoken) openconnect-internal.h
$(lib_srcs_iconv) $(lib_srcs_oath) $(lib_srcs_yubikey) $(lib_srcs_stoken) openconnect-internal.h

if OPENCONNECT_LIBPCSCLITE
library_srcs += $(lib_srcs_yubikey)
endif
if OPENCONNECT_STOKEN
library_srcs += $(lib_srcs_stoken)
endif
Expand All @@ -58,8 +62,8 @@ library_srcs += $(lib_srcs_posix)
endif

libopenconnect_la_SOURCES = version.c $(library_srcs)
libopenconnect_la_CFLAGS = $(AM_CFLAGS) $(SSL_CFLAGS) $(DTLS_SSL_CFLAGS) $(LIBXML2_CFLAGS) $(LIBPROXY_CFLAGS) $(ZLIB_CFLAGS) $(P11KIT_CFLAGS) $(TSS_CFLAGS) $(LIBSTOKEN_CFLAGS) $(LIBOATH_CFLAGS) $(LIBPSKC_CFLAGS) $(GSSAPI_CFLAGS) $(INTL_CFLAGS) $(ICONV_CFLAGS)
libopenconnect_la_LIBADD = $(SSL_LIBS) $(DTLS_SSL_LIBS) $(LIBXML2_LIBS) $(LIBPROXY_LIBS) $(ZLIB_LIBS) $(P11KIT_LIBS) $(TSS_LIBS) $(LIBSTOKEN_LIBS) $(LIBOATH_LIBS) $(LIBPSKC_LIBS) $(GSSAPI_LIBS) $(INTL_LIBS) $(ICONV_LIBS)
libopenconnect_la_CFLAGS = $(AM_CFLAGS) $(SSL_CFLAGS) $(DTLS_SSL_CFLAGS) $(LIBXML2_CFLAGS) $(LIBPROXY_CFLAGS) $(ZLIB_CFLAGS) $(P11KIT_CFLAGS) $(TSS_CFLAGS) $(LIBSTOKEN_CFLAGS) $(LIBOATH_CFLAGS) $(LIBPSKC_CFLAGS) $(GSSAPI_CFLAGS) $(INTL_CFLAGS) $(ICONV_CFLAGS) $(LIBPCSCLITE_CFLAGS)
libopenconnect_la_LIBADD = $(SSL_LIBS) $(DTLS_SSL_LIBS) $(LIBXML2_LIBS) $(LIBPROXY_LIBS) $(ZLIB_LIBS) $(P11KIT_LIBS) $(TSS_LIBS) $(LIBSTOKEN_LIBS) $(LIBOATH_LIBS) $(LIBPSKC_LIBS) $(GSSAPI_LIBS) $(INTL_LIBS) $(ICONV_LIBS) $(LIBPCSCLITE_LIBS)
if OPENBSD_LIBTOOL
# OpenBSD's libtool doesn't have -version-number, but its -version-info arg
# does what GNU libtool's -version-number does. Which arguably is what the
Expand Down
9 changes: 8 additions & 1 deletion auth.c
Expand Up @@ -1064,6 +1064,10 @@ static int can_gen_tokencode(struct openconnect_info *vpninfo,

case OC_TOKEN_MODE_HOTP:
return can_gen_hotp_code(vpninfo, form, opt);
#endif
#ifdef HAVE_LIBPCSCLITE
case OC_TOKEN_MODE_YUBIKEY:
return can_gen_yubikey_code(vpninfo, form, opt);
#endif
default:
return -EINVAL;
Expand Down Expand Up @@ -1099,7 +1103,10 @@ static int do_gen_tokencode(struct openconnect_info *vpninfo,
case OC_TOKEN_MODE_HOTP:
return do_gen_hotp_code(vpninfo, form, opt);
#endif

#ifdef HAVE_LIBPCSCLITE
case OC_TOKEN_MODE_YUBIKEY:
return do_gen_yubikey_code(vpninfo, form, opt);
#endif
default:
return -EINVAL;
}
Expand Down
12 changes: 12 additions & 0 deletions configure.ac
Expand Up @@ -598,6 +598,18 @@ AS_IF([test "x$with_stoken" != "xno"], [
], [libstoken_pkg=disabled])
AM_CONDITIONAL(OPENCONNECT_STOKEN, [test "$libstoken_pkg" = "yes"])

AC_ARG_WITH([libpcsclite],
AS_HELP_STRING([--without-libpcsclite],
[Build without libpcsclite library (for Yubikey support) [default=auto]]))
AS_IF([test "x$with_libpcsclite" != "xno"], [
PKG_CHECK_MODULES(LIBPCSCLITE, libpcsclite,
[AC_SUBST(LIBPCSCLITE_PC, libpcsclite)
AC_DEFINE([HAVE_LIBPCSCLITE], 1, [Have libpcsclite])
libpcsclite_pkg=yes],
libpcsclite_pkg=no)
], [libpcsclite_pkg=disabled])
AM_CONDITIONAL(OPENCONNECT_LIBPCSCLITE, [test "$libpcsclite_pkg" = "yes"])

AC_ARG_WITH([liboath],
AS_HELP_STRING([--without-liboath],
[Build without liboath library [default=auto]]))
Expand Down
4 changes: 4 additions & 0 deletions library.c
Expand Up @@ -602,6 +602,10 @@ int openconnect_set_token_mode(struct openconnect_info *vpninfo,

case OC_TOKEN_MODE_HOTP:
return set_hotp_mode(vpninfo, token_str);
#endif
#ifdef HAVE_LIBPCSCLITE
case OC_TOKEN_MODE_YUBIKEY:
return set_yubikey_mode(vpninfo, token_str);
#endif
default:
return -EOPNOTSUPP;
Expand Down
17 changes: 17 additions & 0 deletions main.c
Expand Up @@ -1218,6 +1218,8 @@ int main(int argc, char **argv)
token_mode = OC_TOKEN_MODE_TOTP;
} else if (strcasecmp(config_arg, "hotp") == 0) {
token_mode = OC_TOKEN_MODE_HOTP;
} else if (strcasecmp(config_arg, "yubikey") == 0) {
token_mode = OC_TOKEN_MODE_YUBIKEY;
} else {
fprintf(stderr, _("Invalid software token mode \"%s\"\n"),
config_arg);
Expand Down Expand Up @@ -1900,6 +1902,21 @@ static void init_token(struct openconnect_info *vpninfo,

break;

case OC_TOKEN_MODE_YUBIKEY:
switch(ret) {
case 0:
return;
case -ENOENT:
fprintf(stderr, _("Yubikey token not found\n"));
exit(1);
case -EOPNOTSUPP:
fprintf(stderr, _("OpenConnect was not built with Yubikey support\n"));
exit(1);
default:
fprintf(stderr, _("General Yubikey failure: %s\n"), strerror(-ret));
exit(1);
}

case OC_TOKEN_MODE_NONE:
/* No-op */
break;
Expand Down
19 changes: 19 additions & 0 deletions openconnect-internal.h
Expand Up @@ -89,6 +89,11 @@
#include <pskc/pskc.h>
#endif

#ifdef HAVE_LIBPCSCLITE
#include <pcsclite.h>
#include <winscard.h>
#endif

#ifdef ENABLE_NLS
#include <libintl.h>
#define _(s) dgettext("openconnect", s)
Expand Down Expand Up @@ -277,6 +282,11 @@ struct openconnect_info {
HOTP_SECRET_HEX,
HOTP_SECRET_PSKC,
} hotp_secret_format; /* We need to give it back in the same form */
#endif
#ifdef HAVE_LIBPCSCLITE
SCARDHANDLE pcsc_ctx, pcsc_card;
char *yubikey_objname;
int yubikey_mode;
#endif
openconnect_lock_token_vfn lock_token;
openconnect_unlock_token_vfn unlock_token;
Expand Down Expand Up @@ -675,6 +685,15 @@ int do_gen_stoken_code(struct openconnect_info *vpninfo,
struct oc_auth_form *form,
struct oc_form_opt *opt);

/* yubikey.c */
int set_yubikey_mode(struct openconnect_info *vpninfo, const char *token_str);
int can_gen_yubikey_code(struct openconnect_info *vpninfo,
struct oc_auth_form *form,
struct oc_form_opt *opt);
int do_gen_yubikey_code(struct openconnect_info *vpninfo,
struct oc_auth_form *form,
struct oc_form_opt *opt);

/* auth.c */
void nuke_opt_values(struct oc_form_opt *opt);
int parse_xml_response(struct openconnect_info *vpninfo, char *response,
Expand Down
1 change: 1 addition & 0 deletions openconnect.h
Expand Up @@ -273,6 +273,7 @@ typedef enum {
OC_TOKEN_MODE_STOKEN,
OC_TOKEN_MODE_TOTP,
OC_TOKEN_MODE_HOTP,
OC_TOKEN_MODE_YUBIKEY,
} oc_token_mode_t;

/* All strings are UTF-8. If operating in a legacy environment where
Expand Down
2 changes: 1 addition & 1 deletion openconnect.pc.in
Expand Up @@ -7,7 +7,7 @@ includedir=@includedir@
Name: openconnect
Description: OpenConnect VPN client
Version: @VERSION@
Requires.private: @LIBPROXY_PC@ @ZLIB_PC@ @SSL_DTLS_PC@ @P11KIT_PC@ @LIBSTOKEN_PC@ @LIBOATH_PC@ @LIBPSKC_PC@ libxml-2.0
Requires.private: @LIBPROXY_PC@ @ZLIB_PC@ @SSL_DTLS_PC@ @P11KIT_PC@ @LIBSTOKEN_PC@ @LIBOATH_PC@ @LIBPSKC_PC@ @LIBPCSCLITE_PC@ libxml-2.0
Libs: -L${libdir} -lopenconnect
Libs.private: @INTL_LIBS@
Cflags: -I${includedir}
1 change: 1 addition & 0 deletions www/changelog.xml
Expand Up @@ -15,6 +15,7 @@
<ul>
<li><b>OpenConnect HEAD</b>
<ul>
<li>Add support for HOTP/TOTP keys from Yubikey NEO devices.</li>
<li>Add <tt>---no-system-trust</tt> option to disable default certificate authorities.</li>
<li>Improve <tt>libiconv</tt> and <tt>libintl</tt> detection.</li>
<li>Stop calling <tt>setenv()</tt> from library functions.</li>
Expand Down

0 comments on commit c24046b

Please sign in to comment.