5 * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include <connman/agent.h>
32 #include <connman/setting.h>
33 #include <connman/service.h>
37 static bool check_reply_has_dict(DBusMessage *reply)
39 const char *signature = DBUS_TYPE_ARRAY_AS_STRING
40 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
41 DBUS_TYPE_STRING_AS_STRING
42 DBUS_TYPE_VARIANT_AS_STRING
43 DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
45 if (dbus_message_has_signature(reply, signature))
48 connman_warn("Reply %s to %s from %s has wrong signature %s",
50 dbus_message_get_interface(reply),
51 dbus_message_get_sender(reply),
52 dbus_message_get_signature(reply));
57 struct request_input_reply {
58 struct connman_service *service;
59 struct connman_peer *peer;
61 authentication_cb_t service_callback;
62 peer_wps_cb_t peer_callback;
68 static void request_input_passphrase_reply(DBusMessage *reply, void *user_data)
70 struct request_input_reply *passphrase_reply = user_data;
71 bool values_received = false;
73 const char *error = NULL;
74 char *identity = NULL;
75 char *passphrase = NULL;
80 DBusMessageIter iter, dict;
83 error = CONNMAN_ERROR_INTERFACE ".OperationAborted";
87 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
88 error = dbus_message_get_error_name(reply);
92 if (!check_reply_has_dict(reply))
95 values_received = true;
97 dbus_message_iter_init(reply, &iter);
98 dbus_message_iter_recurse(&iter, &dict);
99 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
100 DBusMessageIter entry, value;
102 dbus_message_iter_recurse(&dict, &entry);
103 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
104 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
108 dbus_message_iter_get_basic(&entry, &key);
110 if (g_str_equal(key, "Identity")) {
111 dbus_message_iter_next(&entry);
112 if (dbus_message_iter_get_arg_type(&entry)
113 != DBUS_TYPE_VARIANT) {
114 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
118 dbus_message_iter_recurse(&entry, &value);
119 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_STRING) {
120 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
124 dbus_message_iter_get_basic(&value, &identity);
126 } else if (g_str_equal(key, "Passphrase")) {
127 dbus_message_iter_next(&entry);
128 if (dbus_message_iter_get_arg_type(&entry)
129 != DBUS_TYPE_VARIANT) {
130 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
134 dbus_message_iter_recurse(&entry, &value);
135 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_STRING) {
136 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
140 dbus_message_iter_get_basic(&value, &passphrase);
142 } else if (g_str_equal(key, "WPS")) {
144 dbus_message_iter_next(&entry);
145 if (dbus_message_iter_get_arg_type(&entry)
146 != DBUS_TYPE_VARIANT) {
147 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
151 dbus_message_iter_recurse(&entry, &value);
152 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_STRING) {
153 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
158 dbus_message_iter_get_basic(&value, &wpspin);
160 } else if (g_str_equal(key, "Name")) {
161 dbus_message_iter_next(&entry);
162 if (dbus_message_iter_get_arg_type(&entry)
163 != DBUS_TYPE_VARIANT) {
164 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
168 dbus_message_iter_recurse(&entry, &value);
169 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_STRING) {
170 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
174 dbus_message_iter_get_basic(&value, &name);
175 name_len = strlen(name);
176 } else if (g_str_equal(key, "SSID")) {
177 DBusMessageIter array_iter;
179 dbus_message_iter_next(&entry);
180 if (dbus_message_iter_get_arg_type(&entry)
181 != DBUS_TYPE_VARIANT) {
182 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
185 dbus_message_iter_recurse(&entry, &value);
186 if (dbus_message_iter_get_arg_type(&value)
187 != DBUS_TYPE_ARRAY) {
188 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
191 dbus_message_iter_recurse(&value, &array_iter);
192 if (dbus_message_iter_get_arg_type(&array_iter)
194 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
197 dbus_message_iter_get_fixed_array(&array_iter, &name,
200 dbus_message_iter_next(&dict);
204 passphrase_reply->service_callback(passphrase_reply->service,
205 values_received, name, name_len,
206 identity, passphrase, wps, wpspin,
207 error, passphrase_reply->user_data);
209 g_free(passphrase_reply);
212 static void request_input_append_alternates(DBusMessageIter *iter,
215 const char *str = user_data;
216 char **alternates, **alternative;
221 alternates = g_strsplit(str, ",", 0);
225 for (alternative = alternates; *alternative; alternative++)
226 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
229 g_strfreev(alternates);
232 static void request_input_append_identity(DBusMessageIter *iter,
235 char *str = "string";
237 connman_dbus_dict_append_basic(iter, "Type",
238 DBUS_TYPE_STRING, &str);
240 connman_dbus_dict_append_basic(iter, "Requirement",
241 DBUS_TYPE_STRING, &str);
244 static void request_input_append_passphrase(DBusMessageIter *iter,
247 struct connman_service *service = user_data;
251 switch (__connman_service_get_security(service)) {
252 case CONNMAN_SERVICE_SECURITY_WEP:
255 case CONNMAN_SERVICE_SECURITY_PSK:
256 #if defined TIZEN_EXT
257 case CONNMAN_SERVICE_SECURITY_RSN:
261 case CONNMAN_SERVICE_SECURITY_8021X:
262 phase2 = __connman_service_get_phase2(service);
265 g_str_has_suffix(phase2, "GTC") ||
266 g_str_has_suffix(phase2, "OTP")))
269 value = "passphrase";
276 connman_dbus_dict_append_basic(iter, "Type",
277 DBUS_TYPE_STRING, &value);
279 connman_dbus_dict_append_basic(iter, "Requirement",
280 DBUS_TYPE_STRING, &value);
282 if (__connman_service_wps_enabled(service)) {
283 connman_dbus_dict_append_array(iter, "Alternates",
285 request_input_append_alternates,
290 struct request_wps_data {
294 static void request_input_append_wps(DBusMessageIter *iter, void *user_data)
296 struct request_wps_data *wps = user_data;
297 const char *str = "wpspin";
299 connman_dbus_dict_append_basic(iter, "Type",
300 DBUS_TYPE_STRING, &str);
301 if (wps && wps->peer)
305 connman_dbus_dict_append_basic(iter, "Requirement",
306 DBUS_TYPE_STRING, &str);
309 static void request_input_append_name(DBusMessageIter *iter, void *user_data)
311 const char *str = "string";
313 connman_dbus_dict_append_basic(iter, "Type",
314 DBUS_TYPE_STRING, &str);
316 connman_dbus_dict_append_basic(iter, "Requirement",
317 DBUS_TYPE_STRING, &str);
318 connman_dbus_dict_append_array(iter, "Alternates",
320 request_input_append_alternates,
324 static void request_input_append_ssid(DBusMessageIter *iter, void *user_data)
326 const char *str = "ssid";
328 connman_dbus_dict_append_basic(iter, "Type",
329 DBUS_TYPE_STRING, &str);
331 connman_dbus_dict_append_basic(iter, "Requirement",
332 DBUS_TYPE_STRING, &str);
335 static void request_input_append_password(DBusMessageIter *iter,
338 char *str = "passphrase";
340 connman_dbus_dict_append_basic(iter, "Type",
341 DBUS_TYPE_STRING, &str);
343 connman_dbus_dict_append_basic(iter, "Requirement",
344 DBUS_TYPE_STRING, &str);
347 struct previous_passphrase_data {
348 const char *passphrase;
352 static void request_input_append_previouspassphrase(DBusMessageIter *iter,
355 struct previous_passphrase_data *data = user_data;
356 const char *requirement = "informational";
358 connman_dbus_dict_append_basic(iter, "Type",
359 DBUS_TYPE_STRING, &data->type);
361 connman_dbus_dict_append_basic(iter, "Requirement",
362 DBUS_TYPE_STRING, &requirement);
364 connman_dbus_dict_append_basic(iter, "Value",
365 DBUS_TYPE_STRING, &data->passphrase);
368 static void previous_passphrase_handler(DBusMessageIter *iter,
369 struct connman_service *service)
371 enum connman_service_security security;
372 struct previous_passphrase_data data;
373 struct connman_network *network;
375 network = __connman_service_get_network(service);
376 data.passphrase = connman_network_get_string(network, "WiFi.PinWPS");
378 if (connman_network_get_bool(network, "WiFi.UseWPS") &&
380 data.type = "wpspin";
382 data.passphrase = __connman_service_get_passphrase(service);
383 if (!data.passphrase)
386 security = __connman_service_get_security(service);
388 case CONNMAN_SERVICE_SECURITY_WEP:
391 case CONNMAN_SERVICE_SECURITY_PSK:
392 #if defined TIZEN_EXT
393 case CONNMAN_SERVICE_SECURITY_RSN:
398 * This should never happen: no passphrase is set if security
399 * is not one of the above. */
405 connman_dbus_dict_append_dict(iter, "PreviousPassphrase",
406 request_input_append_previouspassphrase, &data);
409 static void request_input_login_reply(DBusMessage *reply, void *user_data)
411 struct request_input_reply *username_password_reply = user_data;
412 const char *error = NULL;
413 bool values_received = false;
414 char *username = NULL;
415 char *password = NULL;
417 DBusMessageIter iter, dict;
420 error = CONNMAN_ERROR_INTERFACE ".OperationAborted";
424 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
425 error = dbus_message_get_error_name(reply);
429 if (!check_reply_has_dict(reply))
432 values_received = true;
434 dbus_message_iter_init(reply, &iter);
435 dbus_message_iter_recurse(&iter, &dict);
436 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
437 DBusMessageIter entry, value;
439 dbus_message_iter_recurse(&dict, &entry);
440 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
443 dbus_message_iter_get_basic(&entry, &key);
445 if (g_str_equal(key, "Username")) {
446 dbus_message_iter_next(&entry);
447 if (dbus_message_iter_get_arg_type(&entry)
448 != DBUS_TYPE_VARIANT) {
449 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
453 dbus_message_iter_recurse(&entry, &value);
454 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_STRING) {
455 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
459 dbus_message_iter_get_basic(&value, &username);
461 } else if (g_str_equal(key, "Password")) {
462 dbus_message_iter_next(&entry);
463 if (dbus_message_iter_get_arg_type(&entry) !=
465 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
469 dbus_message_iter_recurse(&entry, &value);
470 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_STRING) {
471 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
475 dbus_message_iter_get_basic(&value, &password);
478 dbus_message_iter_next(&dict);
482 username_password_reply->service_callback(
483 username_password_reply->service, values_received,
484 NULL, 0, username, password, FALSE, NULL, error,
485 username_password_reply->user_data);
487 g_free(username_password_reply);
490 int __connman_agent_request_passphrase_input(struct connman_service *service,
491 authentication_cb_t callback,
492 const char *dbus_sender, void *user_data)
494 DBusMessage *message;
495 const char *path, *agent_sender, *agent_path;
496 DBusMessageIter iter;
497 DBusMessageIter dict;
498 struct request_input_reply *passphrase_reply;
502 agent = connman_agent_get_info(dbus_sender, &agent_sender,
505 DBG("agent %p service %p path %s", agent, service, agent_path);
507 if (!service || !agent || !agent_path || !callback)
510 message = dbus_message_new_method_call(agent_sender, agent_path,
511 CONNMAN_AGENT_INTERFACE,
516 dbus_message_iter_init_append(message, &iter);
518 path = __connman_service_get_path(service);
519 dbus_message_iter_append_basic(&iter,
520 DBUS_TYPE_OBJECT_PATH, &path);
522 connman_dbus_dict_open(&iter, &dict);
524 if (__connman_service_is_hidden(service)) {
525 connman_dbus_dict_append_dict(&dict, "Name",
526 request_input_append_name, NULL);
527 connman_dbus_dict_append_dict(&dict, "SSID",
528 request_input_append_ssid, NULL);
531 if (__connman_service_get_security(service) ==
532 CONNMAN_SERVICE_SECURITY_8021X) {
533 connman_dbus_dict_append_dict(&dict, "Identity",
534 request_input_append_identity, service);
537 if (__connman_service_get_security(service) !=
538 CONNMAN_SERVICE_SECURITY_NONE) {
539 connman_dbus_dict_append_dict(&dict, "Passphrase",
540 request_input_append_passphrase, service);
542 previous_passphrase_handler(&dict, service);
545 if (__connman_service_wps_enabled(service))
546 connman_dbus_dict_append_dict(&dict, "WPS",
547 request_input_append_wps, NULL);
549 connman_dbus_dict_close(&iter, &dict);
551 passphrase_reply = g_try_new0(struct request_input_reply, 1);
552 if (!passphrase_reply) {
553 dbus_message_unref(message);
557 passphrase_reply->service = service;
558 passphrase_reply->service_callback = callback;
559 passphrase_reply->user_data = user_data;
561 err = connman_agent_queue_message(service, message,
562 connman_timeout_input_request(),
563 request_input_passphrase_reply,
564 passphrase_reply, agent);
566 if (err < 0 && err != -EBUSY) {
567 DBG("error %d sending agent message", err);
568 dbus_message_unref(message);
569 g_free(passphrase_reply);
573 dbus_message_unref(message);
578 int __connman_agent_request_login_input(struct connman_service *service,
579 authentication_cb_t callback, void *user_data)
581 DBusMessage *message;
582 const char *path, *agent_sender, *agent_path;
583 DBusMessageIter iter;
584 DBusMessageIter dict;
585 struct request_input_reply *username_password_reply;
589 agent = connman_agent_get_info(NULL, &agent_sender, &agent_path);
591 if (!service || !agent || !agent_path || !callback)
594 message = dbus_message_new_method_call(agent_sender, agent_path,
595 CONNMAN_AGENT_INTERFACE,
600 dbus_message_iter_init_append(message, &iter);
602 path = __connman_service_get_path(service);
603 dbus_message_iter_append_basic(&iter,
604 DBUS_TYPE_OBJECT_PATH, &path);
606 connman_dbus_dict_open(&iter, &dict);
608 connman_dbus_dict_append_dict(&dict, "Username",
609 request_input_append_identity, service);
611 connman_dbus_dict_append_dict(&dict, "Password",
612 request_input_append_password, service);
614 connman_dbus_dict_close(&iter, &dict);
616 username_password_reply = g_try_new0(struct request_input_reply, 1);
617 if (!username_password_reply) {
618 dbus_message_unref(message);
622 username_password_reply->service = service;
623 username_password_reply->service_callback = callback;
624 username_password_reply->user_data = user_data;
626 err = connman_agent_queue_message(service, message,
627 connman_timeout_input_request(),
628 request_input_login_reply, username_password_reply,
630 if (err < 0 && err != -EBUSY) {
631 DBG("error %d sending agent request", err);
632 dbus_message_unref(message);
633 g_free(username_password_reply);
637 dbus_message_unref(message);
642 struct request_browser_reply_data {
643 struct connman_service *service;
644 browser_authentication_cb_t callback;
648 static void request_browser_reply(DBusMessage *reply, void *user_data)
650 struct request_browser_reply_data *browser_reply_data = user_data;
652 const char *error = NULL;
655 error = CONNMAN_ERROR_INTERFACE ".OperationAborted";
659 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
660 error = dbus_message_get_error_name(reply);
667 browser_reply_data->callback(browser_reply_data->service, result,
668 error, browser_reply_data->user_data);
669 g_free(browser_reply_data);
672 int __connman_agent_request_browser(struct connman_service *service,
673 browser_authentication_cb_t callback,
674 const char *url, void *user_data)
676 struct request_browser_reply_data *browser_reply_data;
677 DBusMessage *message;
678 DBusMessageIter iter;
679 const char *path, *agent_sender, *agent_path;
683 agent = connman_agent_get_info(NULL, &agent_sender, &agent_path);
685 if (!service || !agent || !agent_path || !callback)
691 message = dbus_message_new_method_call(agent_sender, agent_path,
692 CONNMAN_AGENT_INTERFACE,
697 dbus_message_iter_init_append(message, &iter);
699 path = __connman_service_get_path(service);
700 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
702 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &url);
704 browser_reply_data = g_try_new0(struct request_browser_reply_data, 1);
705 if (!browser_reply_data) {
706 dbus_message_unref(message);
710 browser_reply_data->service = service;
711 browser_reply_data->callback = callback;
712 browser_reply_data->user_data = user_data;
714 err = connman_agent_queue_message(service, message,
715 connman_timeout_browser_launch(),
716 request_browser_reply, browser_reply_data,
719 if (err < 0 && err != -EBUSY) {
720 DBG("error %d sending browser request", err);
721 dbus_message_unref(message);
722 g_free(browser_reply_data);
726 dbus_message_unref(message);
731 int __connman_agent_report_peer_error(struct connman_peer *peer,
732 const char *path, const char *error,
733 report_error_cb_t callback,
734 const char *dbus_sender,
737 return connman_agent_report_error_full(peer, path, "ReportPeerError",
738 error, callback, dbus_sender, user_data);
741 static void request_peer_authorization_reply(DBusMessage *reply,
744 struct request_input_reply *auth_reply = user_data;
745 DBusMessageIter iter, dict;
746 const char *error = NULL;
747 bool choice_done = false;
752 error = CONNMAN_ERROR_INTERFACE ".OperationAborted";
756 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
757 error = dbus_message_get_error_name(reply);
761 if (!check_reply_has_dict(reply))
764 dbus_message_iter_init(reply, &iter);
765 dbus_message_iter_recurse(&iter, &dict);
766 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
767 DBusMessageIter entry, value;
769 dbus_message_iter_recurse(&dict, &entry);
770 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
771 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
775 dbus_message_iter_get_basic(&entry, &key);
777 if (g_str_equal(key, "WPS")) {
780 dbus_message_iter_next(&entry);
781 if (dbus_message_iter_get_arg_type(&entry)
782 != DBUS_TYPE_VARIANT) {
783 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
787 dbus_message_iter_recurse(&entry, &value);
788 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_STRING) {
789 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
793 dbus_message_iter_get_basic(&value, &wpspin);
796 dbus_message_iter_next(&dict);
799 if (!auth_reply->wps_requested)
803 auth_reply->peer_callback(auth_reply->peer, choice_done, wpspin,
804 error, auth_reply->user_data);
809 int __connman_agent_request_peer_authorization(struct connman_peer *peer,
810 peer_wps_cb_t callback,
812 const char *dbus_sender,
815 struct request_wps_data wps = { .peer = true };
816 const char *path, *agent_sender, *agent_path;
817 struct request_input_reply *auth_reply;
818 DBusMessageIter dict, iter;
819 DBusMessage *message;
823 agent = connman_agent_get_info(dbus_sender, &agent_sender,
825 DBG("agent %p peer %p path %s", agent, peer, agent_path);
827 if (!peer || !agent || !agent_path || !callback)
830 message = dbus_message_new_method_call(agent_sender, agent_path,
831 CONNMAN_AGENT_INTERFACE, "RequestPeerAuthorization");
835 dbus_message_iter_init_append(message, &iter);
837 path = __connman_peer_get_path(peer);
838 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
840 connman_dbus_dict_open(&iter, &dict);
843 connman_dbus_dict_append_dict(&dict, "WPS",
844 request_input_append_wps, &wps);
846 connman_dbus_dict_close(&iter, &dict);
848 auth_reply = g_try_new0(struct request_input_reply, 1);
850 dbus_message_unref(message);
854 auth_reply->peer = peer;
855 auth_reply->peer_callback = callback;
856 auth_reply->wps_requested = wps_requested;
857 auth_reply->user_data = user_data;
859 err = connman_agent_queue_message(peer, message,
860 connman_timeout_input_request(),
861 request_peer_authorization_reply,
863 if (err < 0 && err != -EBUSY) {
864 DBG("error %d sending agent message", err);
865 dbus_message_unref(message);
870 dbus_message_unref(message);