Imported Upstream version 1.38
[platform/upstream/connman.git] / vpn / vpn-agent.c
index b0b582b..ab6fea5 100644 (file)
@@ -3,6 +3,7 @@
  *  Connection Manager
  *
  *  Copyright (C) 2012  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2019  Jolla Ltd. All rights reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -30,6 +31,8 @@
 #include <gdbus.h>
 #include <connman/log.h>
 #include <connman/agent.h>
+#include <connman/vpn-dbus.h>
+#include <connman/task.h>
 #include <vpn/vpn-provider.h>
 
 #include "vpn-agent.h"
@@ -102,6 +105,7 @@ void vpn_agent_append_host_and_name(DBusMessageIter *iter,
 struct user_info_data {
        struct vpn_provider *provider;
        const char *username_str;
+       const char *type_str;
 };
 
 static void request_input_append_user_info(DBusMessageIter *iter,
@@ -109,10 +113,10 @@ static void request_input_append_user_info(DBusMessageIter *iter,
 {
        struct user_info_data *data = user_data;
        struct vpn_provider *provider = data->provider;
-       const char *str = "string";
+       const char *str = NULL;
 
        connman_dbus_dict_append_basic(iter, "Type",
-                               DBUS_TYPE_STRING, &str);
+                               DBUS_TYPE_STRING, &data->type_str);
        str = "mandatory";
        connman_dbus_dict_append_basic(iter, "Requirement",
                                DBUS_TYPE_STRING, &str);
@@ -134,12 +138,150 @@ void vpn_agent_append_user_info(DBusMessageIter *iter,
                .username_str = username_str
        };
 
+       data.type_str = "string";
        connman_dbus_dict_append_dict(iter, "Username",
                                request_input_append_user_info,
                                &data);
 
        data.username_str = NULL;
+       data.type_str = "password";
        connman_dbus_dict_append_dict(iter, "Password",
                                request_input_append_user_info,
                                &data);
 }
+
+static void request_input_append_flag(DBusMessageIter *iter,
+                                               void *user_data)
+{
+       dbus_bool_t data = (dbus_bool_t)GPOINTER_TO_INT(user_data);
+       const char *str = NULL;
+
+       str = "boolean";
+       connman_dbus_dict_append_basic(iter, "Type",
+                               DBUS_TYPE_STRING, &str);
+
+       str = "control";
+       connman_dbus_dict_append_basic(iter, "Requirement",
+                               DBUS_TYPE_STRING, &str);
+
+       connman_dbus_dict_append_basic(iter, "Value",
+                               DBUS_TYPE_BOOLEAN, &data);
+}
+
+void vpn_agent_append_allow_credential_storage(DBusMessageIter *iter,
+                               bool allow)
+{
+       connman_dbus_dict_append_dict(iter, "AllowStoreCredentials",
+                               request_input_append_flag,
+                               GINT_TO_POINTER(allow));
+}
+
+void vpn_agent_append_allow_credential_retrieval(DBusMessageIter *iter,
+                               bool allow)
+{
+       connman_dbus_dict_append_dict(iter, "AllowRetrieveCredentials",
+                               request_input_append_flag,
+                               GINT_TO_POINTER(allow));
+}
+
+void vpn_agent_append_keep_credentials(DBusMessageIter *iter, bool allow)
+{
+       connman_dbus_dict_append_dict(iter, "KeepCredentials",
+                               request_input_append_flag,
+                               GINT_TO_POINTER(allow));
+}
+
+struct failure_data {
+       struct vpn_provider *provider;
+       const char* type_str;
+       const char *key;
+       const char* str;
+};
+
+static void request_input_append_failure(DBusMessageIter *iter,
+                                               void *user_data)
+{
+       struct failure_data *data;
+       const char *str;
+
+       data = user_data;
+
+       connman_dbus_dict_append_basic(iter, "Type",
+                               DBUS_TYPE_STRING, &data->type_str);
+       str = "informational";
+       connman_dbus_dict_append_basic(iter, "Requirement",
+                               DBUS_TYPE_STRING, &str);
+
+       str = data->str;
+
+       /* Try to get information from provider about error */
+       if (!str)
+               str = vpn_provider_get_string(data->provider, data->key);
+
+       if (str)
+               connman_dbus_dict_append_basic(iter, "Value",
+                                               DBUS_TYPE_STRING, &str);
+}
+
+void vpn_agent_append_auth_failure(DBusMessageIter *iter,
+                               struct vpn_provider *provider,
+                               const char* information)
+{
+       struct failure_data data;
+       unsigned int value;
+
+       /* Skip if there are no auth errors */
+       value = vpn_provider_get_authentication_errors(provider);
+       if (!value)
+               return;
+
+       data.provider = provider;
+       data.type_str = "string";
+       data.key = "VpnAgent.AuthFailure";
+       data.str = information;
+
+       connman_dbus_dict_append_dict(iter, data.key,
+                               request_input_append_failure, &data);
+}
+
+int vpn_agent_check_and_process_reply_error(DBusMessage *reply,
+                               struct vpn_provider *provider,
+                               struct connman_task *task,
+                               vpn_provider_connect_cb_t cb, void *user_data)
+{
+       DBusError error;
+       int err;
+
+       if (!reply || !provider)
+               return EINVAL;
+
+       dbus_error_init(&error);
+
+       if (!dbus_set_error_from_message(&error, reply))
+               return 0;
+
+       if (!g_strcmp0(error.name, VPN_AGENT_INTERFACE ".Error.Canceled"))
+               err = ECANCELED;
+       else if (!g_strcmp0(error.name, "org.freedesktop.DBus.Error.Timeout"))
+               err = ETIMEDOUT;
+       else if (!g_strcmp0(error.name, "org.freedesktop.DBus.Error.NoReply"))
+               err = ENOMSG;
+       else
+               err = EACCES;
+
+       dbus_error_free(&error);
+
+       if (cb)
+               cb(provider, user_data, err);
+
+       if (task)
+               connman_task_stop(task);
+
+       /*
+        * VPN agent dialog cancel, timeout, broken connection should set the
+        * VPN back to idle state
+        */
+       vpn_provider_set_state(provider, VPN_PROVIDER_STATE_IDLE);
+
+       return err;
+}