11 #include <sys/socket.h>
13 #include <asm/byteorder.h>
17 #include <pb-config/pb-config.h>
18 #include <talloc/talloc.h>
19 #include <waiter/waiter.h>
21 #include <crypt/crypt.h>
22 #include <i18n/i18n.h>
24 #include "pb-protocol/pb-protocol.h"
25 #include "list/list.h"
27 #include "device-handler.h"
28 #include "discover-server.h"
32 struct discover_server {
34 struct waitset *waitset;
35 struct waiter *waiter;
38 struct device_handler *device_handler;
39 bool restrict_clients;
43 struct discover_server *server;
44 struct list_item list;
45 struct waiter *waiter;
49 struct waiter *auth_waiter;
53 static int server_destructor(void *arg)
55 struct discover_server *server = arg;
58 waiter_remove(server->waiter);
60 if (server->socket >= 0)
61 close(server->socket);
66 static int client_destructor(void *arg)
68 struct client *client = arg;
74 waiter_remove(client->waiter);
76 if (client->auth_waiter)
77 waiter_remove(client->auth_waiter);
79 list_remove(&client->list);
85 static void print_clients(struct discover_server *server)
86 __attribute__((unused));
88 static void print_clients(struct discover_server *server)
90 struct client *client;
92 pb_debug("current clients [%p,%p,%p]:\n",
93 &server->clients.head,
94 server->clients.head.prev,
95 server->clients.head.next);
96 list_for_each_entry(&server->clients, client, list)
97 pb_debug("\t[%p,%p,%p] client: %d\n", &client->list,
98 client->list.prev, client->list.next,
102 static int client_write_message(
103 struct discover_server *server __attribute__((unused)),
104 struct client *client, struct pb_protocol_message *message)
108 if (client->remote_closed)
111 rc = pb_protocol_write_message(client->fd, message);
113 client->remote_closed = true;
118 static int write_device_add_message(struct discover_server *server,
119 struct client *client, const struct device *dev)
121 struct pb_protocol_message *message;
124 len = pb_protocol_device_len(dev);
126 message = pb_protocol_create_message(client,
127 PB_PROTOCOL_ACTION_DEVICE_ADD, len);
131 pb_protocol_serialise_device(dev, message->payload, len);
133 return client_write_message(server, client, message);
136 static int write_boot_option_add_message(struct discover_server *server,
137 struct client *client, const struct boot_option *opt)
139 struct pb_protocol_message *message;
142 len = pb_protocol_boot_option_len(opt);
144 message = pb_protocol_create_message(client,
145 PB_PROTOCOL_ACTION_BOOT_OPTION_ADD, len);
149 pb_protocol_serialise_boot_option(opt, message->payload, len);
151 return client_write_message(server, client, message);
154 static int write_plugin_option_add_message(struct discover_server *server,
155 struct client *client, const struct plugin_option *opt)
157 struct pb_protocol_message *message;
160 len = pb_protocol_plugin_option_len(opt);
162 message = pb_protocol_create_message(client,
163 PB_PROTOCOL_ACTION_PLUGIN_OPTION_ADD, len);
167 pb_protocol_serialise_plugin_option(opt, message->payload, len);
169 return client_write_message(server, client, message);
172 static int write_plugins_remove_message(struct discover_server *server,
173 struct client *client)
175 struct pb_protocol_message *message;
177 message = pb_protocol_create_message(client,
178 PB_PROTOCOL_ACTION_PLUGINS_REMOVE, 0);
182 /* No payload so nothing to serialise */
184 return client_write_message(server, client, message);
187 static int write_device_remove_message(struct discover_server *server,
188 struct client *client, char *dev_id)
190 struct pb_protocol_message *message;
193 len = strlen(dev_id) + sizeof(uint32_t);
195 message = pb_protocol_create_message(client,
196 PB_PROTOCOL_ACTION_DEVICE_REMOVE, len);
200 pb_protocol_serialise_string(message->payload, dev_id);
202 return client_write_message(server, client, message);
205 static int write_boot_status_message(struct discover_server *server,
206 struct client *client, const struct status *status)
208 struct pb_protocol_message *message;
211 len = pb_protocol_boot_status_len(status);
213 message = pb_protocol_create_message(client,
214 PB_PROTOCOL_ACTION_STATUS, len);
218 pb_protocol_serialise_boot_status(status, message->payload, len);
220 return client_write_message(server, client, message);
223 static int write_system_info_message(struct discover_server *server,
224 struct client *client, const struct system_info *sysinfo)
226 struct pb_protocol_message *message;
229 len = pb_protocol_system_info_len(sysinfo);
231 message = pb_protocol_create_message(client,
232 PB_PROTOCOL_ACTION_SYSTEM_INFO, len);
236 pb_protocol_serialise_system_info(sysinfo, message->payload, len);
238 return client_write_message(server, client, message);
241 static int write_config_message(struct discover_server *server,
242 struct client *client, const struct config *config)
244 struct pb_protocol_message *message;
247 len = pb_protocol_config_len(config);
249 message = pb_protocol_create_message(client,
250 PB_PROTOCOL_ACTION_CONFIG, len);
254 pb_protocol_serialise_config(config, message->payload, len);
256 return client_write_message(server, client, message);
259 static int write_authenticate_message(struct discover_server *server,
260 struct client *client)
262 struct pb_protocol_message *message;
263 struct auth_message auth_msg;
266 auth_msg.op = AUTH_MSG_RESPONSE;
267 auth_msg.authenticated = client->can_modify;
269 len = pb_protocol_authenticate_len(&auth_msg);
271 message = pb_protocol_create_message(client,
272 PB_PROTOCOL_ACTION_AUTHENTICATE, len);
276 pb_protocol_serialise_authenticate(&auth_msg, message->payload, len);
278 return client_write_message(server, client, message);
281 static int client_auth_timeout(void *arg)
283 struct client *client = arg;
286 client->auth_waiter = NULL;
287 client->can_modify = false;
289 rc = write_authenticate_message(client->server, client);
291 pb_log("failed to send client auth timeout\n");
296 static int discover_server_handle_auth_message(struct client *client,
297 struct auth_message *auth_msg)
299 struct status *status;
303 status = talloc_zero(client, struct status);
305 switch (auth_msg->op) {
306 case AUTH_MSG_REQUEST:
307 if (!crypt_check_password(auth_msg->password)) {
309 pb_log("Client failed to authenticate\n");
310 status->type = STATUS_ERROR;
311 status->message = talloc_asprintf(status,
312 _("Password incorrect"));
314 client->can_modify = true;
315 rc = write_authenticate_message(client->server,
317 if (client->auth_waiter)
318 waiter_remove(client->auth_waiter);
319 client->auth_waiter = waiter_register_timeout(
320 client->server->waitset,
322 client_auth_timeout, client);
323 pb_log("Client authenticated\n");
324 status->type = STATUS_INFO;
325 status->message = talloc_asprintf(status,
326 _("Authenticated successfully"));
330 if (client->server->restrict_clients) {
331 if (!crypt_check_password(auth_msg->set_password.password)) {
333 pb_log("Wrong password for set request\n");
334 status->type = STATUS_ERROR;
335 status->message = talloc_asprintf(status,
336 _("Password incorrect"));
341 rc = crypt_set_password(auth_msg,
342 auth_msg->set_password.new_password);
344 pb_log("Failed to set password\n");
345 status->type = STATUS_ERROR;
346 status->message = talloc_asprintf(status,
347 _("Error setting password"));
349 if (!auth_msg->set_password.new_password ||
350 !strlen(auth_msg->set_password.new_password)) {
351 platform_set_password("");
352 discover_server_set_auth_mode(client->server,
354 pb_log("Password cleared\n");
356 hash = crypt_get_hash(auth_msg);
357 platform_set_password(hash);
359 discover_server_set_auth_mode(client->server,
362 pb_log("System password changed\n");
363 status->type = STATUS_ERROR;
364 status->message = talloc_asprintf(status,
365 _("Password updated successfully"));
368 case AUTH_MSG_DECRYPT:
369 if (!client->can_modify) {
370 pb_log("Unauthenticated client tried to open encrypted device %s\n",
371 auth_msg->decrypt_dev.device_id);
373 status->type = STATUS_ERROR;
374 status->message = talloc_asprintf(status,
375 _("Must authenticate before opening encrypted device"));
379 device_handler_open_encrypted_dev(client->server->device_handler,
380 auth_msg->decrypt_dev.password,
381 auth_msg->decrypt_dev.device_id);
384 pb_log("%s: unknown op\n", __func__);
390 write_boot_status_message(client->server, client, status);
396 static int discover_server_process_message(void *arg)
398 struct autoboot_option *autoboot_opt;
399 struct pb_protocol_message *message;
400 struct boot_command *boot_command;
401 struct auth_message *auth_msg;
402 struct status *status;
403 struct client *client = arg;
404 struct config *config;
408 message = pb_protocol_read_message(client, client->fd);
416 * If crypt support is enabled, non-authorised clients can only delay
417 * boot, not configure options or change the default boot option.
419 if (!client->can_modify) {
420 switch (message->action) {
421 case PB_PROTOCOL_ACTION_BOOT:
422 boot_command = talloc(client, struct boot_command);
424 rc = pb_protocol_deserialise_boot_command(boot_command,
427 pb_log("%s: no boot command?", __func__);
431 device_handler_boot(client->server->device_handler,
432 client->can_modify, boot_command);
434 case PB_PROTOCOL_ACTION_CANCEL_DEFAULT:
435 device_handler_cancel_default(client->server->device_handler);
437 case PB_PROTOCOL_ACTION_AUTHENTICATE:
438 auth_msg = talloc(client, struct auth_message);
439 rc = pb_protocol_deserialise_authenticate(
442 pb_log("Couldn't parse client's auth request\n");
446 rc = discover_server_handle_auth_message(client,
448 talloc_free(auth_msg);
451 pb_log("non-root client tried to perform action %d\n",
453 status = talloc_zero(client, struct status);
455 status->type = STATUS_ERROR;
456 status->message = talloc_asprintf(status,
457 "Client must run as root to make changes");
458 write_boot_status_message(client->server, client,
466 switch (message->action) {
467 case PB_PROTOCOL_ACTION_BOOT:
468 boot_command = talloc(client, struct boot_command);
470 rc = pb_protocol_deserialise_boot_command(boot_command,
473 pb_log_fn("no boot command?\n");
477 device_handler_boot(client->server->device_handler,
478 client->can_modify, boot_command);
481 case PB_PROTOCOL_ACTION_CANCEL_DEFAULT:
482 device_handler_cancel_default(client->server->device_handler);
485 case PB_PROTOCOL_ACTION_REINIT:
486 device_handler_reinit(client->server->device_handler);
489 case PB_PROTOCOL_ACTION_CONFIG:
490 config = talloc_zero(client, struct config);
492 rc = pb_protocol_deserialise_config(config, message);
494 pb_log_fn("no config?\n");
498 device_handler_update_config(client->server->device_handler,
502 case PB_PROTOCOL_ACTION_ADD_URL:
503 url = pb_protocol_deserialise_string((void *) client, message);
505 device_handler_process_url(client->server->device_handler,
509 case PB_PROTOCOL_ACTION_PLUGIN_INSTALL:
510 url = pb_protocol_deserialise_string((void *) client, message);
512 device_handler_install_plugin(client->server->device_handler,
516 case PB_PROTOCOL_ACTION_TEMP_AUTOBOOT:
517 autoboot_opt = talloc_zero(client, struct autoboot_option);
518 rc = pb_protocol_deserialise_temp_autoboot(autoboot_opt,
521 pb_log("can't parse temporary autoboot message\n");
525 device_handler_apply_temp_autoboot(
526 client->server->device_handler,
530 /* For AUTH_MSG_SET */
531 case PB_PROTOCOL_ACTION_AUTHENTICATE:
532 auth_msg = talloc(client, struct auth_message);
533 rc = pb_protocol_deserialise_authenticate(
536 pb_log("Couldn't parse client's auth request\n");
540 discover_server_handle_auth_message(client, auth_msg);
541 talloc_free(auth_msg);
544 pb_log_fn("invalid action %d\n", message->action);
552 void discover_server_set_auth_mode(struct discover_server *server,
553 bool restrict_clients)
555 struct client *client;
557 server->restrict_clients = restrict_clients;
559 list_for_each_entry(&server->clients, client, list) {
560 client->can_modify = !restrict_clients;
561 write_authenticate_message(server, client);
565 static int discover_server_process_connection(void *arg)
567 struct discover_server *server = arg;
568 struct statuslog_entry *entry;
569 int fd, rc, i, n_devices, n_plugins;
570 struct client *client;
574 /* accept the incoming connection */
575 fd = accept(server->socket, NULL, NULL);
577 pb_log("accept: %s\n", strerror(errno));
581 /* add to our list of clients */
582 client = talloc_zero(server, struct client);
583 list_add(&server->clients, &client->list);
585 talloc_set_destructor(client, client_destructor);
588 client->server = server;
589 client->waiter = waiter_register_io(server->waitset, client->fd,
590 WAIT_IN, discover_server_process_message,
594 * get some info on the connecting process - if the client is being
595 * run as root allow them to make changes
597 if (server->restrict_clients) {
598 len = sizeof(struct ucred);
599 rc = getsockopt(client->fd, SOL_SOCKET, SO_PEERCRED, &ucred,
602 pb_log("Failed to get socket info - restricting client\n");
603 client->can_modify = false;
605 pb_log("Client details: pid: %d, uid: %d, egid: %d\n",
606 ucred.pid, ucred.uid, ucred.gid);
607 client->can_modify = ucred.uid == 0;
610 client->can_modify = true;
612 /* send auth status to client */
613 rc = write_authenticate_message(server, client);
617 /* send sysinfo to client */
618 rc = write_system_info_message(server, client, system_info_get());
622 /* send config to client */
623 rc = write_config_message(server, client, config_get());
627 /* send existing devices to client */
628 n_devices = device_handler_get_device_count(server->device_handler);
629 for (i = 0; i < n_devices; i++) {
630 const struct discover_boot_option *opt;
631 const struct discover_device *device;
633 device = device_handler_get_device(server->device_handler, i);
634 rc = write_device_add_message(server, client, device->device);
638 list_for_each_entry(&device->boot_options, opt, list) {
639 rc = write_boot_option_add_message(server, client,
646 /* send status backlog to client */
647 list_for_each_entry(&server->status, entry, list)
648 write_boot_status_message(server, client, entry->status);
650 /* send installed plugins to client */
651 n_plugins = device_handler_get_plugin_count(server->device_handler);
652 for (i = 0; i < n_plugins; i++) {
653 const struct plugin_option *plugin;
655 plugin = device_handler_get_plugin(server->device_handler, i);
656 write_plugin_option_add_message(server, client, plugin);
662 void discover_server_notify_device_add(struct discover_server *server,
663 struct device *device)
665 struct client *client;
667 list_for_each_entry(&server->clients, client, list)
668 write_device_add_message(server, client, device);
672 void discover_server_notify_boot_option_add(struct discover_server *server,
673 struct boot_option *boot_option)
675 struct client *client;
677 list_for_each_entry(&server->clients, client, list)
678 write_boot_option_add_message(server, client, boot_option);
681 void discover_server_notify_device_remove(struct discover_server *server,
682 struct device *device)
684 struct client *client;
686 list_for_each_entry(&server->clients, client, list)
687 write_device_remove_message(server, client, device->id);
691 void discover_server_notify_boot_status(struct discover_server *server,
692 struct status *status)
694 struct statuslog_entry *entry;
695 struct client *client;
697 /* Duplicate the status struct to add to the backlog */
698 entry = talloc(server, struct statuslog_entry);
700 pb_log("Failed to allocated saved status!\n");
702 entry->status = talloc(entry, struct status);
704 entry->status->type = status->type;
705 entry->status->message = talloc_strdup(entry->status,
707 entry->status->backlog = true;
708 list_add_tail(&server->status, &entry->list);
714 list_for_each_entry(&server->clients, client, list)
715 write_boot_status_message(server, client, status);
718 void discover_server_notify_system_info(struct discover_server *server,
719 const struct system_info *sysinfo)
721 struct client *client;
723 list_for_each_entry(&server->clients, client, list)
724 write_system_info_message(server, client, sysinfo);
727 void discover_server_notify_config(struct discover_server *server,
728 const struct config *config)
730 struct client *client;
732 list_for_each_entry(&server->clients, client, list)
733 write_config_message(server, client, config);
736 void discover_server_notify_plugin_option_add(struct discover_server *server,
737 struct plugin_option *opt)
739 struct client *client;
741 list_for_each_entry(&server->clients, client, list)
742 write_plugin_option_add_message(server, client, opt);
745 void discover_server_notify_plugins_remove(struct discover_server *server)
747 struct client *client;
749 list_for_each_entry(&server->clients, client, list)
750 write_plugins_remove_message(server, client);
753 void discover_server_set_device_source(struct discover_server *server,
754 struct device_handler *handler)
756 server->device_handler = handler;
759 struct discover_server *discover_server_init(struct waitset *waitset)
761 struct discover_server *server;
762 struct sockaddr_un addr;
765 server = talloc(NULL, struct discover_server);
769 server->waiter = NULL;
770 server->waitset = waitset;
771 list_init(&server->clients);
772 list_init(&server->status);
774 unlink(PB_SOCKET_PATH);
776 server->socket = socket(AF_UNIX, SOCK_STREAM, 0);
777 if (server->socket < 0) {
778 pb_log("error creating server socket: %s\n", strerror(errno));
782 talloc_set_destructor(server, server_destructor);
783 addr.sun_family = AF_UNIX;
784 strcpy(addr.sun_path, PB_SOCKET_PATH);
786 if (bind(server->socket, (struct sockaddr *)&addr, sizeof(addr))) {
787 pb_log("error binding server socket: %s\n", strerror(errno));
791 /* Allow all clients to communicate on this socket */
792 group = getgrnam("petitgroup");
794 if (chown(PB_SOCKET_PATH, 0, group->gr_gid))
795 pb_log_fn("Error setting socket ownership: %m\n");
797 if (chmod(PB_SOCKET_PATH, 0660))
798 pb_log_fn("Error setting socket permissions: %m\n");
801 if (listen(server->socket, 8)) {
802 pb_log("server socket listen: %s\n", strerror(errno));
806 server->waiter = waiter_register_io(server->waitset, server->socket,
807 WAIT_IN, discover_server_process_connection, server);
816 void discover_server_destroy(struct discover_server *server)