agent: Verify that the reply contains a dictionary
[framework/connectivity/connman.git] / src / agent.c
index b87f4e8..ebee19c 100644 (file)
@@ -2,7 +2,7 @@
  *
  *  Connection Manager
  *
- *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2007-2012  Intel Corporation. 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
@@ -85,6 +85,26 @@ int __connman_agent_unregister(const char *sender, const char *path)
        return 0;
 }
 
+static connman_bool_t check_reply_has_dict(DBusMessage *reply)
+{
+       const char *signature = DBUS_TYPE_ARRAY_AS_STRING
+               DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+               DBUS_TYPE_STRING_AS_STRING
+               DBUS_TYPE_VARIANT_AS_STRING
+               DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
+
+       if (dbus_message_has_signature(reply, signature) == TRUE)
+               return TRUE;
+
+       connman_warn("Reply %s to %s from %s has wrong signature %s",
+                       signature,
+                       dbus_message_get_interface(reply),
+                       dbus_message_get_sender(reply),
+                       dbus_message_get_signature(reply));
+
+       return FALSE;
+}
+
 struct request_input_reply {
        struct connman_service *service;
        authentication_cb_t callback;
@@ -96,6 +116,7 @@ static void request_input_passphrase_reply(DBusPendingCall *call, void *user_dat
        struct request_input_reply *passphrase_reply = user_data;
        connman_bool_t values_received = FALSE;
        connman_bool_t wps = FALSE;
+       const char *error = NULL;
        char *identity = NULL;
        char *passphrase = NULL;
        char *wpspin = NULL;
@@ -105,7 +126,12 @@ static void request_input_passphrase_reply(DBusPendingCall *call, void *user_dat
        DBusMessageIter iter, dict;
        DBusMessage *reply = dbus_pending_call_steal_reply(call);
 
-       if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
+       if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
+               error = dbus_message_get_error_name(reply);
+               goto done;
+       }
+
+       if (check_reply_has_dict(reply) == FALSE)
                goto done;
 
        values_received = TRUE;
@@ -176,7 +202,7 @@ done:
        passphrase_reply->callback(passphrase_reply->service, values_received,
                                name, name_len,
                                identity, passphrase,
-                               wps, wpspin,
+                               wps, wpspin, error,
                                passphrase_reply->user_data);
        connman_service_unref(passphrase_reply->service);
        dbus_message_unref(reply);
@@ -311,15 +337,24 @@ static void request_input_append_password(DBusMessageIter *iter,
 static void request_input_login_reply(DBusPendingCall *call, void *user_data)
 {
        struct request_input_reply *username_password_reply = user_data;
+       const char *error = NULL;
+       connman_bool_t values_received = FALSE;
        char *username = NULL;
        char *password = NULL;
        char *key;
        DBusMessageIter iter, dict;
        DBusMessage *reply = dbus_pending_call_steal_reply(call);
 
-       if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
+       if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
+               error = dbus_message_get_error_name(reply);
+               goto done;
+       }
+
+       if (check_reply_has_dict(reply) == FALSE)
                goto done;
 
+       values_received = TRUE;
+
        dbus_message_iter_init(reply, &iter);
        dbus_message_iter_recurse(&iter, &dict);
        while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
@@ -353,9 +388,9 @@ static void request_input_login_reply(DBusPendingCall *call, void *user_data)
 
 done:
        username_password_reply->callback(username_password_reply->service,
-                                       TRUE, NULL, 0,
+                                       values_received, NULL, 0,
                                        username, password,
-                                       FALSE, NULL,
+                                       FALSE, NULL, error,
                                        username_password_reply->user_data);
        connman_service_unref(username_password_reply->service);
        dbus_message_unref(reply);
@@ -402,8 +437,11 @@ int __connman_agent_request_passphrase_input(struct connman_service *service,
                                        request_input_append_identity, service);
        }
 
-       connman_dbus_dict_append_dict(&dict, "Passphrase",
-                               request_input_append_passphrase, service);
+       if (__connman_service_get_security(service) !=
+                       CONNMAN_SERVICE_SECURITY_NONE) {
+               connman_dbus_dict_append_dict(&dict, "Passphrase",
+                                       request_input_append_passphrase, service);
+       }
 
        if (__connman_service_wps_enabled(service) == TRUE) {
            connman_dbus_dict_append_dict(&dict, "WPS",
@@ -520,15 +558,18 @@ static void request_browser_reply(DBusPendingCall *call, void *user_data)
        struct request_browser_reply_data *browser_reply_data = user_data;
        DBusMessage *reply = dbus_pending_call_steal_reply(call);
        connman_bool_t result = FALSE;
+       const char *error = NULL;
 
-       if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
+       if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
+               error = dbus_message_get_error_name(reply);
                goto done;
+       }
 
        result = TRUE;
 
 done:
-       browser_reply_data->callback(browser_reply_data->service,
-                                       result, browser_reply_data->user_data);
+       browser_reply_data->callback(browser_reply_data->service, result,
+                                       error, browser_reply_data->user_data);
        connman_service_unref(browser_reply_data->service);
        dbus_message_unref(reply);
        g_free(browser_reply_data);
@@ -620,6 +661,7 @@ static void report_error_reply(DBusPendingCall *call, void *user_data)
        connman_service_unref(report_error->service);
        g_free(report_error);
        dbus_message_unref(reply);
+       dbus_pending_call_unref(call);
 }
 
 int __connman_agent_report_error(struct connman_service *service,