0

I am surprised about way of working getpass(). I am using it in python, however I am aware of the fact that it is about https://linux.die.net/man/3/getpass call in reality. Moreover, I am aware of the fact that ssh-add uses it as well.

It is not easy to think about from many causes.

    1.

The getpass() function opens /dev/tty (the controlling terminal of the process), outputs the string prompt, turns off echoing, reads one line (the "password"), restores the terminal state and closes /dev/tty again.

What does it mean? It opens new terminal? /dev/tty/ is opened before getpass call?
What does it mean that it restore terminal state?

  1. Why does expect can work with ssh-add or getpass while as echo does not?
    Let's consider:
#getpass.py 
import getpass

password = getpass.getpass()
print password

    [user@host ~]$ python2.7 ~/getpass.py 
    Password: 
    somepassword

It works. Why? I was able to type password from keybord so I guess that it has read from stdin. After all, the promise was about reading password /dev/tty, not stdin.


[user@host ~]$ python2.7 ~/getpass.py # we allow it to wait for password and let check to new bash session
[user@host ~]$ # new bash session
[user@host ~]$ python2.7 ~/getpass.py
[user@host ~]$ pgrep python
21502
[user@host ~]$ ls -al /proc/21502/fd
razem 0
dr-x------ 2 user wheel  0 04-14 17:55 .
dr-xr-xr-x 9 user wheel  0 04-14 17:53 ..
lrwx------ 1 user wheel 64 04-14 17:55 0 -> /dev/pts/6
lrwx------ 1 user wheel 64 04-14 17:55 1 -> /dev/pts/6
lrwx------ 1 user wheel 64 04-14 17:55 2 -> /dev/pts/6
lrwx------ 1 user wheel 64 04-14 17:55 3 -> /dev/tty
[user@host ~]$ echo 'some_password' > /proc/21502/fd/0 #stdin of python process
[user@host ~]$ echo 'some_password' > /proc/21502/fd/3
some_password # it prins some_password here, I know why (driver of `/dev/tty` check which process call it) 

It does not work.
I have no idea how expect tool can work (I checked it and it works). Can anyone explain it, please?

dbs9654
  • 13
  • 3
  • Could you explain what `getpass` change in terminal? Why expect is able to write to `/dev/tty` of another process? Emulation make matter more complex ;) – dbs9654 Apr 14 '20 at 16:09
  • What do you mean, "of another process"? `expect` creates its own TTY, which the child processes it starts inherit and write to. – Charles Duffy Apr 14 '20 at 16:13

1 Answers1

0

Why?

expect acts as a terminal program. As such, it allocates a pseudoterminal (a PTY), and sets that as the active terminal for programs it starts. On Linux, this is done with openpty().

Thus, software which (like getpass) interact directly with the terminal instead of going through stdout and stderr are handled by expect.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Is `expect` like `terminator` ? – dbs9654 Apr 14 '20 at 16:12
  • Insofar as they both create PTYs that the programs run within them interact with, yes. – Charles Duffy Apr 14 '20 at 16:13
  • If you want to see a much simpler program that does the same thing, take a look at [EmPTY](http://empty.sf.net). – Charles Duffy Apr 14 '20 at 16:15
  • When I start `terminator` or `expect` it talk to `kernel`: give me a pseudo terminal (`/dev/pts`) device ? – dbs9654 Apr 14 '20 at 16:16
  • Yes. See the source of EmPTY at https://github.com/ierton/empty/blob/master/empty.c, or any of the other programs mentioned; in particular, the use of [`openpty`](http://man7.org/linux/man-pages/man3/openpty.3.html) – Charles Duffy Apr 14 '20 at 16:17
  • So I understand it like: – dbs9654 Apr 14 '20 at 16:19
  • > I am `expect` and I will allocate some pseudoterminal. Now, all processes executed from me will be started with `stdin/stdout/stderr` attached to this pseudoterminal. Yeah? – dbs9654 Apr 14 '20 at 16:21
  • Yes, *and* when they open `/dev/tty` to talk to the terminal directly (like `getpass` does), that also goes to the pseudoterminal. – Charles Duffy Apr 14 '20 at 16:22
  • What does it mean directly? Without `pts`? – dbs9654 Apr 14 '20 at 16:23
  • Does terminals are property of process? I know that `stdin,stdout,stderr` are some property of process. However, process is aware of being attached to some terminal? – dbs9654 Apr 14 '20 at 16:26
  • In other words, `sendline` is about `write` to some descriptor. From what, `expect` know where to write? – dbs9654 Apr 14 '20 at 16:34
  • Yes, a process has a "controlling terminal", which is indeed a property thereof. `/dev/tty` refers to whichever terminal is the controlling terminal of a given process. – Charles Duffy Apr 14 '20 at 16:35
  • But no, `write` doesn't refer to it. `write` is passed a file descriptor number, which it looks up in the FD table. It's when opening `/dev/tty` that the controlling terminal is looked up and used to generate a file descriptor that looks at it; when `write` is called, that work is already done. – Charles Duffy Apr 14 '20 at 16:36
  • so `getpass` call can change controlling terminal? I understand that `getpass` read password from `/dev/tty`. – dbs9654 Apr 14 '20 at 16:52
  • I never said that getpass can change the controlling terminal. `expect` can change the controlling terminal. Correct, getpass reads from `/dev/tty`. – Charles Duffy Apr 14 '20 at 17:14
  • Is it possible to deal with passing password to `getpass()` without `expect` like tools? – dbs9654 Apr 14 '20 at 17:21
  • There's a long answer (basically, "yes, if you do things that are even more invasive / even less portable"), but the short answer is "no". Anyhow, it's not something you should be trying to do in the first place; depending on the details of the use case, there's generally a better-practice alternative somewhere. – Charles Duffy Apr 14 '20 at 17:50