sapling/eden/scm/tests/test-fb-hgext-sshaskpass.py

50 lines
1.1 KiB
Python
Raw Normal View History

from __future__ import absolute_import
sshaskpass: enable ssh to ask password if running with chg Summary: During chg pull or push over ssh, ssh is started by chgserver which does not have a controlling tty. Therefore the ssh process won't be able to ask for passwords interactively. This is actually a hard issue because an unprivileged process without a ctty cannot attach to a ctty of another process. The discussion at upstream tends to make it clear it's part of limitations of chg. Therefore if we decide to workaround it, it has to live outside core, thus fb-hgext. GUI ssh-askpass is actually a good and clean choice. See D3510178 and D3515604. However, they are for OS X but not Linux. This diff is a very hacky solution to make ssh-askpass works in terminal. It starts a "tty server" providing tty I/O fds and set `SSH_ASKPASS` to use a custom script talking to the "tty server". Test Plan: Run the new test. Start a sshd locally and try: ``` $ hg push ssh://root@localhost/tmp pushing to ssh://root@localhost/tmp root@localhost's password: remote: Permission denied (publickey,password). abort: no suitable response from remote hg! $ chg push ssh://root@localhost/tmp pushing to ssh://root@localhost/tmp ==== SSH Authenticating ==== root@localhost's password: remote: Permission denied (publickey,password). abort: no suitable response from remote hg! ``` Reviewers: #mercurial, ttung, mpm Reviewed By: mpm Subscribers: durham, mpm, mjpieters Differential Revision: https://phabricator.intern.facebook.com/D3577509 Tasks: 12029680 Signature: t1:3577509:1469467700:cd93565bd47e535bb4cb41fcdaa39e45dddfae28
2016-07-17 22:35:34 +03:00
import os
import signal
sshaskpass: enable ssh to ask password if running with chg Summary: During chg pull or push over ssh, ssh is started by chgserver which does not have a controlling tty. Therefore the ssh process won't be able to ask for passwords interactively. This is actually a hard issue because an unprivileged process without a ctty cannot attach to a ctty of another process. The discussion at upstream tends to make it clear it's part of limitations of chg. Therefore if we decide to workaround it, it has to live outside core, thus fb-hgext. GUI ssh-askpass is actually a good and clean choice. See D3510178 and D3515604. However, they are for OS X but not Linux. This diff is a very hacky solution to make ssh-askpass works in terminal. It starts a "tty server" providing tty I/O fds and set `SSH_ASKPASS` to use a custom script talking to the "tty server". Test Plan: Run the new test. Start a sshd locally and try: ``` $ hg push ssh://root@localhost/tmp pushing to ssh://root@localhost/tmp root@localhost's password: remote: Permission denied (publickey,password). abort: no suitable response from remote hg! $ chg push ssh://root@localhost/tmp pushing to ssh://root@localhost/tmp ==== SSH Authenticating ==== root@localhost's password: remote: Permission denied (publickey,password). abort: no suitable response from remote hg! ``` Reviewers: #mercurial, ttung, mpm Reviewed By: mpm Subscribers: durham, mpm, mjpieters Differential Revision: https://phabricator.intern.facebook.com/D3577509 Tasks: 12029680 Signature: t1:3577509:1469467700:cd93565bd47e535bb4cb41fcdaa39e45dddfae28
2016-07-17 22:35:34 +03:00
import sys
# Make sure we use sshaskpass.py in this repo, unaffected by PYTHONPATH
from edenscm.hgext import sshaskpass
from edenscm.mercurial import error
from testutil.dott import feature
feature.require(["py2"])
sshaskpass: enable ssh to ask password if running with chg Summary: During chg pull or push over ssh, ssh is started by chgserver which does not have a controlling tty. Therefore the ssh process won't be able to ask for passwords interactively. This is actually a hard issue because an unprivileged process without a ctty cannot attach to a ctty of another process. The discussion at upstream tends to make it clear it's part of limitations of chg. Therefore if we decide to workaround it, it has to live outside core, thus fb-hgext. GUI ssh-askpass is actually a good and clean choice. See D3510178 and D3515604. However, they are for OS X but not Linux. This diff is a very hacky solution to make ssh-askpass works in terminal. It starts a "tty server" providing tty I/O fds and set `SSH_ASKPASS` to use a custom script talking to the "tty server". Test Plan: Run the new test. Start a sshd locally and try: ``` $ hg push ssh://root@localhost/tmp pushing to ssh://root@localhost/tmp root@localhost's password: remote: Permission denied (publickey,password). abort: no suitable response from remote hg! $ chg push ssh://root@localhost/tmp pushing to ssh://root@localhost/tmp ==== SSH Authenticating ==== root@localhost's password: remote: Permission denied (publickey,password). abort: no suitable response from remote hg! ``` Reviewers: #mercurial, ttung, mpm Reviewed By: mpm Subscribers: durham, mpm, mjpieters Differential Revision: https://phabricator.intern.facebook.com/D3577509 Tasks: 12029680 Signature: t1:3577509:1469467700:cd93565bd47e535bb4cb41fcdaa39e45dddfae28
2016-07-17 22:35:34 +03:00
if not sys.platform.startswith("linux"):
sys.stderr.write("this test only supports linux\n")
sys.exit(80)
sshaskpass: enable ssh to ask password if running with chg Summary: During chg pull or push over ssh, ssh is started by chgserver which does not have a controlling tty. Therefore the ssh process won't be able to ask for passwords interactively. This is actually a hard issue because an unprivileged process without a ctty cannot attach to a ctty of another process. The discussion at upstream tends to make it clear it's part of limitations of chg. Therefore if we decide to workaround it, it has to live outside core, thus fb-hgext. GUI ssh-askpass is actually a good and clean choice. See D3510178 and D3515604. However, they are for OS X but not Linux. This diff is a very hacky solution to make ssh-askpass works in terminal. It starts a "tty server" providing tty I/O fds and set `SSH_ASKPASS` to use a custom script talking to the "tty server". Test Plan: Run the new test. Start a sshd locally and try: ``` $ hg push ssh://root@localhost/tmp pushing to ssh://root@localhost/tmp root@localhost's password: remote: Permission denied (publickey,password). abort: no suitable response from remote hg! $ chg push ssh://root@localhost/tmp pushing to ssh://root@localhost/tmp ==== SSH Authenticating ==== root@localhost's password: remote: Permission denied (publickey,password). abort: no suitable response from remote hg! ``` Reviewers: #mercurial, ttung, mpm Reviewed By: mpm Subscribers: durham, mpm, mjpieters Differential Revision: https://phabricator.intern.facebook.com/D3577509 Tasks: 12029680 Signature: t1:3577509:1469467700:cd93565bd47e535bb4cb41fcdaa39e45dddfae28
2016-07-17 22:35:34 +03:00
# stdin, stderr have to be tty to run test
pid, master = os.forkpty()
if pid:
# parent, test some I/O
os.write(master, "(input)\n")
with os.fdopen(master, "r") as f:
sys.stdout.write("pty receives: %r" % f.read())
sshaskpass: enable ssh to ask password if running with chg Summary: During chg pull or push over ssh, ssh is started by chgserver which does not have a controlling tty. Therefore the ssh process won't be able to ask for passwords interactively. This is actually a hard issue because an unprivileged process without a ctty cannot attach to a ctty of another process. The discussion at upstream tends to make it clear it's part of limitations of chg. Therefore if we decide to workaround it, it has to live outside core, thus fb-hgext. GUI ssh-askpass is actually a good and clean choice. See D3510178 and D3515604. However, they are for OS X but not Linux. This diff is a very hacky solution to make ssh-askpass works in terminal. It starts a "tty server" providing tty I/O fds and set `SSH_ASKPASS` to use a custom script talking to the "tty server". Test Plan: Run the new test. Start a sshd locally and try: ``` $ hg push ssh://root@localhost/tmp pushing to ssh://root@localhost/tmp root@localhost's password: remote: Permission denied (publickey,password). abort: no suitable response from remote hg! $ chg push ssh://root@localhost/tmp pushing to ssh://root@localhost/tmp ==== SSH Authenticating ==== root@localhost's password: remote: Permission denied (publickey,password). abort: no suitable response from remote hg! ``` Reviewers: #mercurial, ttung, mpm Reviewed By: mpm Subscribers: durham, mpm, mjpieters Differential Revision: https://phabricator.intern.facebook.com/D3577509 Tasks: 12029680 Signature: t1:3577509:1469467700:cd93565bd47e535bb4cb41fcdaa39e45dddfae28
2016-07-17 22:35:34 +03:00
os.waitpid(pid, 0)
sys.exit(0)
sigterm = getattr(signal, "SIGTERM", None)
if sigterm:
def catchterm(*args):
raise error.SignalInterrupt
signal.signal(sigterm, catchterm)
sshaskpass: enable ssh to ask password if running with chg Summary: During chg pull or push over ssh, ssh is started by chgserver which does not have a controlling tty. Therefore the ssh process won't be able to ask for passwords interactively. This is actually a hard issue because an unprivileged process without a ctty cannot attach to a ctty of another process. The discussion at upstream tends to make it clear it's part of limitations of chg. Therefore if we decide to workaround it, it has to live outside core, thus fb-hgext. GUI ssh-askpass is actually a good and clean choice. See D3510178 and D3515604. However, they are for OS X but not Linux. This diff is a very hacky solution to make ssh-askpass works in terminal. It starts a "tty server" providing tty I/O fds and set `SSH_ASKPASS` to use a custom script talking to the "tty server". Test Plan: Run the new test. Start a sshd locally and try: ``` $ hg push ssh://root@localhost/tmp pushing to ssh://root@localhost/tmp root@localhost's password: remote: Permission denied (publickey,password). abort: no suitable response from remote hg! $ chg push ssh://root@localhost/tmp pushing to ssh://root@localhost/tmp ==== SSH Authenticating ==== root@localhost's password: remote: Permission denied (publickey,password). abort: no suitable response from remote hg! ``` Reviewers: #mercurial, ttung, mpm Reviewed By: mpm Subscribers: durham, mpm, mjpieters Differential Revision: https://phabricator.intern.facebook.com/D3577509 Tasks: 12029680 Signature: t1:3577509:1469467700:cd93565bd47e535bb4cb41fcdaa39e45dddfae28
2016-07-17 22:35:34 +03:00
# child, start a ttyserver and do some I/O
ttysrvpid, sockpath = sshaskpass._startttyserver()
try:
r, w = sshaskpass._receivefds(sockpath)
with os.fdopen(r) as f:
line = f.readline()
os.write(w, "client receives: " + line)
sshaskpass: enable ssh to ask password if running with chg Summary: During chg pull or push over ssh, ssh is started by chgserver which does not have a controlling tty. Therefore the ssh process won't be able to ask for passwords interactively. This is actually a hard issue because an unprivileged process without a ctty cannot attach to a ctty of another process. The discussion at upstream tends to make it clear it's part of limitations of chg. Therefore if we decide to workaround it, it has to live outside core, thus fb-hgext. GUI ssh-askpass is actually a good and clean choice. See D3510178 and D3515604. However, they are for OS X but not Linux. This diff is a very hacky solution to make ssh-askpass works in terminal. It starts a "tty server" providing tty I/O fds and set `SSH_ASKPASS` to use a custom script talking to the "tty server". Test Plan: Run the new test. Start a sshd locally and try: ``` $ hg push ssh://root@localhost/tmp pushing to ssh://root@localhost/tmp root@localhost's password: remote: Permission denied (publickey,password). abort: no suitable response from remote hg! $ chg push ssh://root@localhost/tmp pushing to ssh://root@localhost/tmp ==== SSH Authenticating ==== root@localhost's password: remote: Permission denied (publickey,password). abort: no suitable response from remote hg! ``` Reviewers: #mercurial, ttung, mpm Reviewed By: mpm Subscribers: durham, mpm, mjpieters Differential Revision: https://phabricator.intern.facebook.com/D3577509 Tasks: 12029680 Signature: t1:3577509:1469467700:cd93565bd47e535bb4cb41fcdaa39e45dddfae28
2016-07-17 22:35:34 +03:00
finally:
sshaskpass._killprocess(ttysrvpid)
os.unlink(sockpath)