diff --git a/auth-common.c b/auth-common.c index 4239152e..6a582680 100644 --- a/auth-common.c +++ b/auth-common.c @@ -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; + } +} diff --git a/auth.c b/auth.c index 88358036..3db82db0 100644 --- a/auth.c +++ b/auth.c @@ -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) { @@ -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; @@ -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) @@ -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) diff --git a/oncp.c b/oncp.c index 6db289d7..ea68c348 100644 --- a/oncp.c +++ b/oncp.c @@ -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) { @@ -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); @@ -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); diff --git a/openconnect-internal.h b/openconnect-internal.h index 5aa1293b..0716dd06 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -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);