]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
ask-password: make password echo fully configurable
authorLennart Poettering <lennart@poettering.net>
Thu, 3 Jun 2021 08:41:05 +0000 (10:41 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 3 Jun 2021 09:16:48 +0000 (11:16 +0200)
This adds --visible=yes|no|asterisk which allow controlling the echo of
the password prompt in detail. The existing --echo switch is then made
an alias for --visible=yes (and a shortcut -e added for it too).

man/systemd-ask-password.xml
src/ask-password/ask-password.c

index a92e45058c5740db108334344d2119b07521aa10..0b1137539bba6afbbb3465362db6bb56671c8243 100644 (file)
         to 90s. A timeout of 0 waits indefinitely. </para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--echo=yes|no|masked</option></term>
+
+        <listitem><para>Controls whether to echo user input. Takes a boolean or the special string
+        <literal>masked</literal>, the default being the latter. If enabled the typed characters are echoed
+        literally, which is useful for prompting for usernames and other non-protected data. If disabled the
+        typed characters are not echoed in any form, the user will not get feedback on their input. If set to
+        <literal>masked</literal>, an asterisk (<literal>*</literal>) is echoed for each character
+        typed. In this mode, if the user hits the tabulator key (<literal>↹</literal>), echo is turned
+        off. (Alternatively, if the user hits the backspace key (<literal>⌫</literal>) while no data has
+        been entered otherwise, echo is turned off, too).</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--echo</option></term>
+        <term><option>-e</option></term>
 
-        <listitem><para>Echo the user input instead of masking it.
-        This is useful when using
-        <filename>systemd-ask-password</filename> to query for
-        usernames. </para></listitem>
+        <listitem><para>Equivalent to <option>--echo=yes</option>, see above.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         <listitem><para>Controls whether or not to prefix the query with a
         lock and key emoji (🔐), if the TTY settings permit this. The default
         is <literal>auto</literal>, which defaults to <literal>yes</literal>,
-        unless <option>--echo</option> is given.</para></listitem>
+        unless <option>--echo=yes</option> is given.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 26cf012f018f80188b0e3333d581a2a9901ec73a..fb4b7be4fcbeb6e5196a331d4980f8a33b8033a1 100644 (file)
@@ -45,7 +45,9 @@ static int help(void) {
                "                      Credential name for LoadCredential=/SetCredential=\n"
                "                      credentials\n"
                "     --timeout=SEC    Timeout in seconds\n"
-               "     --echo           Do not mask input (useful for usernames)\n"
+               "     --echo=yes|no|masked\n"
+               "                      Control whether to show password while typing (echo)\n"
+               "  -e --echo           Equivalent to --echo=yes\n"
                "     --emoji=yes|no|auto\n"
                "                      Show a lock and key emoji\n"
                "     --no-tty         Ask question via agent even on TTY\n"
@@ -66,7 +68,6 @@ static int parse_argv(int argc, char *argv[]) {
         enum {
                 ARG_ICON = 0x100,
                 ARG_TIMEOUT,
-                ARG_ECHO,
                 ARG_EMOJI,
                 ARG_NO_TTY,
                 ARG_ACCEPT_CACHED,
@@ -83,7 +84,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "version",       no_argument,       NULL, ARG_VERSION       },
                 { "icon",          required_argument, NULL, ARG_ICON          },
                 { "timeout",       required_argument, NULL, ARG_TIMEOUT       },
-                { "echo",          no_argument,       NULL, ARG_ECHO          },
+                { "echo",          optional_argument, NULL, 'e'               },
                 { "emoji",         required_argument, NULL, ARG_EMOJI         },
                 { "no-tty",        no_argument,       NULL, ARG_NO_TTY        },
                 { "accept-cached", no_argument,       NULL, ARG_ACCEPT_CACHED },
@@ -96,12 +97,14 @@ static int parse_argv(int argc, char *argv[]) {
         };
 
         const char *emoji = NULL;
-        int c;
+        int c, r;
 
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+        /* Note the asymmetry: the long option --echo= allows an optional argument, the short option does
+         * not. */
+        while ((c = getopt_long(argc, argv, "he", options, NULL)) >= 0)
 
                 switch (c) {
 
@@ -116,14 +119,30 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_TIMEOUT:
-                        if (parse_sec(optarg, &arg_timeout) < 0)
-                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                       "Failed to parse --timeout parameter %s",
-                                                       optarg);
+                        r = parse_sec(optarg, &arg_timeout);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse --timeout= parameter: %s", optarg);
+
                         break;
 
-                case ARG_ECHO:
-                        arg_flags |= ASK_PASSWORD_ECHO;
+                case 'e':
+                        if (!optarg) {
+                                /* Short option -e is used, or no argument to long option --echo= */
+                                arg_flags |= ASK_PASSWORD_ECHO;
+                                arg_flags &= ~ASK_PASSWORD_SILENT;
+                        } else if (isempty(optarg) || streq(optarg, "masked"))
+                                /* Empty argument or explicit string "masked" for default behaviour. */
+                                arg_flags &= ~(ASK_PASSWORD_ECHO|ASK_PASSWORD_SILENT);
+                        else {
+                                bool b;
+
+                                r = parse_boolean_argument("--echo=", optarg, &b);
+                                if (r < 0)
+                                        return r;
+
+                                SET_FLAG(arg_flags, ASK_PASSWORD_ECHO, b);
+                                SET_FLAG(arg_flags, ASK_PASSWORD_SILENT, !b);
+                        }
                         break;
 
                 case ARG_EMOJI:
@@ -168,12 +187,12 @@ static int parse_argv(int argc, char *argv[]) {
         if (isempty(emoji) || streq(emoji, "auto"))
                 SET_FLAG(arg_flags, ASK_PASSWORD_HIDE_EMOJI, FLAGS_SET(arg_flags, ASK_PASSWORD_ECHO));
         else {
-                int r;
                 bool b;
 
                 r = parse_boolean_argument("--emoji=", emoji, &b);
                 if (r < 0)
                          return r;
+
                 SET_FLAG(arg_flags, ASK_PASSWORD_HIDE_EMOJI, !b);
         }