aboutsummaryrefslogtreecommitdiffstats
path: root/pinentry-rofi.py
diff options
context:
space:
mode:
authorMatěj Cepl <mcepl@cepl.eu>2023-05-17 17:51:52 +0200
committerMatěj Cepl <mcepl@cepl.eu>2023-08-11 11:59:00 +0200
commita67f3096128ff26b0a58e4eb09ae57756d6fd97c (patch)
treea5217ebd8817a4daabdcf595e62bca90ecbc5c96 /pinentry-rofi.py
parentdf3c4ae12a602d5316d16bf331644aff842a24c2 (diff)
downloadpinentry-rofi-a67f3096128ff26b0a58e4eb09ae57756d6fd97c.tar.gz
fix: First rewrite to Python should be complete, except it doesn't work.
Diffstat (limited to 'pinentry-rofi.py')
-rwxr-xr-x[-rw-r--r--]pinentry-rofi.py103
1 files changed, 92 insertions, 11 deletions
diff --git a/pinentry-rofi.py b/pinentry-rofi.py
index 3ce5556..e2266e6 100644..100755
--- 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('<', '&lt;').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 <rofi>"
+ 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)