resetting manifest requested domain to floor
[platform/upstream/openconnect.git] / library.c
index 7eec6b5..73e7c54 100644 (file)
--- a/library.c
+++ b/library.c
@@ -1,7 +1,7 @@
 /*
  * OpenConnect (SSL + DTLS) VPN client
  *
- * Copyright © 2008-2011 Intel Corporation.
+ * Copyright © 2008-2012 Intel Corporation.
  *
  * Authors: David Woodhouse <dwmw2@infradead.org>
  *
  */
 
 #include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#ifdef LIBSTOKEN_HDR
+#include LIBSTOKEN_HDR
+#endif
+
+#include <libxml/tree.h>
 
 #include "openconnect-internal.h"
 
-struct openconnect_info *openconnect_vpninfo_new_with_cbdata (char *useragent,
+struct openconnect_info *openconnect_vpninfo_new (char *useragent,
                                                  openconnect_validate_peer_cert_vfn validate_peer_cert,
                                                  openconnect_write_new_config_vfn write_new_config,
                                                  openconnect_process_auth_form_vfn process_auth_form,
@@ -35,7 +43,6 @@ struct openconnect_info *openconnect_vpninfo_new_with_cbdata (char *useragent,
 {
        struct openconnect_info *vpninfo = calloc (sizeof(*vpninfo), 1);
 
-       vpninfo->mtu = 1406;
        vpninfo->ssl_fd = -1;
        vpninfo->cert_expire_warning = 60 * 86400;
        vpninfo->useragent = openconnect_create_useragent (useragent);
@@ -44,6 +51,8 @@ struct openconnect_info *openconnect_vpninfo_new_with_cbdata (char *useragent,
        vpninfo->process_auth_form = process_auth_form;
        vpninfo->progress = progress;
        vpninfo->cbdata = privdata?:vpninfo;
+       vpninfo->cancel_fd = -1;
+       openconnect_set_reported_os(vpninfo, NULL);
 
 #ifdef ENABLE_NLS
        bindtextdomain("openconnect", LOCALEDIR);
@@ -52,17 +61,28 @@ struct openconnect_info *openconnect_vpninfo_new_with_cbdata (char *useragent,
        return vpninfo;
 }
 
-struct openconnect_info *openconnect_vpninfo_new (char *useragent,
-                                                 openconnect_validate_peer_cert_fn validate_peer_cert,
-                                                 openconnect_write_new_config_fn write_new_config,
-                                                 openconnect_process_auth_form_fn process_auth_form,
-                                                 openconnect_progress_fn progress)
+int openconnect_set_reported_os (struct openconnect_info *vpninfo, const char *os)
 {
-       return openconnect_vpninfo_new_with_cbdata (useragent,
-                                                   (void *)validate_peer_cert,
-                                                   (void *)write_new_config,
-                                                   (void *)process_auth_form,
-                                                   (void *)progress, NULL);
+       if (!os) {
+#if defined(__APPLE__)
+               os = "mac";
+#else
+               os = sizeof(long) > 4 ? "linux-64" : "linux";
+#endif
+       }
+
+       /* FIXME: is there a special platname for 64-bit Windows? */
+       if (!strcmp(os, "mac"))
+               vpninfo->csd_xmltag = "csdMac";
+       else if (!strcmp(os, "linux") || !strcmp(os, "linux-64"))
+               vpninfo->csd_xmltag = "csdLinux";
+       else if (!strcmp(os, "win"))
+               vpninfo->csd_xmltag = "csd";
+       else
+               return -EINVAL;
+
+       vpninfo->platname = os;
+       return 0;
 }
 
 static void free_optlist (struct vpn_option *opt)
@@ -79,7 +99,8 @@ static void free_optlist (struct vpn_option *opt)
 
 void openconnect_vpninfo_free (struct openconnect_info *vpninfo)
 {
-       openconnect_reset_ssl(vpninfo);
+       openconnect_close_https(vpninfo, 1);
+       free(vpninfo->peer_addr);
        free_optlist(vpninfo->cookies);
        free_optlist(vpninfo->cstp_options);
        free_optlist(vpninfo->dtls_options);
@@ -88,8 +109,20 @@ void openconnect_vpninfo_free (struct openconnect_info *vpninfo)
        free(vpninfo->redirect_url);
        free(vpninfo->proxy_type);
        free(vpninfo->proxy);
-       free(vpninfo->csd_scriptname);
+
+       if (vpninfo->csd_scriptname) {
+               unlink(vpninfo->csd_scriptname);
+               free(vpninfo->csd_scriptname);
+       }
+       free(vpninfo->csd_token);
+       free(vpninfo->csd_ticket);
        free(vpninfo->csd_stuburl);
+       free(vpninfo->csd_starturl);
+       free(vpninfo->csd_waiturl);
+       free(vpninfo->csd_preurl);
+       if (vpninfo->opaque_srvdata)
+               xmlFreeNode(vpninfo->opaque_srvdata);
+
        /* These are const in openconnect itself, but for consistency of
           the library API we do take ownership of the strings we're given,
           and thus we have to free them too. */
@@ -97,6 +130,21 @@ void openconnect_vpninfo_free (struct openconnect_info *vpninfo)
        if (vpninfo->cert != vpninfo->sslkey)
                free((void *)vpninfo->sslkey);
        free((void *)vpninfo->cert);
+       if (vpninfo->peer_cert) {
+#if defined (OPENCONNECT_OPENSSL)
+               X509_free(vpninfo->peer_cert);
+#elif defined (OPENCONNECT_GNUTLS)
+               gnutls_x509_crt_deinit(vpninfo->peer_cert);
+#endif
+               vpninfo->peer_cert = NULL;
+       }
+       free(vpninfo->useragent);
+#ifdef LIBSTOKEN_HDR
+       if (vpninfo->stoken_pin)
+               free(vpninfo->stoken_pin);
+       if (vpninfo->stoken_ctx)
+               stoken_destroy(vpninfo->stoken_ctx);
+#endif
        /* No need to free deflate streams; they weren't initialised */
        free(vpninfo);
 }
@@ -121,7 +169,7 @@ void openconnect_set_urlpath (struct openconnect_info *vpninfo, char *urlpath)
        vpninfo->urlpath = urlpath;
 }
 
-void openconnect_set_xmlsha1 (struct openconnect_info *vpninfo, char *xmlsha1, int size)
+void openconnect_set_xmlsha1 (struct openconnect_info *vpninfo, const char *xmlsha1, int size)
 {
        if (size != sizeof (vpninfo->xmlsha1))
                return;
@@ -150,9 +198,9 @@ void openconnect_set_client_cert (struct openconnect_info *vpninfo, char *cert,
                vpninfo->sslkey = cert;
 }
 
-struct x509_st *openconnect_get_peer_cert (struct openconnect_info *vpninfo)
+OPENCONNECT_X509 *openconnect_get_peer_cert (struct openconnect_info *vpninfo)
 {
-       return SSL_get_peer_certificate(vpninfo->https_ssl);
+       return vpninfo->peer_cert;
 }
 
 int openconnect_get_port (struct openconnect_info *vpninfo)
@@ -173,28 +221,44 @@ void openconnect_clear_cookie (struct openconnect_info *vpninfo)
 
 void openconnect_reset_ssl (struct openconnect_info *vpninfo)
 {
-       if (vpninfo->https_ssl) {
-               openconnect_close_https(vpninfo);
-       }
+       openconnect_close_https(vpninfo, 0);
        if (vpninfo->peer_addr) {
                free(vpninfo->peer_addr);
                vpninfo->peer_addr = NULL;
        }
-       if (vpninfo->https_ctx) {
-               SSL_CTX_free(vpninfo->https_ctx);
-               vpninfo->https_ctx = NULL;
-       }
 }
 
 int openconnect_parse_url (struct openconnect_info *vpninfo, char *url)
 {
+       char *scheme = NULL;
+       int ret;
+
        if (vpninfo->peer_addr) {
                free(vpninfo->peer_addr);
                vpninfo->peer_addr = NULL;
        }
 
-       return internal_parse_url (url, NULL, &vpninfo->hostname,
-                                  &vpninfo->port, &vpninfo->urlpath, 443);
+       free(vpninfo->hostname);
+       vpninfo->hostname = NULL;
+       free(vpninfo->urlpath);
+       vpninfo->urlpath = NULL;
+
+       ret = internal_parse_url (url, &scheme, &vpninfo->hostname,
+                                 &vpninfo->port, &vpninfo->urlpath, 443);
+
+       if (ret) {
+               vpn_progress(vpninfo, PRG_ERR,
+                            _("Failed to parse server URL '%s'\n"),
+                            url);
+               return ret;
+       }
+       if (scheme && strcmp(scheme, "https")) {
+               vpn_progress(vpninfo, PRG_ERR,
+                            _("Only https:// permitted for server URL\n"));
+               ret = -EINVAL;
+       }
+       free(scheme);
+       return ret;
 }
 
 void openconnect_set_cert_expiry_warning (struct openconnect_info *vpninfo,
@@ -203,7 +267,93 @@ void openconnect_set_cert_expiry_warning (struct openconnect_info *vpninfo,
        vpninfo->cert_expire_warning = seconds;
 }
 
+void openconnect_set_cancel_fd (struct openconnect_info *vpninfo, int fd)
+{
+       vpninfo->cancel_fd = fd;
+}
+
 const char *openconnect_get_version (void)
 {
-       return openconnect_version;
+       return openconnect_version_str;
+}
+
+int openconnect_has_pkcs11_support(void)
+{
+#if defined (OPENCONNECT_GNUTLS) && defined (HAVE_P11KIT)
+       return 1;
+#else
+       return 0;
+#endif
+}
+
+#if defined (OPENCONNECT_OPENSSL) && defined (HAVE_ENGINE)
+#include <openssl/engine.h>
+#endif
+int openconnect_has_tss_blob_support(void)
+{
+#if defined (OPENCONNECT_OPENSSL) && defined (HAVE_ENGINE)
+       ENGINE *e;
+
+       ENGINE_load_builtin_engines();
+
+       e = ENGINE_by_id("tpm");
+       if (e) {
+               ENGINE_free(e);
+               return 1;
+       }
+#elif defined (OPENCONNECT_GNUTLS) && defined (HAVE_TROUSERS)
+       return 1;
+#endif
+       return 0;
+}
+
+int openconnect_has_stoken_support(void)
+{
+#ifdef LIBSTOKEN_HDR
+       return 1;
+#else
+       return 0;
+#endif
+}
+
+/*
+ * Enable software token generation if use_stoken == 1.
+ *
+ * If token_str is not NULL, try to parse the string.  Otherwise, try to read
+ * the token data from ~/.stokenrc
+ *
+ * Return value:
+ *  = -EOPNOTSUPP, if libstoken is not available
+ *  = -EINVAL, if the token string is invalid (token_str was provided)
+ *  = -ENOENT, if ~/.stokenrc is missing (token_str was NULL)
+ *  = -EIO, for other libstoken failures
+ *  = 0, on success
+ */
+int openconnect_set_stoken_mode (struct openconnect_info *vpninfo,
+                                int use_stoken, const char *token_str)
+{
+#ifdef LIBSTOKEN_HDR
+       int ret;
+
+       vpninfo->use_stoken = 0;
+       if (!use_stoken)
+               return 0;
+
+       if (!vpninfo->stoken_ctx) {
+               vpninfo->stoken_ctx = stoken_new();
+               if (!vpninfo->stoken_ctx)
+                       return -EIO;
+       }
+
+       ret = token_str ?
+             stoken_import_string(vpninfo->stoken_ctx, token_str) :
+             stoken_import_rcfile(vpninfo->stoken_ctx, NULL);
+       if (ret)
+               return ret;
+
+       vpninfo->use_stoken = 1;
+       return 0;
+#else
+       return -EOPNOTSUPP;
+#endif
 }