library: Use named constants for process_auth_form() return value

Currently we have 3 valid results, and we're about to add a fourth.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
main: Rename process_auth_form() to avoid conflict with library

Since we're still including openconnect-internal.h in main.c, it isn't
possible to use function names that overlap with internal library
symbols.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
Create a common process_auth_form() wrapper function

This will be used to show/hide options based on the authgroup setting.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
auth: Remove outdated comment for parse_auth_choice()

We do offer <select> choices to the user (and have for some time).

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
auth: Introduce free_opt() helper function

This frees the name/label/value (as appropriate) and fixes a potential
leak in parse_auth_choice().

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
library: Change oc_form_opt_select->choices to a pointer array

This will allow the library to store internal data at the end of each
oc_choice struct, and potentially at the end of the oc_form_opt_select
struct as well.

This change breaks the public API.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
auth: Provide information on which auth choice is currently selected

In XML POST mode, the gateway keeps track of which authgroup is selected.
Provide this information to the UI so that the interface can be rendered
correctly.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
process_auth_form: Add code to support NEWGROUP return status from UI

In order to support refreshing the <opaque> data (XML POST) or the
secondary_* fields (non XML POST) on the auth form, it is necessary for
the process_auth_form() callback to return to libopenconnect to refresh
the form fields whenever the user changes the value of a <select>
dropdown.

This change should not break existing implementations.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
main: Extend read_stdin() to accept hidden (password) input

We can use read_stdin() for all of our prompts, instead of duplicating
the fgets()/strchr()/... logic everywhere user input is needed.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
main: Split process_auth_form_cb() into smaller functions

Implement helper functions for user prompts and consolidate some redundant
code.  This should not materially affect its behavior.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
main: Make the authgroup picker CLI more user-friendly

Perform case-insensitive partial matches where possible.  Allow the user
to retry if he makes a mistake.

Example usage:

    Connected to HTTPS on vpn.uci.edu
    Please enter your username and password.
    GROUP: [Default-WebVPN|Merage|MerageFull|UCI|UCIFull]:x
    Auth choice "x" not available
    GROUP: [Default-WebVPN|Merage|MerageFull|UCI|UCIFull]:mer
    Auth choice "mer" matches multiple options
    GROUP: [Default-WebVPN|Merage|MerageFull|UCI|UCIFull]:meragex
    Auth choice "meragex" not available
    GROUP: [Default-WebVPN|Merage|MerageFull|UCI|UCIFull]:merage
    Username:fred
    [...]

The same logic also applies to the --authgroup switch.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
auth: Parse second-auth-related properties from the auth form

Add new fields/flags to the oc_form_opt and oc_choice structs.

Note that it isn't possible to add private fields at the end of
oc_form_opt, because the layout of oc_form_opt_select depends on the
length of oc_form_opt.  So we will add a publicly visible flags
field (which also supports internal flags) and reserve space for future
expansion.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
auth: Hide unused form fields based on the selected authgroup

Non-aggregate-auth servers have limited support for customizing the login
form based on which authgroup is currently selected.  Flag the appropriate
fields as OC_FORM_OPT_IGNORE based on these attributes:

  <input second-auth="1"> (for text/password fields)

  <option                 (for authgroup options)
          second-auth="1"
          secondary_username="foo"
          secondary_username_editable="true"
          noaaa="1" >

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
Revert "auth: Temporarily disable XML POST if an authgroup dropdown exists"

This reverts commit f2774911bc2d94e3130a4a10079c5cb56e57a2b2.

Now that the new library API allows callers to change the authgroup via
NEWGROUP, we no longer need this workaround.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
auth: Add OC_FORM_OPT_NUMERIC hint and apply it to token PIN entry

Tell the UI if an auth form field expects numeric input only.  This allows
mobile platforms to pop up a numeric keypad or disable T9/ITU-T text
entry.

This has only been tested with token PIN entry, but it may also be useful
for unlocking password or PIN protected certs.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
library: Bump API version to 3.0 and document changes

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
main: Update CLI to handle hidden fields and NEWGROUP

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
main: Avoid infinite "303 See Other" loops on certificate-only authgroups

Since we are now caching the authgroup selection, it is possible to
receive a form from the server that skips all user prompts.  If the
selected authgroup is set up for certificate auth only (no l/p) and the
client certificate is not valid, the server will render a new form which
shows only the authgroup dropdown.  Since our CLI caches this response,
we need to make sure it doesn't keep resubmitting the same response over
and over again.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
main: Don't free password if it isn't used in the first auth form

The gateway might not request the password until a subsequent auth form.
For instance, ocserv with plain password authentication sends one form
requesting just a username, and then a second form for the password.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
library: Clean up partially completed auth forms on error

We already have code in the library to nuke any opt->value strings set
by the callback, so this is cleaner than having to repeat the same code
in every openconnect frontend.

(Note that http.c already calls free_auth_form() on error, but the SSL
passphrase/PIN prompts generally do not.)

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>