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>
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>
Unconditionally redirect CSD stdout to stderr

CSD output breaks --cookieonly, so let's make a rule that
openconnect_obtain_cookie() will never print to stdout.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
ssl: Set FD_CLOEXEC on all sockets

It was recently discovered that open CSTP sockets were being inherited
by the tunnel script.  Use FD_CLOEXEC so this no longer happens.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
gnutls: Remove unused local variable

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
Introduce new helper functions for cancel_fd checking

The same code shows up in 12 places, so we'll move it into a common
location.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
library: Rename cancel_fd to cmd_fd

Applications which use libopenconnect may need to interrupt the mainloop
for a couple of reasons:

 - Cancel/disconnect
 - Force reconnect: in case the IP configuration changed
 - Retrieving bytecounts or other internal information

The cancel_fd mechanism provides a convenient way to send these commands,
but first we need to make it more generic (while preserving backward
compatibility).

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
library: Add new openconnect_setup_cmd_pipe() call

Most callers will use a simple nonblocking UNIX pipe as their cmd_fd,
so provide a convenience function for creating it.  Also, libopenconnect
will take care of cleaning up pipes created in this manner when the
library instance is freed.

Pipes created through this function will be able to send new commands,
such as "reconnect".  Pipes passed in via openconnect_set_cancel_fd()
can only be used to cancel the connection, for backward compatibility.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
Add new helper functions to support cmd_fd feature

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
Temporarily build ssl.c + deps into the main executable

This lets us access the cmd_fd helper functions from the mainloop without
breaking the build.  This change will be reverted when the mainloop is
moved into libopenconnect.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
Move signal handling out of mainloop

In order to make the mainloop a reusable library function, it should not
take over any POSIX signals.  Handle the signals in main.c instead, and
use the cmd_fd mechanism to tell the mainloop to exit.

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