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"));
369 pb_log("%s: unknown op\n", __func__);
374 write_boot_status_message(client->server, client, status);
380 static int discover_server_process_message(void *arg)
382 struct autoboot_option *autoboot_opt;
383 struct pb_protocol_message *message;
384 struct boot_command *boot_command;
385 struct auth_message *auth_msg;
386 struct status *status;
387 struct client *client = arg;
388 struct config *config;
392 message = pb_protocol_read_message(client, client->fd);
400 * If crypt support is enabled, non-authorised clients can only delay
401 * boot, not configure options or change the default boot option.
403 if (!client->can_modify) {
404 switch (message->action) {
405 case PB_PROTOCOL_ACTION_BOOT:
406 boot_command = talloc(client, struct boot_command);
408 rc = pb_protocol_deserialise_boot_command(boot_command,
411 pb_log("%s: no boot command?", __func__);
415 device_handler_boot(client->server->device_handler,
416 client->can_modify, boot_command);
418 case PB_PROTOCOL_ACTION_CANCEL_DEFAULT:
419 device_handler_cancel_default(client->server->device_handler);
421 case PB_PROTOCOL_ACTION_AUTHENTICATE:
422 auth_msg = talloc(client, struct auth_message);
423 rc = pb_protocol_deserialise_authenticate(
426 pb_log("Couldn't parse client's auth request\n");
430 rc = discover_server_handle_auth_message(client,
432 talloc_free(auth_msg);
435 pb_log("non-root client tried to perform action %d\n",
437 status = talloc_zero(client, struct status);
439 status->type = STATUS_ERROR;
440 status->message = talloc_asprintf(status,
441 "Client must run as root to make changes");
442 write_boot_status_message(client->server, client,
450 switch (message->action) {
451 case PB_PROTOCOL_ACTION_BOOT:
452 boot_command = talloc(client, struct boot_command);
454 rc = pb_protocol_deserialise_boot_command(boot_command,
457 pb_log_fn("no boot command?\n");
461 device_handler_boot(client->server->device_handler,
462 client->can_modify, boot_command);
465 case PB_PROTOCOL_ACTION_CANCEL_DEFAULT:
466 device_handler_cancel_default(client->server->device_handler);
469 case PB_PROTOCOL_ACTION_REINIT:
470 device_handler_reinit(client->server->device_handler);
473 case PB_PROTOCOL_ACTION_CONFIG:
474 config = talloc_zero(client, struct config);
476 rc = pb_protocol_deserialise_config(config, message);
478 pb_log_fn("no config?\n");
482 device_handler_update_config(client->server->device_handler,
486 case PB_PROTOCOL_ACTION_ADD_URL:
487 url = pb_protocol_deserialise_string((void *) client, message);
489 device_handler_process_url(client->server->device_handler,
493 case PB_PROTOCOL_ACTION_PLUGIN_INSTALL:
494 url = pb_protocol_deserialise_string((void *) client, message);
496 device_handler_install_plugin(client->server->device_handler,
500 case PB_PROTOCOL_ACTION_TEMP_AUTOBOOT:
501 autoboot_opt = talloc_zero(client, struct autoboot_option);
502 rc = pb_protocol_deserialise_temp_autoboot(autoboot_opt,
505 pb_log("can't parse temporary autoboot message\n");
509 device_handler_apply_temp_autoboot(
510 client->server->device_handler,
514 /* For AUTH_MSG_SET */
515 case PB_PROTOCOL_ACTION_AUTHENTICATE:
516 auth_msg = talloc(client, struct auth_message);
517 rc = pb_protocol_deserialise_authenticate(
520 pb_log("Couldn't parse client's auth request\n");
524 rc = discover_server_handle_auth_message(client, auth_msg);
525 talloc_free(auth_msg);
528 pb_log_fn("invalid action %d\n", message->action);
536 void discover_server_set_auth_mode(struct discover_server *server,
537 bool restrict_clients)
539 struct client *client;
541 server->restrict_clients = restrict_clients;
543 list_for_each_entry(&server->clients, client, list) {
544 client->can_modify = !restrict_clients;
545 write_authenticate_message(server, client);
549 static int discover_server_process_connection(void *arg)
551 struct discover_server *server = arg;
552 struct statuslog_entry *entry;
553 int fd, rc, i, n_devices, n_plugins;
554 struct client *client;
558 /* accept the incoming connection */
559 fd = accept(server->socket, NULL, NULL);
561 pb_log("accept: %s\n", strerror(errno));
565 /* add to our list of clients */
566 client = talloc_zero(server, struct client);
567 list_add(&server->clients, &client->list);
569 talloc_set_destructor(client, client_destructor);
572 client->server = server;
573 client->waiter = waiter_register_io(server->waitset, client->fd,
574 WAIT_IN, discover_server_process_message,
578 * get some info on the connecting process - if the client is being
579 * run as root allow them to make changes
581 if (server->restrict_clients) {
582 len = sizeof(struct ucred);
583 rc = getsockopt(client->fd, SOL_SOCKET, SO_PEERCRED, &ucred,
586 pb_log("Failed to get socket info - restricting client\n");
587 client->can_modify = false;
589 pb_log("Client details: pid: %d, uid: %d, egid: %d\n",
590 ucred.pid, ucred.uid, ucred.gid);
591 client->can_modify = ucred.uid == 0;
594 client->can_modify = true;
596 /* send auth status to client */
597 rc = write_authenticate_message(server, client);
601 /* send sysinfo to client */
602 rc = write_system_info_message(server, client, system_info_get());
606 /* send config to client */
607 rc = write_config_message(server, client, config_get());
611 /* send existing devices to client */
612 n_devices = device_handler_get_device_count(server->device_handler);
613 for (i = 0; i < n_devices; i++) {
614 const struct discover_boot_option *opt;
615 const struct discover_device *device;
617 device = device_handler_get_device(server->device_handler, i);
618 rc = write_device_add_message(server, client, device->device);
622 list_for_each_entry(&device->boot_options, opt, list) {
623 rc = write_boot_option_add_message(server, client,
630 /* send status backlog to client */
631 list_for_each_entry(&server->status, entry, list)
632 write_boot_status_message(server, client, entry->status);
634 /* send installed plugins to client */
635 n_plugins = device_handler_get_plugin_count(server->device_handler);
636 for (i = 0; i < n_plugins; i++) {
637 const struct plugin_option *plugin;
639 plugin = device_handler_get_plugin(server->device_handler, i);
640 write_plugin_option_add_message(server, client, plugin);
646 void discover_server_notify_device_add(struct discover_server *server,
647 struct device *device)
649 struct client *client;
651 list_for_each_entry(&server->clients, client, list)
652 write_device_add_message(server, client, device);
656 void discover_server_notify_boot_option_add(struct discover_server *server,
657 struct boot_option *boot_option)
659 struct client *client;
661 list_for_each_entry(&server->clients, client, list)
662 write_boot_option_add_message(server, client, boot_option);
665 void discover_server_notify_device_remove(struct discover_server *server,
666 struct device *device)
668 struct client *client;
670 list_for_each_entry(&server->clients, client, list)
671 write_device_remove_message(server, client, device->id);
675 void discover_server_notify_boot_status(struct discover_server *server,
676 struct status *status)
678 struct statuslog_entry *entry;
679 struct client *client;
681 /* Duplicate the status struct to add to the backlog */
682 entry = talloc(server, struct statuslog_entry);
684 pb_log("Failed to allocated saved status!\n");
686 entry->status = talloc(entry, struct status);
688 entry->status->type = status->type;
689 entry->status->message = talloc_strdup(entry->status,
691 entry->status->backlog = true;
692 list_add_tail(&server->status, &entry->list);
698 list_for_each_entry(&server->clients, client, list)
699 write_boot_status_message(server, client, status);
702 void discover_server_notify_system_info(struct discover_server *server,
703 const struct system_info *sysinfo)
705 struct client *client;
707 list_for_each_entry(&server->clients, client, list)
708 write_system_info_message(server, client, sysinfo);
711 void discover_server_notify_config(struct discover_server *server,
712 const struct config *config)
714 struct client *client;
716 list_for_each_entry(&server->clients, client, list)
717 write_config_message(server, client, config);
720 void discover_server_notify_plugin_option_add(struct discover_server *server,
721 struct plugin_option *opt)
723 struct client *client;
725 list_for_each_entry(&server->clients, client, list)
726 write_plugin_option_add_message(server, client, opt);
729 void discover_server_notify_plugins_remove(struct discover_server *server)
731 struct client *client;
733 list_for_each_entry(&server->clients, client, list)
734 write_plugins_remove_message(server, client);
737 void discover_server_set_device_source(struct discover_server *server,
738 struct device_handler *handler)
740 server->device_handler = handler;
743 struct discover_server *discover_server_init(struct waitset *waitset)
745 struct discover_server *server;
746 struct sockaddr_un addr;
749 server = talloc(NULL, struct discover_server);
753 server->waiter = NULL;
754 server->waitset = waitset;
755 list_init(&server->clients);
756 list_init(&server->status);
758 unlink(PB_SOCKET_PATH);
760 server->socket = socket(AF_UNIX, SOCK_STREAM, 0);
761 if (server->socket < 0) {
762 pb_log("error creating server socket: %s\n", strerror(errno));
766 talloc_set_destructor(server, server_destructor);
767 addr.sun_family = AF_UNIX;
768 strcpy(addr.sun_path, PB_SOCKET_PATH);
770 if (bind(server->socket, (struct sockaddr *)&addr, sizeof(addr))) {
771 pb_log("error binding server socket: %s\n", strerror(errno));
775 /* Allow all clients to communicate on this socket */
776 group = getgrnam("petitgroup");
778 chown(PB_SOCKET_PATH, 0, group->gr_gid);
779 chmod(PB_SOCKET_PATH, 0660);
782 if (listen(server->socket, 8)) {
783 pb_log("server socket listen: %s\n", strerror(errno));
787 server->waiter = waiter_register_io(server->waitset, server->socket,
788 WAIT_IN, discover_server_process_connection, server);
797 void discover_server_destroy(struct discover_server *server)