tty-ask-password-agent.c revision 092c4c437f30bb030deae89cc81109a624898b36
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik This file is part of systemd.
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik Copyright 2010 Lennart Poettering
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik systemd is free software; you can redistribute it and/or modify it
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik under the terms of the GNU Lesser General Public License as published by
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik the Free Software Foundation; either version 2.1 of the License, or
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik (at your option) any later version.
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik systemd is distributed in the hope that it will be useful, but
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik WITHOUT ANY WARRANTY; without even the implied warranty of
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik Lesser General Public License for more details.
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik You should have received a copy of the GNU Lesser General Public License
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik along with systemd; If not, see <http://www.gnu.org/licenses/>.
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvikstatic bool arg_plymouth = false;
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvikstatic bool arg_console = false;
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik if ((notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK)) < 0) {
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik if (inotify_add_watch(notify, flag_file, IN_ATTRIB /* for the link count */) < 0) {
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik if ((fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik strncpy(sa.un.sun_path+1, "/org/freedesktop/plymouthd", sizeof(sa.un.sun_path)-1);
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik log_error("Failed to connect to Plymouth: %m");
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n);
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik if ((k = loop_write(fd, packet, n+1, true)) != n+1) {
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik r = k < 0 ? (int) k : -EIO;
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik sleep_for = (int) ((until - y) / USEC_PER_MSEC);
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik if ((j = poll(pollfd, notify > 0 ? 2 : 1, sleep_for)) < 0) {
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik } else if (j == 0) {
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik if (notify > 0 && pollfd[POLL_INOTIFY].revents != 0)
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik if ((k = read(fd, buffer + p, sizeof(buffer) - p)) <= 0) {
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik /* Hmm, first try with cached
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik * passwords failed, so let's retry
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik * with a normal password request */
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) {
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik if ((k = loop_write(fd, packet, n+1, true)) != n+1) {
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik r = k < 0 ? (int) k : -EIO;
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik /* No password, because UI not shown */
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik } else if (buffer[0] == 2 || buffer[0] == 9) {
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik /* One ore more answers */
381a9b85cf2c73401fc1bff06c2e0d86389a5e88Jorgen Austvik if (!(l = strv_parse_nulstr(buffer + 5, size))) {
71e31fc573ba527f0d2be7929c2cb98037c860ecKnut Anders Hatlen /* Unknown packet */
381a9b85cf2c73401fc1bff06c2e0d86389a5e88Jorgen Austvikstatic int parse_password(const char *filename, char **wall) {
381a9b85cf2c73401fc1bff06c2e0d86389a5e88Jorgen Austvik char *socket_name = NULL, *message = NULL, *packet = NULL;
381a9b85cf2c73401fc1bff06c2e0d86389a5e88Jorgen Austvik unsigned pid = 0;
381a9b85cf2c73401fc1bff06c2e0d86389a5e88Jorgen Austvik { "Ask", "Socket", config_parse_string, 0, &socket_name },
381a9b85cf2c73401fc1bff06c2e0d86389a5e88Jorgen Austvik { "Ask", "NotAfter", config_parse_uint64, 0, ¬_after },
71e31fc573ba527f0d2be7929c2cb98037c860ecKnut Anders Hatlen { "Ask", "Message", config_parse_string, 0, &message },
381a9b85cf2c73401fc1bff06c2e0d86389a5e88Jorgen Austvik { "Ask", "PID", config_parse_unsigned, 0, &pid },
71e31fc573ba527f0d2be7929c2cb98037c860ecKnut Anders Hatlen { "Ask", "AcceptCached", config_parse_bool, 0, &accept_cached },
8d22687fbdc540bd0b4d05fd90d87fb6037f4b9fJorgen Austvik r = config_parse(filename, f, NULL, config_item_table_lookup, (void*) items, true, NULL);
goto finish;
if (!socket_name) {
r = -EBADMSG;
goto finish;
if (not_after > 0) {
goto finish;
if (pid > 0 &&
goto finish;
char *_wall;
pid) < 0) {
r = log_oom();
goto finish;
} sa;
goto finish;
if (arg_plymouth) {
r = -ENOMEM;
char *password;
if (arg_console)
r = tty_fd;
goto finish;
if (arg_console) {
r = -ENOMEM;
goto finish;
goto finish;
r = -errno;
goto finish;
if (sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(socket_name)) < 0) {
r = -errno;
goto finish;
fclose(f);
if (socket_fd >= 0)
static int wall_tty_block(void) {
int fd, r;
return -ENOMEM;
free(p);
if (fd < 0)
return -errno;
return fd;
int fd, k;
free(p);
if (asprintf(&p, "/run/systemd/ask-password-block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0)
free(p);
if (fd < 0)
static int show_passwords(void) {
DIR *d;
return -errno;
char *wall;
r = log_oom();
goto finish;
free(p);
if (wall) {
closedir(d);
static int watch_passwords(void) {
r = -errno;
goto finish;
r = -errno;
goto finish;
r = -errno;
goto finish;
if ((r = show_passwords()) < 0)
r = -errno;
goto finish;
if (notify >= 0)
if (signal_fd >= 0)
if (tty_block_fd >= 0)
static int help(void) {
help();
case ARG_VERSION:
case ARG_LIST:
case ARG_QUERY:
case ARG_WATCH:
case ARG_WALL:
case ARG_PLYMOUTH:
arg_plymouth = true;
case ARG_CONSOLE:
arg_console = true;
return -EINVAL;
return -EINVAL;
help();
return -EINVAL;
log_open();
goto finish;
if (arg_console) {
setsid();
r = watch_passwords();
r = show_passwords();