From 8199354dfe763b39489f6a4e8e2728dce37112f8 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 12 Aug 2014 13:36:46 +0100 Subject: [PATCH] Add openconnect_set_token_callbacks() API This allows the application to lock the file (or other) storage when a token is about to be generated, then to unlock it and write the new counter back to the file when we're done. This gives us a clean way to use HOTP tokens safely. Signed-off-by: David Woodhouse --- libopenconnect.map.in | 5 +++++ library.c | 12 ++++++++++++ openconnect-internal.h | 3 +++ openconnect.h | 27 ++++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/libopenconnect.map.in b/libopenconnect.map.in index 526980e2..083c2ae9 100644 --- a/libopenconnect.map.in +++ b/libopenconnect.map.in @@ -61,6 +61,11 @@ OPENCONNECT_3.3 { openconnect_set_proxy_auth; } OPENCONNECT_3.1; +OPENCONNECT_3.4 { + global: + openconnect_set_token_callbacks; +} OPENCONNECT_3.3; + OPENCONNECT_PRIVATE { global: @SYMVER_TIME@ @SYMVER_GETLINE@ @SYMVER_JAVA@ @SYMVER_ASPRINTF@ @SYMVER_VASPRINTF@ openconnect_version_str; diff --git a/library.c b/library.c index d3964fd4..edc09f3a 100644 --- a/library.c +++ b/library.c @@ -665,6 +665,18 @@ static int set_hotp_mode(struct openconnect_info *vpninfo, #endif } +int openconnect_set_token_callbacks(struct openconnect_info *vpninfo, + void *tokdata, + openconnect_lock_token_vfn lock, + openconnect_unlock_token_vfn unlock) +{ + vpninfo->lock_token = lock; + vpninfo->unlock_token = unlock; + vpninfo->tok_cbdata = tokdata; + + return 0; +} + /* * Enable software token generation. * diff --git a/openconnect-internal.h b/openconnect-internal.h index 02377c56..75a8ce78 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -275,6 +275,9 @@ struct openconnect_info { HOTP_SECRET_PSKC, } hotp_secret_format; /* We need to give it back in the same form */ #endif + openconnect_lock_token_vfn lock_token; + openconnect_unlock_token_vfn unlock_token; + void *tok_cbdata; OPENCONNECT_X509 *peer_cert; diff --git a/openconnect.h b/openconnect.h index 91d3b695..ea0e0094 100644 --- a/openconnect.h +++ b/openconnect.h @@ -29,9 +29,12 @@ #endif #define OPENCONNECT_API_VERSION_MAJOR 3 -#define OPENCONNECT_API_VERSION_MINOR 3 +#define OPENCONNECT_API_VERSION_MINOR 4 /* + * API version 3.4: + * - Add openconnect_set_token_callbacks() + * * API version 3.3: * - Add openconnect_set_pfs(), openconnect_set_dpd(), * openconnect_set_proxy_auth() @@ -293,6 +296,28 @@ void openconnect_set_hostname(struct openconnect_info *, char *); char *openconnect_get_urlpath(struct openconnect_info *); void openconnect_set_urlpath(struct openconnect_info *, char *); +/* Some software tokens, such as HOTP tokens, include a counter which + * needs to be stored in persistent storage. + * + * For such tokens, the lock function is first invoked to obtain a lock + * on the storage because we're about to generate a new code. It is + * permitted to call openconnect_set_token_mode() from the lock function, + * if the token storage has been updated since it was first loaded. The + * token mode must not change; only the token secret. + * + * The unlock function is called when a token code has been generated, + * with a new token secret to be written to the persistent storage. The + * secret will be in the same format as it was originally received by + * openconnect_set_token_mode(). The new token may be NULL if an error + * was encountered generating the code, in which case it is only + * necessary for the callback function to unlock the storage. + */ +typedef int (*openconnect_lock_token_vfn)(void *tokdata); +typedef int (*openconnect_unlock_token_vfn)(void *tokdata, const char *new_tok); +int openconnect_set_token_callbacks(struct openconnect_info *, void *tokdata, + openconnect_lock_token_vfn, + openconnect_unlock_token_vfn); + /* These functions do *not* take ownership of the string; it is parsed and then discarded. */ int openconnect_set_token_mode(struct openconnect_info *,