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;
85 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
86 error = dbus_message_get_error_name(reply);
90 if (!check_reply_has_dict(reply))
93 values_received = true;
95 dbus_message_iter_init(reply, &iter);
96 dbus_message_iter_recurse(&iter, &dict);
97 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
98 DBusMessageIter entry, value;
100 dbus_message_iter_recurse(&dict, &entry);
101 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
104 dbus_message_iter_get_basic(&entry, &key);
106 if (g_str_equal(key, "Identity")) {
107 dbus_message_iter_next(&entry);
108 if (dbus_message_iter_get_arg_type(&entry)
109 != DBUS_TYPE_VARIANT)
111 dbus_message_iter_recurse(&entry, &value);
112 dbus_message_iter_get_basic(&value, &identity);
114 } else if (g_str_equal(key, "Passphrase")) {
115 dbus_message_iter_next(&entry);
116 if (dbus_message_iter_get_arg_type(&entry)
117 != DBUS_TYPE_VARIANT)
119 dbus_message_iter_recurse(&entry, &value);
120 dbus_message_iter_get_basic(&value, &passphrase);
122 } else if (g_str_equal(key, "WPS")) {
125 dbus_message_iter_next(&entry);
126 if (dbus_message_iter_get_arg_type(&entry)
127 != DBUS_TYPE_VARIANT)
129 dbus_message_iter_recurse(&entry, &value);
130 dbus_message_iter_get_basic(&value, &wpspin);
132 } else if (g_str_equal(key, "Name")) {
133 dbus_message_iter_next(&entry);
134 if (dbus_message_iter_get_arg_type(&entry)
135 != DBUS_TYPE_VARIANT)
137 dbus_message_iter_recurse(&entry, &value);
138 dbus_message_iter_get_basic(&value, &name);
139 name_len = strlen(name);
140 } else if (g_str_equal(key, "SSID")) {
141 dbus_message_iter_next(&entry);
142 if (dbus_message_iter_get_arg_type(&entry)
143 != DBUS_TYPE_VARIANT)
145 dbus_message_iter_recurse(&entry, &value);
146 if (dbus_message_iter_get_arg_type(&value)
147 != DBUS_TYPE_VARIANT)
149 if (dbus_message_iter_get_element_type(&value)
150 != DBUS_TYPE_VARIANT)
152 dbus_message_iter_get_fixed_array(&value, &name,
155 dbus_message_iter_next(&dict);
159 passphrase_reply->service_callback(passphrase_reply->service,
160 values_received, name, name_len,
161 identity, passphrase, wps, wpspin,
162 error, passphrase_reply->user_data);
164 g_free(passphrase_reply);
167 static void request_input_append_alternates(DBusMessageIter *iter,
170 const char *str = user_data;
171 char **alternates, **alternative;
176 alternates = g_strsplit(str, ",", 0);
180 for (alternative = alternates; *alternative; alternative++)
181 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
184 g_strfreev(alternates);
187 static void request_input_append_identity(DBusMessageIter *iter,
190 char *str = "string";
192 connman_dbus_dict_append_basic(iter, "Type",
193 DBUS_TYPE_STRING, &str);
195 connman_dbus_dict_append_basic(iter, "Requirement",
196 DBUS_TYPE_STRING, &str);
199 static void request_input_append_passphrase(DBusMessageIter *iter,
202 struct connman_service *service = user_data;
206 switch (__connman_service_get_security(service)) {
207 case CONNMAN_SERVICE_SECURITY_WEP:
210 case CONNMAN_SERVICE_SECURITY_PSK:
213 case CONNMAN_SERVICE_SECURITY_8021X:
214 phase2 = __connman_service_get_phase2(service);
217 g_str_has_suffix(phase2, "GTC") ||
218 g_str_has_suffix(phase2, "OTP")))
221 value = "passphrase";
228 connman_dbus_dict_append_basic(iter, "Type",
229 DBUS_TYPE_STRING, &value);
231 connman_dbus_dict_append_basic(iter, "Requirement",
232 DBUS_TYPE_STRING, &value);
234 if (__connman_service_wps_enabled(service)) {
235 connman_dbus_dict_append_array(iter, "Alternates",
237 request_input_append_alternates,
242 struct request_wps_data {
246 static void request_input_append_wps(DBusMessageIter *iter, void *user_data)
248 struct request_wps_data *wps = user_data;
249 const char *str = "wpspin";
251 connman_dbus_dict_append_basic(iter, "Type",
252 DBUS_TYPE_STRING, &str);
253 if (wps && wps->peer)
257 connman_dbus_dict_append_basic(iter, "Requirement",
258 DBUS_TYPE_STRING, &str);
261 static void request_input_append_name(DBusMessageIter *iter, void *user_data)
263 const char *str = "string";
265 connman_dbus_dict_append_basic(iter, "Type",
266 DBUS_TYPE_STRING, &str);
268 connman_dbus_dict_append_basic(iter, "Requirement",
269 DBUS_TYPE_STRING, &str);
270 connman_dbus_dict_append_array(iter, "Alternates",
272 request_input_append_alternates,
276 static void request_input_append_ssid(DBusMessageIter *iter, void *user_data)
278 const char *str = "ssid";
280 connman_dbus_dict_append_basic(iter, "Type",
281 DBUS_TYPE_STRING, &str);
283 connman_dbus_dict_append_basic(iter, "Requirement",
284 DBUS_TYPE_STRING, &str);
287 static void request_input_append_password(DBusMessageIter *iter,
290 char *str = "passphrase";
292 connman_dbus_dict_append_basic(iter, "Type",
293 DBUS_TYPE_STRING, &str);
295 connman_dbus_dict_append_basic(iter, "Requirement",
296 DBUS_TYPE_STRING, &str);
299 struct previous_passphrase_data {
300 const char *passphrase;
304 static void request_input_append_previouspassphrase(DBusMessageIter *iter,
307 struct previous_passphrase_data *data = user_data;
308 const char *requirement = "informational";
310 connman_dbus_dict_append_basic(iter, "Type",
311 DBUS_TYPE_STRING, &data->type);
313 connman_dbus_dict_append_basic(iter, "Requirement",
314 DBUS_TYPE_STRING, &requirement);
316 connman_dbus_dict_append_basic(iter, "Value",
317 DBUS_TYPE_STRING, &data->passphrase);
320 static void previous_passphrase_handler(DBusMessageIter *iter,
321 struct connman_service *service)
323 enum connman_service_security security;
324 struct previous_passphrase_data data;
325 struct connman_network *network;
327 network = __connman_service_get_network(service);
328 data.passphrase = connman_network_get_string(network, "WiFi.PinWPS");
330 if (connman_network_get_bool(network, "WiFi.UseWPS") &&
332 data.type = "wpspin";
334 data.passphrase = __connman_service_get_passphrase(service);
335 if (!data.passphrase)
338 security = __connman_service_get_security(service);
340 case CONNMAN_SERVICE_SECURITY_WEP:
343 case CONNMAN_SERVICE_SECURITY_PSK:
347 * This should never happen: no passphrase is set if security
348 * is not one of the above. */
354 connman_dbus_dict_append_dict(iter, "PreviousPassphrase",
355 request_input_append_previouspassphrase, &data);
358 static void request_input_login_reply(DBusMessage *reply, void *user_data)
360 struct request_input_reply *username_password_reply = user_data;
361 const char *error = NULL;
362 bool values_received = false;
363 char *username = NULL;
364 char *password = NULL;
366 DBusMessageIter iter, dict;
371 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
372 error = dbus_message_get_error_name(reply);
376 if (!check_reply_has_dict(reply))
379 values_received = true;
381 dbus_message_iter_init(reply, &iter);
382 dbus_message_iter_recurse(&iter, &dict);
383 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
384 DBusMessageIter entry, value;
386 dbus_message_iter_recurse(&dict, &entry);
387 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
390 dbus_message_iter_get_basic(&entry, &key);
392 if (g_str_equal(key, "Username")) {
393 dbus_message_iter_next(&entry);
394 if (dbus_message_iter_get_arg_type(&entry)
395 != DBUS_TYPE_VARIANT)
397 dbus_message_iter_recurse(&entry, &value);
398 dbus_message_iter_get_basic(&value, &username);
400 } else if (g_str_equal(key, "Password")) {
401 dbus_message_iter_next(&entry);
402 if (dbus_message_iter_get_arg_type(&entry) !=
405 dbus_message_iter_recurse(&entry, &value);
406 dbus_message_iter_get_basic(&value, &password);
409 dbus_message_iter_next(&dict);
413 username_password_reply->service_callback(
414 username_password_reply->service, values_received,
415 NULL, 0, username, password, FALSE, NULL, error,
416 username_password_reply->user_data);
418 g_free(username_password_reply);
421 int __connman_agent_request_passphrase_input(struct connman_service *service,
422 authentication_cb_t callback,
423 const char *dbus_sender, void *user_data)
425 DBusMessage *message;
426 const char *path, *agent_sender, *agent_path;
427 DBusMessageIter iter;
428 DBusMessageIter dict;
429 struct request_input_reply *passphrase_reply;
433 agent = connman_agent_get_info(dbus_sender, &agent_sender,
436 DBG("agent %p service %p path %s", agent, service, agent_path);
438 if (!service || !agent || !agent_path || !callback)
441 message = dbus_message_new_method_call(agent_sender, agent_path,
442 CONNMAN_AGENT_INTERFACE,
447 dbus_message_iter_init_append(message, &iter);
449 path = __connman_service_get_path(service);
450 dbus_message_iter_append_basic(&iter,
451 DBUS_TYPE_OBJECT_PATH, &path);
453 connman_dbus_dict_open(&iter, &dict);
455 if (__connman_service_is_hidden(service)) {
456 connman_dbus_dict_append_dict(&dict, "Name",
457 request_input_append_name, NULL);
458 connman_dbus_dict_append_dict(&dict, "SSID",
459 request_input_append_ssid, NULL);
462 if (__connman_service_get_security(service) ==
463 CONNMAN_SERVICE_SECURITY_8021X) {
464 connman_dbus_dict_append_dict(&dict, "Identity",
465 request_input_append_identity, service);
468 if (__connman_service_get_security(service) !=
469 CONNMAN_SERVICE_SECURITY_NONE) {
470 connman_dbus_dict_append_dict(&dict, "Passphrase",
471 request_input_append_passphrase, service);
473 previous_passphrase_handler(&dict, service);
476 if (__connman_service_wps_enabled(service))
477 connman_dbus_dict_append_dict(&dict, "WPS",
478 request_input_append_wps, NULL);
480 connman_dbus_dict_close(&iter, &dict);
482 passphrase_reply = g_try_new0(struct request_input_reply, 1);
483 if (!passphrase_reply) {
484 dbus_message_unref(message);
488 passphrase_reply->service = service;
489 passphrase_reply->service_callback = callback;
490 passphrase_reply->user_data = user_data;
492 err = connman_agent_queue_message(service, message,
493 connman_timeout_input_request(),
494 request_input_passphrase_reply,
495 passphrase_reply, agent);
497 if (err < 0 && err != -EBUSY) {
498 DBG("error %d sending agent message", err);
499 dbus_message_unref(message);
500 g_free(passphrase_reply);
504 dbus_message_unref(message);
509 int __connman_agent_request_login_input(struct connman_service *service,
510 authentication_cb_t callback, void *user_data)
512 DBusMessage *message;
513 const char *path, *agent_sender, *agent_path;
514 DBusMessageIter iter;
515 DBusMessageIter dict;
516 struct request_input_reply *username_password_reply;
520 agent = connman_agent_get_info(NULL, &agent_sender, &agent_path);
522 if (!service || !agent || !agent_path || !callback)
525 message = dbus_message_new_method_call(agent_sender, agent_path,
526 CONNMAN_AGENT_INTERFACE,
531 dbus_message_iter_init_append(message, &iter);
533 path = __connman_service_get_path(service);
534 dbus_message_iter_append_basic(&iter,
535 DBUS_TYPE_OBJECT_PATH, &path);
537 connman_dbus_dict_open(&iter, &dict);
539 connman_dbus_dict_append_dict(&dict, "Username",
540 request_input_append_identity, service);
542 connman_dbus_dict_append_dict(&dict, "Password",
543 request_input_append_password, service);
545 connman_dbus_dict_close(&iter, &dict);
547 username_password_reply = g_try_new0(struct request_input_reply, 1);
548 if (!username_password_reply) {
549 dbus_message_unref(message);
553 username_password_reply->service = service;
554 username_password_reply->service_callback = callback;
555 username_password_reply->user_data = user_data;
557 err = connman_agent_queue_message(service, message,
558 connman_timeout_input_request(),
559 request_input_login_reply, username_password_reply,
561 if (err < 0 && err != -EBUSY) {
562 DBG("error %d sending agent request", err);
563 dbus_message_unref(message);
564 g_free(username_password_reply);
568 dbus_message_unref(message);
573 struct request_browser_reply_data {
574 struct connman_service *service;
575 browser_authentication_cb_t callback;
579 static void request_browser_reply(DBusMessage *reply, void *user_data)
581 struct request_browser_reply_data *browser_reply_data = user_data;
583 const char *error = NULL;
585 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
586 error = dbus_message_get_error_name(reply);
593 browser_reply_data->callback(browser_reply_data->service, result,
594 error, browser_reply_data->user_data);
595 g_free(browser_reply_data);
598 int __connman_agent_request_browser(struct connman_service *service,
599 browser_authentication_cb_t callback,
600 const char *url, void *user_data)
602 struct request_browser_reply_data *browser_reply_data;
603 DBusMessage *message;
604 DBusMessageIter iter;
605 const char *path, *agent_sender, *agent_path;
609 agent = connman_agent_get_info(NULL, &agent_sender, &agent_path);
611 if (!service || !agent || !agent_path || !callback)
617 message = dbus_message_new_method_call(agent_sender, agent_path,
618 CONNMAN_AGENT_INTERFACE,
623 dbus_message_iter_init_append(message, &iter);
625 path = __connman_service_get_path(service);
626 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
628 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &url);
630 browser_reply_data = g_try_new0(struct request_browser_reply_data, 1);
631 if (!browser_reply_data) {
632 dbus_message_unref(message);
636 browser_reply_data->service = service;
637 browser_reply_data->callback = callback;
638 browser_reply_data->user_data = user_data;
640 err = connman_agent_queue_message(service, message,
641 connman_timeout_browser_launch(),
642 request_browser_reply, browser_reply_data,
645 if (err < 0 && err != -EBUSY) {
646 DBG("error %d sending browser request", err);
647 dbus_message_unref(message);
648 g_free(browser_reply_data);
652 dbus_message_unref(message);
657 int __connman_agent_report_peer_error(struct connman_peer *peer,
658 const char *path, const char *error,
659 report_error_cb_t callback,
660 const char *dbus_sender,
663 return connman_agent_report_error_full(peer, path, "ReportPeerError",
664 error, callback, dbus_sender, user_data);
667 static void request_peer_authorization_reply(DBusMessage *reply,
670 struct request_input_reply *auth_reply = user_data;
671 DBusMessageIter iter, dict;
672 const char *error = NULL;
673 bool choice_done = false;
680 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
681 error = dbus_message_get_error_name(reply);
685 if (!check_reply_has_dict(reply))
688 dbus_message_iter_init(reply, &iter);
689 dbus_message_iter_recurse(&iter, &dict);
690 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
691 DBusMessageIter entry, value;
693 dbus_message_iter_recurse(&dict, &entry);
694 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
697 dbus_message_iter_get_basic(&entry, &key);
699 if (g_str_equal(key, "WPS")) {
702 dbus_message_iter_next(&entry);
703 if (dbus_message_iter_get_arg_type(&entry)
704 != DBUS_TYPE_VARIANT)
706 dbus_message_iter_recurse(&entry, &value);
707 dbus_message_iter_get_basic(&value, &wpspin);
710 dbus_message_iter_next(&dict);
713 if (!auth_reply->wps_requested)
717 auth_reply->peer_callback(auth_reply->peer, choice_done, wpspin,
718 error, auth_reply->user_data);
723 int __connman_agent_request_peer_authorization(struct connman_peer *peer,
724 peer_wps_cb_t callback,
726 const char *dbus_sender,
729 struct request_wps_data wps = { .peer = true };
730 const char *path, *agent_sender, *agent_path;
731 struct request_input_reply *auth_reply;
732 DBusMessageIter dict, iter;
733 DBusMessage *message;
737 agent = connman_agent_get_info(dbus_sender, &agent_sender,
739 DBG("agent %p peer %p path %s", agent, peer, agent_path);
741 if (!peer || !agent || !agent_path || !callback)
744 message = dbus_message_new_method_call(agent_sender, agent_path,
745 CONNMAN_AGENT_INTERFACE, "RequestPeerAuthorization");
749 dbus_message_iter_init_append(message, &iter);
751 path = __connman_peer_get_path(peer);
752 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
754 connman_dbus_dict_open(&iter, &dict);
757 connman_dbus_dict_append_dict(&dict, "WPS",
758 request_input_append_wps, &wps);
760 connman_dbus_dict_close(&iter, &dict);
762 auth_reply = g_try_new0(struct request_input_reply, 1);
764 dbus_message_unref(message);
768 auth_reply->peer = peer;
769 auth_reply->peer_callback = callback;
770 auth_reply->wps_requested = wps_requested;
771 auth_reply->user_data = user_data;
773 err = connman_agent_queue_message(peer, message,
774 connman_timeout_input_request(),
775 request_peer_authorization_reply,
777 if (err < 0 && err != -EBUSY) {
778 DBG("error %d sending agent message", err);
779 dbus_message_unref(message);
784 dbus_message_unref(message);