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:
258 case CONNMAN_SERVICE_SECURITY_8021X:
259 phase2 = __connman_service_get_phase2(service);
262 g_str_has_suffix(phase2, "GTC") ||
263 g_str_has_suffix(phase2, "OTP")))
266 value = "passphrase";
273 connman_dbus_dict_append_basic(iter, "Type",
274 DBUS_TYPE_STRING, &value);
276 connman_dbus_dict_append_basic(iter, "Requirement",
277 DBUS_TYPE_STRING, &value);
279 if (__connman_service_wps_enabled(service)) {
280 connman_dbus_dict_append_array(iter, "Alternates",
282 request_input_append_alternates,
287 struct request_wps_data {
291 static void request_input_append_wps(DBusMessageIter *iter, void *user_data)
293 struct request_wps_data *wps = user_data;
294 const char *str = "wpspin";
296 connman_dbus_dict_append_basic(iter, "Type",
297 DBUS_TYPE_STRING, &str);
298 if (wps && wps->peer)
302 connman_dbus_dict_append_basic(iter, "Requirement",
303 DBUS_TYPE_STRING, &str);
306 static void request_input_append_name(DBusMessageIter *iter, void *user_data)
308 const char *str = "string";
310 connman_dbus_dict_append_basic(iter, "Type",
311 DBUS_TYPE_STRING, &str);
313 connman_dbus_dict_append_basic(iter, "Requirement",
314 DBUS_TYPE_STRING, &str);
315 connman_dbus_dict_append_array(iter, "Alternates",
317 request_input_append_alternates,
321 static void request_input_append_ssid(DBusMessageIter *iter, void *user_data)
323 const char *str = "ssid";
325 connman_dbus_dict_append_basic(iter, "Type",
326 DBUS_TYPE_STRING, &str);
328 connman_dbus_dict_append_basic(iter, "Requirement",
329 DBUS_TYPE_STRING, &str);
332 static void request_input_append_password(DBusMessageIter *iter,
335 char *str = "passphrase";
337 connman_dbus_dict_append_basic(iter, "Type",
338 DBUS_TYPE_STRING, &str);
340 connman_dbus_dict_append_basic(iter, "Requirement",
341 DBUS_TYPE_STRING, &str);
344 struct previous_passphrase_data {
345 const char *passphrase;
349 static void request_input_append_previouspassphrase(DBusMessageIter *iter,
352 struct previous_passphrase_data *data = user_data;
353 const char *requirement = "informational";
355 connman_dbus_dict_append_basic(iter, "Type",
356 DBUS_TYPE_STRING, &data->type);
358 connman_dbus_dict_append_basic(iter, "Requirement",
359 DBUS_TYPE_STRING, &requirement);
361 connman_dbus_dict_append_basic(iter, "Value",
362 DBUS_TYPE_STRING, &data->passphrase);
365 static void previous_passphrase_handler(DBusMessageIter *iter,
366 struct connman_service *service)
368 enum connman_service_security security;
369 struct previous_passphrase_data data;
370 struct connman_network *network;
372 network = __connman_service_get_network(service);
373 data.passphrase = connman_network_get_string(network, "WiFi.PinWPS");
375 if (connman_network_get_bool(network, "WiFi.UseWPS") &&
377 data.type = "wpspin";
379 data.passphrase = __connman_service_get_passphrase(service);
380 if (!data.passphrase)
383 security = __connman_service_get_security(service);
385 case CONNMAN_SERVICE_SECURITY_WEP:
388 case CONNMAN_SERVICE_SECURITY_PSK:
392 * This should never happen: no passphrase is set if security
393 * is not one of the above. */
399 connman_dbus_dict_append_dict(iter, "PreviousPassphrase",
400 request_input_append_previouspassphrase, &data);
403 static void request_input_login_reply(DBusMessage *reply, void *user_data)
405 struct request_input_reply *username_password_reply = user_data;
406 const char *error = NULL;
407 bool values_received = false;
408 char *username = NULL;
409 char *password = NULL;
411 DBusMessageIter iter, dict;
414 error = CONNMAN_ERROR_INTERFACE ".OperationAborted";
418 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
419 error = dbus_message_get_error_name(reply);
423 if (!check_reply_has_dict(reply))
426 values_received = true;
428 dbus_message_iter_init(reply, &iter);
429 dbus_message_iter_recurse(&iter, &dict);
430 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
431 DBusMessageIter entry, value;
433 dbus_message_iter_recurse(&dict, &entry);
434 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
437 dbus_message_iter_get_basic(&entry, &key);
439 if (g_str_equal(key, "Username")) {
440 dbus_message_iter_next(&entry);
441 if (dbus_message_iter_get_arg_type(&entry)
442 != DBUS_TYPE_VARIANT) {
443 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
447 dbus_message_iter_recurse(&entry, &value);
448 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_STRING) {
449 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
453 dbus_message_iter_get_basic(&value, &username);
455 } else if (g_str_equal(key, "Password")) {
456 dbus_message_iter_next(&entry);
457 if (dbus_message_iter_get_arg_type(&entry) !=
459 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
463 dbus_message_iter_recurse(&entry, &value);
464 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_STRING) {
465 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
469 dbus_message_iter_get_basic(&value, &password);
472 dbus_message_iter_next(&dict);
476 username_password_reply->service_callback(
477 username_password_reply->service, values_received,
478 NULL, 0, username, password, FALSE, NULL, error,
479 username_password_reply->user_data);
481 g_free(username_password_reply);
484 int __connman_agent_request_passphrase_input(struct connman_service *service,
485 authentication_cb_t callback,
486 const char *dbus_sender, void *user_data)
488 DBusMessage *message;
489 const char *path, *agent_sender, *agent_path;
490 DBusMessageIter iter;
491 DBusMessageIter dict;
492 struct request_input_reply *passphrase_reply;
496 agent = connman_agent_get_info(dbus_sender, &agent_sender,
499 DBG("agent %p service %p path %s", agent, service, agent_path);
501 if (!service || !agent || !agent_path || !callback)
504 message = dbus_message_new_method_call(agent_sender, agent_path,
505 CONNMAN_AGENT_INTERFACE,
510 dbus_message_iter_init_append(message, &iter);
512 path = __connman_service_get_path(service);
513 dbus_message_iter_append_basic(&iter,
514 DBUS_TYPE_OBJECT_PATH, &path);
516 connman_dbus_dict_open(&iter, &dict);
518 if (__connman_service_is_hidden(service)) {
519 connman_dbus_dict_append_dict(&dict, "Name",
520 request_input_append_name, NULL);
521 connman_dbus_dict_append_dict(&dict, "SSID",
522 request_input_append_ssid, NULL);
525 if (__connman_service_get_security(service) ==
526 CONNMAN_SERVICE_SECURITY_8021X) {
527 connman_dbus_dict_append_dict(&dict, "Identity",
528 request_input_append_identity, service);
531 if (__connman_service_get_security(service) !=
532 CONNMAN_SERVICE_SECURITY_NONE) {
533 connman_dbus_dict_append_dict(&dict, "Passphrase",
534 request_input_append_passphrase, service);
536 previous_passphrase_handler(&dict, service);
539 if (__connman_service_wps_enabled(service))
540 connman_dbus_dict_append_dict(&dict, "WPS",
541 request_input_append_wps, NULL);
543 connman_dbus_dict_close(&iter, &dict);
545 passphrase_reply = g_try_new0(struct request_input_reply, 1);
546 if (!passphrase_reply) {
547 dbus_message_unref(message);
551 passphrase_reply->service = service;
552 passphrase_reply->service_callback = callback;
553 passphrase_reply->user_data = user_data;
555 err = connman_agent_queue_message(service, message,
556 connman_timeout_input_request(),
557 request_input_passphrase_reply,
558 passphrase_reply, agent);
560 if (err < 0 && err != -EBUSY) {
561 DBG("error %d sending agent message", err);
562 dbus_message_unref(message);
563 g_free(passphrase_reply);
567 dbus_message_unref(message);
572 int __connman_agent_request_login_input(struct connman_service *service,
573 authentication_cb_t callback, void *user_data)
575 DBusMessage *message;
576 const char *path, *agent_sender, *agent_path;
577 DBusMessageIter iter;
578 DBusMessageIter dict;
579 struct request_input_reply *username_password_reply;
583 agent = connman_agent_get_info(NULL, &agent_sender, &agent_path);
585 if (!service || !agent || !agent_path || !callback)
588 message = dbus_message_new_method_call(agent_sender, agent_path,
589 CONNMAN_AGENT_INTERFACE,
594 dbus_message_iter_init_append(message, &iter);
596 path = __connman_service_get_path(service);
597 dbus_message_iter_append_basic(&iter,
598 DBUS_TYPE_OBJECT_PATH, &path);
600 connman_dbus_dict_open(&iter, &dict);
602 connman_dbus_dict_append_dict(&dict, "Username",
603 request_input_append_identity, service);
605 connman_dbus_dict_append_dict(&dict, "Password",
606 request_input_append_password, service);
608 connman_dbus_dict_close(&iter, &dict);
610 username_password_reply = g_try_new0(struct request_input_reply, 1);
611 if (!username_password_reply) {
612 dbus_message_unref(message);
616 username_password_reply->service = service;
617 username_password_reply->service_callback = callback;
618 username_password_reply->user_data = user_data;
620 err = connman_agent_queue_message(service, message,
621 connman_timeout_input_request(),
622 request_input_login_reply, username_password_reply,
624 if (err < 0 && err != -EBUSY) {
625 DBG("error %d sending agent request", err);
626 dbus_message_unref(message);
627 g_free(username_password_reply);
631 dbus_message_unref(message);
636 struct request_browser_reply_data {
637 struct connman_service *service;
638 browser_authentication_cb_t callback;
642 static void request_browser_reply(DBusMessage *reply, void *user_data)
644 struct request_browser_reply_data *browser_reply_data = user_data;
646 const char *error = NULL;
649 error = CONNMAN_ERROR_INTERFACE ".OperationAborted";
653 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
654 error = dbus_message_get_error_name(reply);
661 browser_reply_data->callback(browser_reply_data->service, result,
662 error, browser_reply_data->user_data);
663 g_free(browser_reply_data);
666 int __connman_agent_request_browser(struct connman_service *service,
667 browser_authentication_cb_t callback,
668 const char *url, void *user_data)
670 struct request_browser_reply_data *browser_reply_data;
671 DBusMessage *message;
672 DBusMessageIter iter;
673 const char *path, *agent_sender, *agent_path;
677 agent = connman_agent_get_info(NULL, &agent_sender, &agent_path);
679 if (!service || !agent || !agent_path || !callback)
685 message = dbus_message_new_method_call(agent_sender, agent_path,
686 CONNMAN_AGENT_INTERFACE,
691 dbus_message_iter_init_append(message, &iter);
693 path = __connman_service_get_path(service);
694 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
696 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &url);
698 browser_reply_data = g_try_new0(struct request_browser_reply_data, 1);
699 if (!browser_reply_data) {
700 dbus_message_unref(message);
704 browser_reply_data->service = service;
705 browser_reply_data->callback = callback;
706 browser_reply_data->user_data = user_data;
708 err = connman_agent_queue_message(service, message,
709 connman_timeout_browser_launch(),
710 request_browser_reply, browser_reply_data,
713 if (err < 0 && err != -EBUSY) {
714 DBG("error %d sending browser request", err);
715 dbus_message_unref(message);
716 g_free(browser_reply_data);
720 dbus_message_unref(message);
725 int __connman_agent_report_peer_error(struct connman_peer *peer,
726 const char *path, const char *error,
727 report_error_cb_t callback,
728 const char *dbus_sender,
731 return connman_agent_report_error_full(peer, path, "ReportPeerError",
732 error, callback, dbus_sender, user_data);
735 static void request_peer_authorization_reply(DBusMessage *reply,
738 struct request_input_reply *auth_reply = user_data;
739 DBusMessageIter iter, dict;
740 const char *error = NULL;
741 bool choice_done = false;
746 error = CONNMAN_ERROR_INTERFACE ".OperationAborted";
750 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
751 error = dbus_message_get_error_name(reply);
755 if (!check_reply_has_dict(reply))
758 dbus_message_iter_init(reply, &iter);
759 dbus_message_iter_recurse(&iter, &dict);
760 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
761 DBusMessageIter entry, value;
763 dbus_message_iter_recurse(&dict, &entry);
764 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
765 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
769 dbus_message_iter_get_basic(&entry, &key);
771 if (g_str_equal(key, "WPS")) {
774 dbus_message_iter_next(&entry);
775 if (dbus_message_iter_get_arg_type(&entry)
776 != DBUS_TYPE_VARIANT) {
777 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
781 dbus_message_iter_recurse(&entry, &value);
782 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_STRING) {
783 error = CONNMAN_ERROR_INTERFACE ".InvalidArguments";
787 dbus_message_iter_get_basic(&value, &wpspin);
790 dbus_message_iter_next(&dict);
793 if (!auth_reply->wps_requested)
797 auth_reply->peer_callback(auth_reply->peer, choice_done, wpspin,
798 error, auth_reply->user_data);
803 int __connman_agent_request_peer_authorization(struct connman_peer *peer,
804 peer_wps_cb_t callback,
806 const char *dbus_sender,
809 struct request_wps_data wps = { .peer = true };
810 const char *path, *agent_sender, *agent_path;
811 struct request_input_reply *auth_reply;
812 DBusMessageIter dict, iter;
813 DBusMessage *message;
817 agent = connman_agent_get_info(dbus_sender, &agent_sender,
819 DBG("agent %p peer %p path %s", agent, peer, agent_path);
821 if (!peer || !agent || !agent_path || !callback)
824 message = dbus_message_new_method_call(agent_sender, agent_path,
825 CONNMAN_AGENT_INTERFACE, "RequestPeerAuthorization");
829 dbus_message_iter_init_append(message, &iter);
831 path = __connman_peer_get_path(peer);
832 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
834 connman_dbus_dict_open(&iter, &dict);
837 connman_dbus_dict_append_dict(&dict, "WPS",
838 request_input_append_wps, &wps);
840 connman_dbus_dict_close(&iter, &dict);
842 auth_reply = g_try_new0(struct request_input_reply, 1);
844 dbus_message_unref(message);
848 auth_reply->peer = peer;
849 auth_reply->peer_callback = callback;
850 auth_reply->wps_requested = wps_requested;
851 auth_reply->user_data = user_data;
853 err = connman_agent_queue_message(peer, message,
854 connman_timeout_input_request(),
855 request_peer_authorization_reply,
857 if (err < 0 && err != -EBUSY) {
858 DBG("error %d sending agent message", err);
859 dbus_message_unref(message);
864 dbus_message_unref(message);