[Bug 69] Generalize SSH_ASKPASS [LONG]

Jim Knoble jmknoble at pobox.com
Tue Apr 8 15:52:08 EST 2003


Steven Doerfler <stevenATlugaruDOTcom> and i seem to have had a
discussion offlist about this.  I'm not sure why i initially took it
offlist (probably thinkographical error).  Regardless, with Steven's
permission, here are excerpts of the discussion.

SUMMARY: Steven didn't realize that there would be an assumed default
         value for the proposed SSH_CONFIRM envariable (namely,
	 ${libexecdir}/ssh-confirm), or that there is for SSH_ASKPASS
	 (${libexecdir}/ssh-askpass).  I didn't realize he didn't
	 realize that.  After enlightenment, we both seem to think that
	 the proposed ssh-confirm/SSH_CONFIRM method is a suitable way
	 for this to proceed.

Anyone who sees something we missed, please speak up.  I plan to begin
work on patches against 3.7-current (i.e., OpenBSD CVS) end of this
week.  The ssh-confirm part of x11-ssh-askpass[*] will follow.

[Sorry about the length; i tried to trim some, but there really wasn't
 that much irrelevant stuff in the discussion....]

__________
[*] http://www.pobox.com/~jmknoble/software/x11-ssh-askpass/

----- Forwarded message from Jim Knoble <jmknoble at pobox.com> -----

Date: Fri, 4 Apr 2003 16:07:47 -0500
From: Jim Knoble <jmknoble at pobox.com>
Subject: Re: [Bug 69] Generalize SSH_ASKPASS
To: Steven Doerfler <steven at lugaru.com>

Circa 2003-04-04 09:48:01 -0500 dixit Steven Doerfler:

: You could retain compatibility without introducing a new program by
: having ssh invoke ssh-askpass with an environment variable hinting
: at the type of request.  For instance, SSH_ASKPASS_PROMPT_HINT=Y
: might indicate that this is a yes/no prompt.
: 
: An ssh-askpass program could decide to show Yes/No buttons when it
: saw such an environment variable setting.  An ssh-askpass program
: would be free to ignore such a hint and always require the user to
: type YES in a text box, so an old ssh-askpass would work with a
: future ssh that supplied an SSH_ASKPASS_PROMPT_HINT, or vice versa.

How is this substantially different from ssh simply calling an
ssh-confirm program directly?

[...]

SSH_ASKPASS_PROMPT_HINT merely creates an extra layer between ssh
(which already knows whether it wants passphrase input or merely
confirmation) and the actual helper programs.  Why make it so complex?

----- End forwarded message -----
----- Forwarded message from Steven Doerfler <steven at lugaru.com> -----

Date: Fri, 04 Apr 2003 18:27:42 -0500
From: Steven Doerfler <steven at lugaru.com>
Subject: Re: [Bug 69] Generalize SSH_ASKPASS
To: Jim Knoble <jmknoble at pobox.com>

At 04:07 PM 4/4/2003 -0500, Jim Knoble wrote:
 [...]
>How is this substantially different from ssh simply calling an
>ssh-confirm program directly?

As the ssh-confirm idea has been proposed, ssh would only call an
ssh-confirm program if the user had set an SSH_CONFIRM environment variable
to point to this new program.

That means users updating to this new version of ssh would discover that to
get the same behavior as before, they now have to install a new program
ssh-confirm and define a new environment variable SSH_CONFIRM to point to
it.  Without that, ssh wouldn't run an external program to ask for
confirmation, as it does now.  So some operations that now pop up an
ssh-askpass window to ask for confirmation would presumably fail instead.

[...]

Even if ssh was clever enough to continue to use an SSH_ASKPASS variable
for confirmation if no SSH_CONFIRM variable was defined, so that updating
ssh wouldn't actually break things, the user would still need to add this
additional SSH_CONFIRM variable to his settings to see the improved behavior.

With what I suggested, the user need do no additional ssh configuration to
get the improved behavior.  It happens automatically as soon as the user
has updated both his ssh and ssh-askpass programs.

>SSH_ASKPASS_PROMPT_HINT merely creates an extra layer between ssh
>(which already knows whether it wants passphrase input or merely
>confirmation) and the actual helper programs.  Why make it so complex?

I think it's simpler than the SSH_CONFIRM approach.  Perhaps I haven't
explained it well, though; I'm not sure what extra layer you mean.

>From the user's point of view, the change I proposed is simpler because the
user doesn't have to engage with it; the two updated programs just
cooperate to produce a more sensible result.  With the SSH_CONFIRM
approach, he does; he has to define a new setting to indicate that he not
only wants passphrase prompts to work sensibly, but he wants sensible
confirmation prompts too.  If he doesn't define the new setting, he gets,
at best, the current "type yes or no and I will replace your response with
asterisks" silliness, and at worst some uses of ssh just fail after updating.

The SSH_ASKPASS_PROMPT_HINT approach would also be simpler from the
developer's point of view.  The change required to ssh would be roughly
three lines long.  First, with either approach, you'd define a new flag so
the confirm() function can tell read_passphrase() it wants confirmation,
not a passphrase.  Then with the SSH_ASKPASS_PROMPT_HINT approach, roughly
one more line is sufficient: a setenv with contents conditioned on the flag
bits.

With the SSH_CONFIRM approach, read_passphrase() would need more
substantial changes.  The simplest method would be to generalize (and
rename) the ssh_askpass() subroutine so it could call either program, then
add new logic to read_passphrase() to look for the new variable and call
the new ssh_askpass() with the right arguments.

Similarly, the changes to all the implementations of the ssh-askpass
program to prompt differently when appropriate would be no more work than
writing a new set of ssh-confirm programs.  And, of course, continuing to
use the existing programs would still work fine under the
SSH_ASKPASS_PROMPT_HINT scheme.

----- End forwarded message -----
----- Forwarded message from Jim Knoble <jmknoble at pobox.com> -----

Date: Mon, 7 Apr 2003 09:48:14 -0400
From: Jim Knoble <jmknoble at pobox.com>
Subject: Re: [Bug 69] Generalize SSH_ASKPASS
To: Steven Doerfler <steven at lugaru.com>

Circa 2003-04-04 18:27:42 -0500 dixit Steven Doerfler:

: As the ssh-confirm idea has been proposed, ssh would only call an
: ssh-confirm program if the user had set an SSH_CONFIRM environment
: variable to point to this new program.

That's certainly not what i meant, whether or not it's what was implied
by what i wrote.  The intent was for ssh-confirm to behave the same way
as ssh-askpass, i.e.:

   char *default_ssh_confirm = "/usr/local/libexec/ssh-confirm"
   char *ssh_confirm = getenv("SSH_CONFIRM");
   if (!ssh_confirm) {
     ssh_confirm = default_ssh_confirm;
   }
   do_ssh_confirm_stuff(ssh_confirm);

Until ssh-confirm programs are available, the default ssh-confirm might
be a simple shell script that runs ssh-askpass:

  #!/bin/sh
  SSH_CONFIRM="${SSH_ASKPASS:- at libexecdir@/ssh-askpass}"
  exec "${SSH_CONFIRM}" "$@"

with the expected substitution for '@libexecdir@'.  Or, if you prefer
something else:

  #!/bin/sh
  ConfirmationDialog() {
    exec xmessage \
      -name 'ssh-confirm' \
      -title 'SSH Confirmation Request' \
      -xrm '*iconName: SSH-Confirm' \
      -center \
      -buttons Yes,No \
      -default No \
      -print \
      "$@"
  }
  if [ $# -eq 0 ]; then
    ConfirmationDialog "<Insert request for confirmation here...>"
  else
    ConfirmationDialog "$@"
  fi

Simple and straightforward.  If you don't like the idea of a shell
script, a simple C program would suffice:

  #include <errno.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <unistd.h>
  char *default_ssh_askpass = "@libexecdir@/ssh-askpass";
  int main(int argc, char **argv) {
    char *ssh_confirm = getenv("SSH_ASKPASS");
    if (!ssh_confirm) {
      ssh_confirm = default_ssh_askpass;
    }
    argv[0] = ssh_confirm;
    if (-1 == execv(ssh_confirm, argv)) {
      fprintf(stderr, "%s: %s\n", ssh_confirm, strerror(errno));
      exit(1);
    }
    /* not reached */
    return(0);
  }

Again, with the expected substitution for '@libexecdir@'.  A similarly
simple program would work for calling xmessage as an interim
confirmation dialog.

: That means users updating to this new version of ssh would discover
: that to get the same behavior as before, they now have to install a
: new program ssh-confirm and define a new environment variable
: SSH_CONFIRM to point to it.
[...]

Nope.  See above.

: Each of the many implementations of ssh-askpass (pure X11, Gtk+,
: MS-Windows, etc.) would mostly likely have to add an ssh-confirm
: program so they could continue to work with this new version of ssh.

Wouldn't have to, but ought to anyway.

[...]

: Even if ssh was clever enough to continue to use an SSH_ASKPASS
: variable for confirmation if no SSH_CONFIRM variable was defined, so
: that updating ssh wouldn't actually break things, the user would
: still need to add this additional SSH_CONFIRM variable to his
: settings to see the improved behavior.

No need.  ssh can be dumb.  The interim default ssh-confirm script can
be smart enough to handle substituting SSH_ASKPASS for SSH_CONFIRM.

: With what I suggested, the user need do no additional ssh
: configuration to get the improved behavior.  It happens
: automatically as soon as the user has updated both his ssh and
: ssh-askpass programs.

Same here, with no additional cruft in between, once ssh-confirm
programs are available.

: >SSH_ASKPASS_PROMPT_HINT merely creates an extra layer [...]
: 
: I think it's simpler than the SSH_CONFIRM approach.  Perhaps I haven't
: explained it well, though; I'm not sure what extra layer you mean.

I mean the extra layer that detects, parses, and acts on
SSH_ASKPASS_PROMPT_HINT.  What you're advocating is:

    ssh needs passphrase ->
        exec either SSH_ASKPASS or ssh-askpass ->
            if SSH_ASKPASS_PROMPT_HINT is set
                if SSH_ASKPASS_PROMPT_HINT caselessly contains 'y'
                   build confirmation dialog
                   display confirmation dialog and react to events
                else
                   build passphrase dialog
                   display passphrase dialog and react to events
                end if
            end if

    ssh needs confirmation ->
        set SSH_ASKPASS_PROMPT_HINT
        exec either SSH_ASKPASS or ssh-askpass ->
            if SSH_ASKPASS_PROMPT_HINT is set
                if SSH_ASKPASS_PROMPT_HINT caselessly contains 'y'
                   build confirmation dialog
                   display confirmation dialog and react to events
                else
                   build passphrase dialog
                   display passphrase dialog and react to events
                end if
            end if

Whereas what i'm advocating is:

    ssh needs passphrase ->
        exec either SSH_ASKPASS or ssh-askpass ->
	    build passphrase dialog
	    display passphrase dialog and react to events

    ssh needs confirmation ->
        exec either SSH_CONFIRM or ssh-confirm ->
	    build confirmation dialog
	    display confirmation dialog and react to events

See the difference?

: >From the user's point of view, the change I proposed is simpler
: because the user doesn't have to engage with it[...].  With the
: SSH_CONFIRM approach, he does; he has to define a new setting to
: indicate that he not only wants passphrase prompts to work sensibly,
: but he wants sensible confirmation prompts too.[...]

Nope ... your arguments center around the misinterpretation that the
environment variable is necessary in order for this to work.  It's not;
it should act the same as the SSH_ASKPASS envariable.

: The SSH_ASKPASS_PROMPT_HINT approach would also be simpler from the
: developer's point of view.  The change required to ssh would be
: roughly three lines long.  First, with either approach, you'd define
: a new flag so the confirm() function can tell read_passphrase() it
: wants confirmation, not a passphrase.  Then with the
: SSH_ASKPASS_PROMPT_HINT approach, roughly one more line is
: sufficient: a setenv with contents conditioned on the flag bits.

And every invocation of read_passphrase that requires confirmation must
also be changed to include the flag.  See also below.

: With the SSH_CONFIRM approach, read_passphrase() would need more
: substantial changes.  The simplest method would be to generalize
: (and rename) the ssh_askpass() subroutine so it could call either
: program, then add new logic to read_passphrase() to look for the new
: variable and call the new ssh_askpass() with the right arguments.

This is not substantially different from the effort you mention above.
Both require changes at the following levels:

    calls to read_passphrase():
      - Add flag meaning "i want confirmation, not a passphrase"

    read_passphrase():
      - Interpret flag meaning "i want confirmation, not a passphrase"
      - Add logic to act on flag.

The only difference is:

    ssh_askpass():
      - generalize to ssh_dialog(envariable_name, default_program)

which is localized and simple.

: Similarly, the changes to all the implementations of the ssh-askpass
: program to prompt differently when appropriate would be no more work
: than writing a new set of ssh-confirm programs.

Not necessarily.  There's quite a bit of "if..then..else" logic
required to stuff both dialogs into one program, unless the programs
are already sufficiently abstracted.  Since i maintain one of them, i
have a well-founded suspicion that they're not so abstracted.

In the case of x11-ssh-askpass, in fact, it would be more
straightforward to create a new source file containing a second main()
for an ssh-confirm program, link it against the other objects
containing low-level and utility routines, and have another program,
than to figure out where the logic needs to be split in order to
"become" ssh-askpass or ssh-confirm.  That logic is moved up the food
chain into ssh, where it belongs.

And even if that turns out not to be the case, i argue that it's also
not significantly more work to write a new ssh-confirm program than it
is to graft it into the relevant flavor of ssh-askpass.

: And, of course, continuing to use the existing programs would still
: work fine under the SSH_ASKPASS_PROMPT_HINT scheme.

They'll still continue to work.

----- End forwarded message -----
----- Forwarded message from Steven Doerfler <steven at lugaru.com> -----

Date: Mon, 07 Apr 2003 11:31:38 -0400
From: Steven Doerfler <steven at lugaru.com>
Subject: Re: [Bug 69] Generalize SSH_ASKPASS
To: Jim Knoble <jmknoble at pobox.com>

At 09:48 AM 4/7/2003 -0400, Jim Knoble wrote:
>That's certainly not what i meant[...].  The intent was for
>ssh-confirm to behave the same way as ssh-askpass, i.e.:

OK, I think I see the problem.  The man page for ssh says it only runs an
ssh-askpass program if there's an SSH_ASKPASS environment variable set (as
well as DISPLAY being set, and other conditions).

    [See ENVIRONMENT -> SSH_ASKPASS in ssh(1).]

I think we agree that it would be bad if ssh-confirm worked that way too,
and didn't run ssh-confirm unless the user added an SSH_CONFIRM environment
variable.  But while the man page says ssh behaves that way, it actually
doesn't, as you pointed out. [...] I hadn't noticed this until now.

As long as ssh-confirm's behavior matches what the ssh code actually does
for ssh-askpass, and not what the man page says it does (and as long as ssh
packagers are careful to include an ssh-confirm script that redirects to
ssh-askpass whenever appropriate when people simply update their ssh), the
main objection I had doesn't apply.  As to which is simpler code-wise, I'll
defer to your judgment.

----- End forwarded message -----
----- Forwarded message from Jim Knoble <jmknoble at pobox.com> -----

Date: Mon, 7 Apr 2003 12:01:46 -0400
From: Jim Knoble <jmknoble at pobox.com>
Subject: Re: [Bug 69] Generalize SSH_ASKPASS
To: Steven Doerfler <steven at lugaru.com>

Circa 2003-04-07 11:31:38 -0400 dixit Steven Doerfler:

: OK, I think I see the problem.  The man page for ssh says it only runs an
: ssh-askpass program if there's an SSH_ASKPASS environment variable set (as
: well as DISPLAY being set, and other conditions).

  [...]
  
Does it really say that?  {Checks...}  Wow.  Looks like the man page
needs changed....

: I think we agree that it would be bad if ssh-confirm worked that way
: too, and didn't run ssh-confirm unless the user added an SSH_CONFIRM
: environment variable.[...]

Confirmed.

: As long as ssh-confirm's behavior matches what the ssh code actually
: does for ssh-askpass, and not what the man page says it does (and as
: long as ssh packagers are careful to include an ssh-confirm script
: that redirects to ssh-askpass whenever appropriate when people
: simply update their ssh)

I would move this even further up the food chain and make the scriptlet
part of OpenSSH proper ... the packagers are the ones liable to replace
the script with the confirmation dialog program, not the other way
around.

: , the main objection I had doesn't apply.

Cool.

[...]

----- End forwarded message -----
----- Forwarded message from Steven Doerfler <steven at lugaru.com> -----

Date: Mon, 07 Apr 2003 12:26:37 -0400
From: Steven Doerfler <steven at lugaru.com>
Subject: Re: [Bug 69] Generalize SSH_ASKPASS
To: Jim Knoble <jmknoble at pobox.com>

At 12:01 PM 4/7/2003 -0400, Jim Knoble wrote:
>I would move this even further up the food chain and make the scriptlet
>part of OpenSSH proper[...].

That sounds like the right way to do it.

[...]

----- End forwarded message -----

-- 
jim knoble  |  jmknoble at pobox.com  |  http://www.pobox.com/~jmknoble/
(GnuPG fingerprint: 31C4:8AAC:F24E:A70C:4000::BBF4:289F:EAA8:1381:1491)
Stop the War on Freedom ... Start the War on Poverty!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 256 bytes
Desc: not available
Url : http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20030408/00a4592e/attachment.bin 


More information about the openssh-unix-dev mailing list