ask-password.c revision 21bc923aa35d455cdef1607eb7022608c705c9f3
d657c51f14601d0235434ffb78cf6ac0f27cc83cLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
220a21d38f675eb835f5758e3d23e896573aa5eaLennart Poettering
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering/***
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering This file is part of systemd.
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering Copyright 2010 Lennart Poettering
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering systemd is free software; you can redistribute it and/or modify it
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering under the terms of the GNU General Public License as published by
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering the Free Software Foundation; either version 2 of the License, or
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering (at your option) any later version.
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering systemd is distributed in the hope that it will be useful, but
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering General Public License for more details.
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering You should have received a copy of the GNU General Public License
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering***/
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <sys/socket.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <sys/poll.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <sys/types.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <assert.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <string.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <errno.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <unistd.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <fcntl.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <sys/un.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <sys/stat.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <sys/signalfd.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <getopt.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <termios.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <limits.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include <stddef.h>
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include "log.h"
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include "macro.h"
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include "util.h"
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include "strv.h"
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering#include "ask-password-api.h"
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poetteringstatic const char *arg_icon = NULL;
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poetteringstatic const char *arg_message = NULL;
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poetteringstatic bool arg_use_tty = true;
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poetteringstatic usec_t arg_timeout = 60 * USEC_PER_SEC;
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poetteringstatic bool arg_accept_cached = false;
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poetteringstatic bool arg_multiple = false;
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poetteringstatic int help(void) {
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering printf("%s [OPTIONS...] MESSAGE\n\n"
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering "Query the user for a system passphrase, via the TTY or an UI agent.\n\n"
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering " -h --help Show this help\n"
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering " --icon=NAME Icon name\n"
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering " --timeout=SEC Timeout in sec\n"
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering " --no-tty Ask question via agent even on TTY\n"
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering " --accept-cached Accept cached passwords\n"
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering " --multiple List multiple passwords if available\n",
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering program_invocation_short_name);
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering return 0;
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering}
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poettering
c4f1b86299c4ce2a62ce845bc48f2794f5459762Lennart Poetteringstatic int parse_argv(int argc, char *argv[]) {
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering enum {
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering ARG_ICON = 0x100,
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering ARG_TIMEOUT,
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering ARG_NO_TTY,
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering ARG_ACCEPT_CACHED,
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering ARG_MULTIPLE
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering };
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering static const struct option options[] = {
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering { "help", no_argument, NULL, 'h' },
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering { "icon", required_argument, NULL, ARG_ICON },
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering { "timeout", required_argument, NULL, ARG_TIMEOUT },
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering { "no-tty", no_argument, NULL, ARG_NO_TTY },
d1f9edafe7b832c507931640f32069d001916b0eLennart Poettering { "accept-cached", no_argument, NULL, ARG_ACCEPT_CACHED },
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering { "multiple", no_argument, NULL, ARG_MULTIPLE },
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering { NULL, 0, NULL, 0 }
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering };
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering int c;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering assert(argc >= 0);
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering assert(argv);
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering switch (c) {
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering case 'h':
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering help();
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering return 0;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering case ARG_ICON:
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering arg_icon = optarg;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering break;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering case ARG_TIMEOUT:
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering if (parse_usec(optarg, &arg_timeout) < 0 || arg_timeout <= 0) {
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering log_error("Failed to parse --timeout parameter %s", optarg);
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering return -EINVAL;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering }
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering break;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering case ARG_NO_TTY:
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering arg_use_tty = false;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering break;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering case ARG_ACCEPT_CACHED:
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering arg_accept_cached = true;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering break;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering case ARG_MULTIPLE:
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering arg_multiple = true;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering break;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering case '?':
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering return -EINVAL;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering default:
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering log_error("Unknown option code %c", c);
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering return -EINVAL;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering }
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering }
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering if (optind != argc-1) {
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering help();
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering return -EINVAL;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering }
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering arg_message = argv[optind];
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering return 1;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering}
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poetteringint main(int argc, char *argv[]) {
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering int r;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering log_parse_environment();
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering log_open();
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering if ((r = parse_argv(argc, argv)) <= 0)
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering goto finish;
91ac74250149a29122b2291c5393dec4592430d4Kay Sievers
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering if (arg_use_tty && isatty(STDIN_FILENO)) {
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering char *password = NULL;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering if ((r = ask_password_tty(arg_message, now(CLOCK_MONOTONIC) + arg_timeout, NULL, &password)) >= 0) {
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering puts(password);
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering free(password);
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering }
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering } else {
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering char **l;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering if ((r = ask_password_agent(arg_message, arg_icon, now(CLOCK_MONOTONIC) + arg_timeout, arg_accept_cached, &l)) >= 0) {
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering char **p;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering STRV_FOREACH(p, l) {
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering puts(*p);
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering if (!arg_multiple)
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering break;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering }
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering strv_free(l);
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering }
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering }
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poetteringfinish:
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering}
b5b4c94a67d90891a0225af0e08cf45dbc329377Lennart Poettering