Skip to content

Commit

Permalink
Allow automatic OATH for Juniper
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 Jan 30, 2015
1 parent bf937a6 commit 50b6c52
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 59 deletions.
63 changes: 63 additions & 0 deletions auth-common.c
Expand Up @@ -133,3 +133,66 @@ void free_auth_form(struct oc_auth_form *form)
free(form->action);
free(form);
}

/* Return value:
* < 0, if unable to generate a tokencode
* = 0, on success
*/
int do_gen_tokencode(struct openconnect_info *vpninfo,
struct oc_auth_form *form)
{
struct oc_form_opt *opt;

for (opt = form->opts; ; opt = opt->next) {
/* this form might not have anything for us to do */
if (!opt)
return 0;
if (opt->type == OC_FORM_OPT_TOKEN)
break;
}

switch (vpninfo->token_mode) {
#ifdef HAVE_LIBSTOKEN
case OC_TOKEN_MODE_STOKEN:
return do_gen_stoken_code(vpninfo, form, opt);
#endif
#ifdef HAVE_LIBOATH
case OC_TOKEN_MODE_TOTP:
return do_gen_totp_code(vpninfo, form, opt);

case OC_TOKEN_MODE_HOTP:
return do_gen_hotp_code(vpninfo, form, opt);
#endif
#ifdef HAVE_LIBPCSCLITE
case OC_TOKEN_MODE_YUBIOATH:
return do_gen_yubikey_code(vpninfo, form, opt);
#endif
default:
return -EINVAL;
}
}

int can_gen_tokencode(struct openconnect_info *vpninfo,
struct oc_auth_form *form,
struct oc_form_opt *opt)
{
switch (vpninfo->token_mode) {
#ifdef HAVE_LIBSTOKEN
case OC_TOKEN_MODE_STOKEN:
return can_gen_stoken_code(vpninfo, form, opt);
#endif
#ifdef HAVE_LIBOATH
case OC_TOKEN_MODE_TOTP:
return can_gen_totp_code(vpninfo, form, opt);

case OC_TOKEN_MODE_HOTP:
return can_gen_hotp_code(vpninfo, form, opt);
#endif
#ifdef HAVE_LIBPCSCLITE
case OC_TOKEN_MODE_YUBIOATH:
return can_gen_yubikey_code(vpninfo, form, opt);
#endif
default:
return -EINVAL;
}
}
67 changes: 8 additions & 59 deletions auth.c
Expand Up @@ -42,9 +42,9 @@

static int xmlpost_append_form_opts(struct openconnect_info *vpninfo,
struct oc_auth_form *form, struct oc_text_buf *body);
static int can_gen_tokencode(struct openconnect_info *vpninfo,
struct oc_auth_form *form, struct oc_form_opt *opt);
static int do_gen_tokencode(struct openconnect_info *vpninfo, struct oc_auth_form *form);
static int cstp_can_gen_tokencode(struct openconnect_info *vpninfo,
struct oc_auth_form *form,
struct oc_form_opt *opt);

int openconnect_set_option_value(struct oc_form_opt *opt, const char *value)
{
Expand Down Expand Up @@ -223,7 +223,7 @@ static int parse_form(struct openconnect_info *vpninfo, struct oc_auth_form *for
} else if (!strcmp(input_type, "text")) {
opt->type = OC_FORM_OPT_TEXT;
} else if (!strcmp(input_type, "password")) {
if (!can_gen_tokencode(vpninfo, form, opt))
if (!cstp_can_gen_tokencode(vpninfo, form, opt))
opt->type = OC_FORM_OPT_TOKEN;
else
opt->type = OC_FORM_OPT_PASSWORD;
Expand Down Expand Up @@ -873,9 +873,9 @@ static int xmlpost_append_form_opts(struct openconnect_info *vpninfo,
* < 0, if unable to generate a tokencode
* = 0, on success
*/
static int can_gen_tokencode(struct openconnect_info *vpninfo,
struct oc_auth_form *form,
struct oc_form_opt *opt)
static int cstp_can_gen_tokencode(struct openconnect_info *vpninfo,
struct oc_auth_form *form,
struct oc_form_opt *opt)
{
if (vpninfo->token_mode == OC_TOKEN_MODE_NONE ||
vpninfo->token_bypassed)
Expand All @@ -892,59 +892,8 @@ static int can_gen_tokencode(struct openconnect_info *vpninfo,
/* Otherwise it's an OATH token of some kind. */
if (strcmp(opt->name, "secondary_password"))
return -EINVAL;
switch (vpninfo->token_mode) {
#ifdef HAVE_LIBOATH
case OC_TOKEN_MODE_TOTP:
return can_gen_totp_code(vpninfo, form, opt);

case OC_TOKEN_MODE_HOTP:
return can_gen_hotp_code(vpninfo, form, opt);
#endif
#ifdef HAVE_LIBPCSCLITE
case OC_TOKEN_MODE_YUBIOATH:
return can_gen_yubikey_code(vpninfo, form, opt);
#endif
default:
return -EINVAL;
}
}

/* Return value:
* < 0, if unable to generate a tokencode
* = 0, on success
*/
static int do_gen_tokencode(struct openconnect_info *vpninfo,
struct oc_auth_form *form)
{
struct oc_form_opt *opt;

for (opt = form->opts; ; opt = opt->next) {
/* this form might not have anything for us to do */
if (!opt)
return 0;
if (opt->type == OC_FORM_OPT_TOKEN)
break;
}

switch (vpninfo->token_mode) {
#ifdef HAVE_LIBSTOKEN
case OC_TOKEN_MODE_STOKEN:
return do_gen_stoken_code(vpninfo, form, opt);
#endif
#ifdef HAVE_LIBOATH
case OC_TOKEN_MODE_TOTP:
return do_gen_totp_code(vpninfo, form, opt);

case OC_TOKEN_MODE_HOTP:
return do_gen_hotp_code(vpninfo, form, opt);
#endif
#ifdef HAVE_LIBPCSCLITE
case OC_TOKEN_MODE_YUBIOATH:
return do_gen_yubikey_code(vpninfo, form, opt);
#endif
default:
return -EINVAL;
}
return can_gen_tokencode(vpninfo, form, opt);
}

static int fetch_config(struct openconnect_info *vpninfo)
Expand Down
38 changes: 38 additions & 0 deletions oncp.c
Expand Up @@ -66,6 +66,35 @@ static xmlNodePtr htmlnode_next(xmlNodePtr top, xmlNodePtr node)
return node->next;
}

static int oncp_can_gen_tokencode(struct openconnect_info *vpninfo,
struct oc_auth_form *form,
struct oc_form_opt *opt)
{
if (vpninfo->token_mode == OC_TOKEN_MODE_NONE ||
vpninfo->token_bypassed)
return -EINVAL;
if (strcmp(form->auth_id, "frmDefender") &&
strcmp(form->auth_id, "frmNextToken"))
return -EINVAL;

switch (vpninfo->token_mode) {
#ifdef HAVE_LIBOATH
case OC_TOKEN_MODE_TOTP:
return can_gen_totp_code(vpninfo, form, opt);

case OC_TOKEN_MODE_HOTP:
return can_gen_hotp_code(vpninfo, form, opt);
#endif
#ifdef HAVE_LIBPCSCLITE
case OC_TOKEN_MODE_YUBIOATH:
return can_gen_yubikey_code(vpninfo, form, opt);
#endif
default:
return -EINVAL;
}
}


static int parse_input_node(struct openconnect_info *vpninfo, struct oc_auth_form *form,
xmlNodePtr node, const char *submit_button)
{
Expand All @@ -89,6 +118,8 @@ static int parse_input_node(struct openconnect_info *vpninfo, struct oc_auth_for
opt->type = OC_FORM_OPT_PASSWORD;
xmlnode_get_prop(node, "name", &opt->name);
asprintf(&opt->label, "%s:", opt->name);
if (!oncp_can_gen_tokencode(vpninfo, form, opt))
opt->type = OC_FORM_OPT_TOKEN;
} else if (!strcasecmp(type, "text")) {
opt->type = OC_FORM_OPT_TEXT;
xmlnode_get_prop(node, "name", &opt->name);
Expand Down Expand Up @@ -508,6 +539,13 @@ int oncp_obtain_cookie(struct openconnect_info *vpninfo)
if (ret)
goto out;

ret = do_gen_tokencode(vpninfo, form);
if (ret) {
vpn_progress(vpninfo, PRG_ERR, _("Failed to generate OTP tokencode; disabling token\n"));
vpninfo->token_bypassed = 1;
goto out;
}

form_done:
append_form_opts(vpninfo, form, resp_buf);
ret = buf_error(resp_buf);
Expand Down
5 changes: 5 additions & 0 deletions openconnect-internal.h
Expand Up @@ -896,6 +896,11 @@ int append_form_opts(struct openconnect_info *vpninfo,
struct oc_auth_form *form, struct oc_text_buf *body);
void free_opt(struct oc_form_opt *opt);
void free_auth_form(struct oc_auth_form *form);
int do_gen_tokencode(struct openconnect_info *vpninfo,
struct oc_auth_form *form);
int can_gen_tokencode(struct openconnect_info *vpninfo,
struct oc_auth_form *form,
struct oc_form_opt *opt);

/* http.c */
struct oc_text_buf *buf_alloc(void);
Expand Down

0 comments on commit 50b6c52

Please sign in to comment.