From a67f3096128ff26b0a58e4eb09ae57756d6fd97c Mon Sep 17 00:00:00 2001 From: Matěj Cepl Date: Wed, 17 May 2023 17:51:52 +0200 Subject: fix: First rewrite to Python should be complete, except it doesn't work. --- pinentry-rofi.py | 103 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 11 deletions(-) mode change 100644 => 100755 pinentry-rofi.py (limited to 'pinentry-rofi.py') diff --git a/pinentry-rofi.py b/pinentry-rofi.py old mode 100644 new mode 100755 index 3ce5556..e2266e6 --- a/pinentry-rofi.py +++ b/pinentry-rofi.py @@ -1,30 +1,111 @@ +#!/usr/bin/env python3 +# Some documentation +# https://info2html.sourceforge.net/cgi-bin/info2html-demo/info2html?(pinentry)Protocol +# https://superuser.com/a/1655428 + +# Although it is called a PIN-Entry, it does allow to enter reasonably +# long strings (at least 2048 characters are supported by every +# pinentry). + +# The client using the PIN-Entry has to check for correctness. + +# Note that all strings are expected to be encoded as UTF-8; +# PINENTRY takes care of converting it to the locally used codeset. +# To include linefeeds or other special characters, you may +# percent-escape them (i.e. a line feed is encoded as `%0A', the +# percent sign itself is encoded as `%25'). + + +import io +import os +import re +import logging import subprocess -rofi = ['rofi', '-dmenu', '-input', '/dev/null', '-password'] +logging.basicConfig(format='%(levelname)s:%(funcName)s:%(message)s', + filename="/tmp/pinentry-log.txt", + level=logging.DEBUG) +log = logging.getLogger() + +rofi_cmd = ['rofi', '-dmenu', '-input', '/dev/null', '-password'] + +GPIN_VALID = re.compile(r'([A-Za-z_]+)=(.+)$') def assuan_send(t): + log.debug(f'assuan_send: {t}') print(t) assuan_send("OK Please go ahead") +win_title = "Prompt for password" +win_prompt = "Password" +win_mesg = '' + while True: line = input() + log.debug(f'line = {line}') ok = True - if line.startswith("OPTION "): + if line.startswith("OPTION"): # OPTION grab # OPTION ttyname=/dev/pts/1 # OPTION ttytype=tmux-256color # OPTION lc-messages=C - # OPTI - pass - elif line == "BYE": - break + assuan_send('OK') + elif line.startswith("GETINFO"): + info = line.split()[1].strip() + # case ( info ) + # when 'pid' + # assuan_send "D #{Process.pid}" + # end + assuan_send('OK') + elif line.startswith("SETKEYINFO"): + # TODO SETKEYINFO s/FINGERPRINT + assuan_send('OK') + elif line.startswith(("SETOK","SETNOTOK","SETERROR","SETCANCEL","SETTIMEOUT", + "SETQUALITYBAR","SETGENPIN")): + assuan_send('OK') + elif line.startswith(("CONFIRM","MESSAGE",)): + assuan_send('OK') + elif line.startswith("SETDESC"): + #SETDESC Please enter the passphrase for the ssh key%0A ke:yf:in:ge:rp:ri:nt + # rofi << '-mesg' << $1.gsub('<', '<').gsub(/%([0-9A-Fa-f]{2})/) { $1.to_i(16).chr } + win_mesg = " ".join(line.split()[1:]).strip() + assuan_send('OK') + elif line.startswith("SETPROMPT"): + #SETPROMPT Passphrase: + win_prompt = line.split()[1].strip() + assuan_send('OK') + elif line.startswith("GETPIN"): + passw = None + with subprocess.check_output(['systemctl', '--user', 'show-environment']) as env_f: + for env_line in env_f: + log.debug(f'env_line = {env_line}') + if (env_match := GPIN_VALID.match(env_line)): + log.debug(f'env_match = {env_match}') + var, val = env_match.groups()[1:] + log.debug(f'var, val = {var}, {val}') + os.env[var] = val + + rofi_cmd.extend(('-p', win_prompt)) + rofi_cmd.extend(('-title', win_title)) + if win_mesg: + rofi_cmd.extend(('-mesg', win_mesg)) + try: + passw = subprocess.run(rofi_cmd, check=True, capture_output=True).stdout.strip() + except subprocess.SubprocessError as ex: + # assuan_send "ERR 83886179 Operation cancelled " + log.exception(f"rofi failed to run: {ex.returncode}, out: {ex.output}, err: {ex.stderr}") + exit(ex.returncode) + ok = false + else: + if passw: + assuan_send(f'D {passw}') + assuan_send('OK') + elif line.startswith("BYE"): + exit(0) else: - rofi.append(line.strip()) - ok = False + assuan_send("BYE") + exit(1) if ok: break - -password = subprocess.check_output(rofi).decode().strip() -assuan_send(password) -- cgit