issue #429: teach sudo about every know i18n password string.
This commit is contained in:
parent
960e505f07
commit
6e9f8e829e
|
@ -0,0 +1,40 @@
|
|||
|
||||
# issue #429: tool for extracting keys out of message catalogs and turning them
|
||||
# into the big gob of base64 as used in mitogen/sudo.py
|
||||
#
|
||||
# Usage:
|
||||
# - apt-get source libpam0g
|
||||
# - cd */po/
|
||||
# - python ~/pogrep.py "Password: "
|
||||
|
||||
import sys
|
||||
import shlex
|
||||
import glob
|
||||
|
||||
|
||||
last_word = None
|
||||
|
||||
for path in glob.glob('*.po'):
|
||||
for line in open(path):
|
||||
bits = shlex.split(line, comments=True)
|
||||
if not bits:
|
||||
continue
|
||||
|
||||
word = bits[0]
|
||||
if len(bits) < 2 or not word:
|
||||
continue
|
||||
|
||||
rest = bits[1]
|
||||
if not rest:
|
||||
continue
|
||||
|
||||
if last_word == 'msgid' and word == 'msgstr':
|
||||
if last_rest == sys.argv[1]:
|
||||
thing = rest.rstrip(': ').decode('utf-8').lower().encode('utf-8').encode('base64').rstrip()
|
||||
print ' %-60s # %s' % (repr(thing)+',', path)
|
||||
|
||||
last_word = word
|
||||
last_rest = rest
|
||||
|
||||
#ag -A 1 'msgid "Password: "'|less | grep msgstr | grep -v '""'|cut -d'"' -f2|cut -d'"' -f1| tr -d :
|
||||
|
|
@ -26,8 +26,10 @@
|
|||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import base64
|
||||
import logging
|
||||
import optparse
|
||||
import re
|
||||
|
||||
import mitogen.core
|
||||
import mitogen.parent
|
||||
|
@ -35,6 +37,73 @@ from mitogen.core import b
|
|||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# These are base64-encoded UTF-8 as our existing minifier/module server
|
||||
# struggles with Unicode Python source in some (forgotten) circumstances.
|
||||
PASSWORD_PROMPTS = [
|
||||
'cGFzc3dvcmQ=', # english
|
||||
'bG96aW5rYQ==', # sr@latin.po
|
||||
'44OR44K544Ov44O844OJ', # ja.po
|
||||
'4Kaq4Ka+4Ka44KaT4Kef4Ka+4Kaw4KeN4Kah', # bn.po
|
||||
'2YPZhNmF2Kkg2KfZhNiz2LE=', # ar.po
|
||||
'cGFzYWhpdHph', # eu.po
|
||||
'0L/QsNGA0L7Qu9GM', # uk.po
|
||||
'cGFyb29s', # et.po
|
||||
'c2FsYXNhbmE=', # fi.po
|
||||
'4Kiq4Ki+4Ki44Ki14Kiw4Kih', # pa.po
|
||||
'Y29udHJhc2lnbm8=', # ia.po
|
||||
'Zm9jYWwgZmFpcmU=', # ga.po
|
||||
'16HXodee15Q=', # he.po
|
||||
'4Kqq4Kq+4Kq44Kq14Kqw4KuN4Kqh', # gu.po
|
||||
'0L/QsNGA0L7Qu9Cw', # bg.po
|
||||
'4Kyq4K2N4Kyw4Kys4K2H4Ky2IOCsuOCsmeCtjeCsleCth+CspA==', # or.po
|
||||
'4K6V4K6f4K614K+B4K6a4K+N4K6a4K+K4K6y4K+N', # ta.po
|
||||
'cGFzc3dvcnQ=', # de.po
|
||||
'7JWU7Zi4', # ko.po
|
||||
'0LvQvtC30LjQvdC60LA=', # sr.po
|
||||
'beG6rXQga2jhuql1', # vi.po
|
||||
'c2VuaGE=', # pt_BR.po
|
||||
'cGFzc3dvcmQ=', # it.po
|
||||
'aGVzbG8=', # cs.po
|
||||
'5a+G56K877ya', # zh_TW.po
|
||||
'aGVzbG8=', # sk.po
|
||||
'4LC44LCC4LCV4LGH4LCk4LCq4LCm4LCu4LGB', # te.po
|
||||
'0L/QsNGA0L7Qu9GM', # kk.po
|
||||
'aGFzxYJv', # pl.po
|
||||
'Y29udHJhc2VueWE=', # ca.po
|
||||
'Y29udHJhc2XDsWE=', # es.po
|
||||
'4LSF4LSf4LSv4LS+4LSz4LS14LS+4LSV4LWN4LSV4LWN', # ml.po
|
||||
'c2VuaGE=', # pt.po
|
||||
'5a+G56CB77ya', # zh_CN.po
|
||||
'4KSX4KWB4KSq4KWN4KSk4KS24KSs4KWN4KSm', # mr.po
|
||||
'bMO2c2Vub3Jk', # sv.po
|
||||
'4YOe4YOQ4YOg4YOd4YOa4YOY', # ka.po
|
||||
'4KS24KSs4KWN4KSm4KSV4KWC4KSf', # hi.po
|
||||
'YWRnYW5nc2tvZGU=', # da.po
|
||||
'4La74LeE4LeD4LeK4La04Lav4La6', # si.po
|
||||
'cGFzc29yZA==', # nb.po
|
||||
'd2FjaHR3b29yZA==', # nl.po
|
||||
'4Kaq4Ka+4Ka44KaT4Kef4Ka+4Kaw4KeN4Kah', # bn_IN.po
|
||||
'cGFyb2xh', # tr.po
|
||||
'4LKX4LOB4LKq4LON4LKk4LKq4LKm', # kn.po
|
||||
'c2FuZGk=', # id.po
|
||||
'0L/QsNGA0L7Qu9GM', # ru.po
|
||||
'amVsc3rDsw==', # hu.po
|
||||
'bW90IGRlIHBhc3Nl', # fr.po
|
||||
'aXBoYXNpd2VkaQ==', # zu.po
|
||||
'4Z6W4Z624Z6A4Z+S4Z6Z4Z6f4Z6Y4Z+S4Z6E4Z624Z6P4Z+LwqDhn5Y=', # km.po
|
||||
'4KaX4KeB4Kaq4KeN4Kak4Ka24Kas4KeN4Kam', # as.po
|
||||
]
|
||||
|
||||
|
||||
PASSWORD_PROMPT_RE = re.compile(
|
||||
u'|'.join(
|
||||
base64.b64decode(s).decode('utf-8')
|
||||
for s in PASSWORD_PROMPTS
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
PASSWORD_PROMPT = b('password')
|
||||
SUDO_OPTIONS = [
|
||||
#(False, 'bool', '--askpass', '-A')
|
||||
|
@ -170,11 +239,15 @@ class Stream(mitogen.parent.Stream):
|
|||
password_sent = False
|
||||
|
||||
for buf in it:
|
||||
LOG.debug('%r: received %r', self, buf)
|
||||
LOG.debug('%s: received %r', self.name, buf)
|
||||
if buf.endswith(self.EC0_MARKER):
|
||||
self._ec0_received()
|
||||
return
|
||||
elif PASSWORD_PROMPT in buf.lower():
|
||||
|
||||
match = PASSWORD_PROMPT_RE.search(buf.decode('utf-8').lower())
|
||||
if match is not None:
|
||||
LOG.debug('%s: matched password prompt %r',
|
||||
self.name, match.group(0))
|
||||
if self.password is None:
|
||||
raise PasswordError(self.password_required_msg)
|
||||
if password_sent:
|
||||
|
|
|
@ -56,5 +56,46 @@ class ConstructorTest(testlib.RouterMixin, testlib.TestCase):
|
|||
])
|
||||
|
||||
|
||||
class NonEnglishPromptTest(testlib.DockerMixin, testlib.TestCase):
|
||||
# Only mitogen/debian-test has a properly configured sudo.
|
||||
mitogen_test_distro = 'debian'
|
||||
|
||||
def test_password_required(self):
|
||||
ssh = self.docker_ssh(
|
||||
username='mitogen__has_sudo',
|
||||
password='has_sudo_password',
|
||||
)
|
||||
ssh.call(os.putenv, 'LANGUAGE', 'fr')
|
||||
ssh.call(os.putenv, 'LC_ALL', 'fr_FR.UTF-8')
|
||||
e = self.assertRaises(mitogen.core.StreamError,
|
||||
lambda: self.router.sudo(via=ssh)
|
||||
)
|
||||
self.assertTrue(mitogen.sudo.Stream.password_required_msg in str(e))
|
||||
|
||||
def test_password_incorrect(self):
|
||||
ssh = self.docker_ssh(
|
||||
username='mitogen__has_sudo',
|
||||
password='has_sudo_password',
|
||||
)
|
||||
ssh.call(os.putenv, 'LANGUAGE', 'fr')
|
||||
ssh.call(os.putenv, 'LC_ALL', 'fr_FR.UTF-8')
|
||||
e = self.assertRaises(mitogen.core.StreamError,
|
||||
lambda: self.router.sudo(via=ssh, password='x')
|
||||
)
|
||||
self.assertTrue(mitogen.sudo.Stream.password_incorrect_msg in str(e))
|
||||
|
||||
def test_password_okay(self):
|
||||
ssh = self.docker_ssh(
|
||||
username='mitogen__has_sudo',
|
||||
password='has_sudo_password',
|
||||
)
|
||||
ssh.call(os.putenv, 'LANGUAGE', 'fr')
|
||||
ssh.call(os.putenv, 'LC_ALL', 'fr_FR.UTF-8')
|
||||
e = self.assertRaises(mitogen.core.StreamError,
|
||||
lambda: self.router.sudo(via=ssh, password='rootpassword')
|
||||
)
|
||||
self.assertTrue(mitogen.sudo.Stream.password_incorrect_msg in str(e))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest2.main()
|
||||
|
|
Loading…
Reference in New Issue