Page MenuHome GnuPG

pinentry-curses on OpenIndiana (Illumos distro) doesn't display correctly
Closed, ResolvedPublic

Description

pinentry-curses (and the fallback from the graphical pinentry-gtk-2 when DISPLAY is not set) doesn't display correctly on OpenIndiana (which is one of the Illumos-based distros that came out of the OpenSolaris project, so it shares a lot of history with Solaris 10 and early Solaris 11).

Symptoms are that none of the text from SETTITLE/SETPROMPT/SETDESC or the border is displayed. The screen is basically blank, though the cursor is roughly in the middle of the screen and it is possible to blindly type in your passphrase, so pinentry-curses is listening, it's just not displaying correctly.

I've tested both with pinentry-curses from 1.1.0 and 1.2.0 and the problem exists in both them.

The problem seems to relate to some terminal types. I normally use "xterm" as my terminal type and it has worked well for me for both command-line work and for other curses-based applications (pine/alpine, top, etc.), however with "OPTION ttytype=xterm" pinentry-curses has the display issues. I'm aware of other TERM types that have the same issue.

If I try setting my "TERM=vt100", then pinentry-curses displays mostly-correctly (the box characters are alternate characters, but that's not a problem).

Not sure why TERM=xterm works for everything else but not pinentry-curses, but that seems to be the case.

The environment:

$ gpgconf --show-versions
Warning: using insecure memory!
* GnuPG 2.3.2 (3bf8d7e1b)
SunOS

* Libgcrypt 1.9.4 (05422ca2)
version:1.9.4:10904:1.42-unknown:12a00:
cc:70500:gcc:7.5.0:
ciphers:arcfour:blowfish:cast5:des:aes:twofish:serpent:rfc2268:seed:camellia:idea:salsa20:gost28147:chacha20:sm4:
pubkeys:dsa:elgamal:rsa:ecc:
digests:crc:gostr3411-94::md4:md5:rmd160:sha1:sha256:sha512:sha3:tiger:whirlpool:stribog:blake2:sm3:
rnd-mod:linux:
cpu-arch::
mpi-asm:generic/mpih-add1.c:generic/mpih-sub1.c:generic/mpih-mul1.c:generic/mpih-mul2.c:generic/mpih-mul3.c:generic/mpih-lshift.c:generic/mpih-rshift.c:
hwflist:
fips-mode:n:n:
rng-type:standard:1:2010000:2:
compliance:::

* GpgRT 1.42-unknown (0000000)

* Libassuan 2.5.5 (f8cfb56)

* KSBA 1.3.5 (?)

* GNUTLS 3.6.16

$ gpgconf --list-dirs
sysconfdir:/etc/gnupg
bindir:/usr/bin
libexecdir:/usr/bin
libdir:/usr/lib/amd64/gnupg
datadir:/usr/share/gnupg
localedir:/usr/share/locale
socketdir:/faculty/ndsu/mooney/.gnupg
dirmngr-socket:/faculty/ndsu/mooney/.gnupg/S.dirmngr
keyboxd-socket:/faculty/ndsu/mooney/.gnupg/S.keyboxd
agent-ssh-socket:/faculty/ndsu/mooney/.gnupg/S.gpg-agent.ssh
agent-extra-socket:/faculty/ndsu/mooney/.gnupg/S.gpg-agent.extra
agent-browser-socket:/faculty/ndsu/mooney/.gnupg/S.gpg-agent.browser
agent-socket:/faculty/ndsu/mooney/.gnupg/S.gpg-agent
homedir:/faculty/ndsu/mooney/.gnupg

pinentry-curses on OpenIndiana is linked against the Solaris-based SVR4 curses (not ncurses), which is considered to be a very strong curses implementation:

$ ldd /usr/lib/pinentry-curses
        libsocket.so.1 =>        /lib/64/libsocket.so.1
        libsecret-1.so.0 =>      /usr/lib/64/libsecret-1.so.0
        libglib-2.0.so.0 =>      /usr/lib/64/libglib-2.0.so.0
        libassuan.so.0 =>        /usr/lib/64/libassuan.so.0
        libgpg-error.so.0 =>     /usr/lib/64/libgpg-error.so.0
        libcurses.so.1 =>        /lib/64/libcurses.so.1
        libc.so.1 =>     /lib/64/libc.so.1
        libnsl.so.1 =>   /lib/64/libnsl.so.1
        libgcrypt.so.20 =>       /usr/lib/64/libgcrypt.so.20
        libgio-2.0.so.0 =>       /usr/lib/64/libgio-2.0.so.0
        libgobject-2.0.so.0 =>   /usr/lib/64/libgobject-2.0.so.0
        libpcre.so.0 =>  /usr/lib/64/libpcre.so.0
        libmp.so.2 =>    /lib/64/libmp.so.2
        libmd.so.1 =>    /lib/64/libmd.so.1
        libgmodule-2.0.so.0 =>   /usr/lib/64/libgmodule-2.0.so.0
        libz.so.1 =>     /usr/lib/64/libz.so.1
        libresolv.so.2 =>        /lib/64/libresolv.so.2
        libffi.so.6 =>   /usr/lib/64/libffi.so.6
        libm.so.2 =>     /lib/64/libm.so.2

gniibe and I have discussed some of this in https://dev.gnupg.org/T5623 , when I mistakenly thought that issue (with gpg-agent) and this issue were related, but I will try summarize all that issue here.

I'll happily provide any additional information I can to try debug what the problem is.

Event Timeline

gniibe triaged this task as Normal priority.
gniibe added projects: pinentry, Support.
gniibe added a subscriber: gniibe.

I found some links:
XTerm FAQ:
https://invisible-island.net/xterm/xterm.faq.html
Why not just use TERM set to "xterm"?
https://invisible-island.net/ncurses/ncurses.faq.html#xterm_generic
What $TERM should I use?
https://tools.ietf.org/doc/xterm/xterm.faq.html#xterm_terminfo

Those explain some (in)compatibility. Detail would be also in the packaging of xterm and its terminfo entry on Illumos.

@mooney Just in case when it's color related problem, could you try to cut&paste the text of the screen when pinentry should display a dialog box?

It appears to you identified the problem really quickly again. If I select the entire screen and paste it, the dialog text is there:

lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
x Please enter the passphrase to unlock the OpenPGP secret key:  x
x "Tim Mooney (NDSU ITS) <Tim.Mooney@ndsu.edu>"                  x
x 1024-bit ELG key, ID 100A77F8477C6C9C,                         x
x created 2001-03-15 (main key ID 015F6BA447576386).             x
x                                                                x
x                                                                x
x Passphrase: __________________________________________________ x
x                                                                x
x         <OK>                                    <Cancel>       x
mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

All of my testing has been done while connecting via ssh to my OpenIndiana workstation. I'm using PuTTY 0.76 as my terminal/SSH client.

Looking through the Illumos terminfo database, there are entries for 'putty', 'putty-256color', and 'putty-vt100'. However, I've tried each of them and they all have the same issue as when using TERM=xterm. The dialog screen *appears* blank.

So far, the only TERM setting I've found that actually works is TERM=vt100, but again that's while using PuTTY as my ssh/terminal.

I've heard from another OpenIndiana user that they've tried TERM=sun-color on the console of their workstation and it also has the display issue.

The next time I'm in my office I will try the same tests in a "mate-terminal" (part of the MATE desktop environment, similar to GNOME2), but I'll unset DISPLAY so I don't get the graphical pinentry program.

Hi gniibe!

I tried TERM=xterm-color (when connected remotely via PuTTY 0.76), but it did not fix the issue. Same invisible display.

As the article you linked points out, there are many, many different TERMINFO definition files for various variants of xterm. OpenIndiana
has 56 different terminfo files with various names starting with 'xterm'.

I'm going to try several variants and see if I can find any of them that work. Then, perhaps using 'infocmp' I can investigate their capabilities and find some common characteristics between the entries that work and the many entries that don't.

After testing about a dozen different term types and doing some library tracing, it appears to be that any terminfo type for which has_colors() is false (so the start_color code is never called) works correctly.

In the testing I've done so far, the problem always appears to happen if the terminfo entry reports that the terminal does have colors. As we discovered and as the tracing has shown, the box and prompt is actually written to the screen, but it's not visible.

I'll continue debugging later this weekend.

Hi gniibe!

I have more news regarding the pinentry issue too.

One of the OpenIndiana developers went ahead and switched pinentry's build for OI so that it uses ncurses, rather than the SVR4-derived curses. This means that the current package they are now shipping doesn't have the "invisible text" issue any longer.

I still believe that there's a subtle problem here with how pinentry is using curses, and I hope to do some more debugging of the issue and eventually discover what was causing the issue, but I don't know that it's worth having you spend any more time on the issue. If the OI developers are fine with shipping a pinentry that uses ncurses rather than the system default curses, then I don't see why you should spend more time debugging this issue. It's possible that there are some other systems out there that are not using ncurses (maybe one of the BSD distros is using traditional BSD curses rather than ncurses), but pretty much anything Linux-based would use ncurses.

I would like it if you could leave this issue open, but my feeling is that it should be marked as a low priority.

gniibe lowered the priority of this task from Normal to Low.Oct 5 2021, 2:24 AM

Thank you for your investigation.

I understand the situation. For pinentry, that's reasonable.

For OpenIndiana (or Solaris), users with Putty might have same/similar issues with other applications.

Hi gniibe!

Quite good news to report on this issue.

One of the other OI users that's been impacted by this pinentry "invisible text" issue, "David Stes" <stes@telenet.be>, has had more time to look at this than I have, and I believe he has identified the issue. His words:

The problem is perhaps that the notion of COLOR_DEFAULT is unknown to
classical curses.

The manpage of ncurses clearly indicates that COLOR_DEFAULT is a ncurses
extension.

See: man use_default_colors

"This function recognizes a special color number -1, which denotes the default terminal color.

The following are equivalent:
       use_default_colors();
       assume_default_colors(-1,-1);

These are ncurses extensions.  "

Also the manpage warns:

"For other curses implementations, color number -1 does not mean anything"

So I think what we see is that ordinary classical curses, is interpreting
the instructions of pinentry to set all colors to the same numbered color.

Which results in unreadable text.

Further, David has identified that in pinentry/pinentry.c, where the foreground, background, and standout colors are all set to PINENTRY_COLOR_DEFAULT, if you change that to use specific colors for the !NCURSES case, then the pinentry text displays as expected on OI with SVR4 or X/Open curses.

--- pinentry/pinentry.c Sun Dec  3 17:13:15 2017
+++ p0/pinentry/pinentry.c      Thu Oct  7 20:49:40 2021
@@ -182,11 +182,19 @@
       /* Global grab.  */
       pinentry.grab = 1;

+#ifdef NCURSES_VERSION
       pinentry.color_fg = PINENTRY_COLOR_DEFAULT;
       pinentry.color_fg_bright = 0;
       pinentry.color_bg = PINENTRY_COLOR_DEFAULT;
       pinentry.color_so = PINENTRY_COLOR_DEFAULT;
       pinentry.color_so_bright = 0;
+#else
+      pinentry.color_fg = PINENTRY_COLOR_GREEN;
+      pinentry.color_fg_bright = 0;
+      pinentry.color_bg = PINENTRY_COLOR_BLACK;
+      pinentry.color_so = PINENTRY_COLOR_YELLOW;
+      pinentry.color_so_bright = 0;
+#endif

       pinentry.owner_uid = -1;
     }

I will add David's patch as an attachment to this issue.

Thank you for locating the bug!

I think that we should be conservative for the change.

Unfortunately, the idea of "default color" is exposed to user; "default" is supported by option (see parse_color function).

So, it's better to add support of "default" color handling in pinentry-curses.c.

And, to keep same behavior, I use PINENTRY_COLOR_WHITE for color_fg, and PINENTRY_COLOR_BLACK for color_bg, not changing color_so.

I pushed the change as: rPd937ccfe4445: curses: Specify fg/bg when an extention of Ncurses is not available.

gniibe edited projects, added Restricted Project; removed Support.Oct 13 2021, 3:26 AM

Hello Tim and Yukata Iibe (gniibe),

I am David Stes and I also use OpenIndiana and was affected by the same issue that Tim discovered.

I have tested the commit that was added and it does not work.

I think there is a small typo in the code :
`

if (pinentry->color_fg == PINENTRY_COLOR_DEFAULT)
  pinentry->color_fg = PINENTRY_COLOR_WHITE;
if (pinentry->color_bg == PINENTRY_COLOR_DEFAULT)
  • pinentry->color_fg = PINENTRY_COLOR_BLACK;

+ pinentry->color_bg = PINENTRY_COLOR_BLACK;`

The code that was added, is setting the color_fg foreground twice and does not change color_bg background.

I think this was just a typo, and that the basic idea was correct.

When I make the above change it "works" by setting color_fg to white and color_bg to black.

But is it really working ? It is an improvement but not perfect.

Both my patch (which Tim posted) and the gniibe patch suffer from the same problem : on my sun-color terminal the default background is black and text characters are white.

So in the case of sun-color on the console the pinentry-curses linked against traditional curses, is using the correct default colors.

But those colors are different in the case of a MATE (GNOME) terminal using xterm-color.

In that case (MATE) I have a white background and black characters by default.

Now my patch and gniibe's patch is picking the "wrong" colors in the xterm-color case.

It should be setting color_fg to black and color_bk to white.

I think this is part of the reason why the ncurses based extensions of default color are used in pinentry-curses.

Another reason is avoiding a werare() or wclear() clearing the terminal and repainting the entire screen.

In the case of xterm-color the current behavior looks weird because the frame is redrawn with a black background and white frame, but pinentry-curses should first do :

werase() or wclear()

to clear the terminal and repaint it completely in the background color.

ncurses is not doing that because its concept of 'default color' is precisely to avoid unnecessarily clearing the entire terminal.

So there are multiple solutions possible.

In any case the current fix is OK provided the color_fg/color_bg is modified, and perhaps if somewhere in the code

`
#ifndef NCURSES_VERSION

wclear();

#endif`

is inserted.

In the patch in attach I do a clear screen in the non-ncurses case.

The idea is that curses cannot work as efficiently as ncurses can, because curses lacks the concept of default color.

My previous patch is not perfect as the screenshot in attach shows. The clear() is not really sufficient as it only redraws the portion below the frame in the new background color (black instead of white).

The problem is that the color black is not really the default background color of the xterm-color.

This problem is not happening for sun-color on the text color which truly has a back default background.

See screenshot of the problem :

The typo is fixed now and after pulling the latest sources from the repo and configure --disable-ncurses :

I observe now perfect results on the login text console (which has a black default background) for both TERM=sun and TERM=sun-color. In the first case standout text is inversed and in the second case standout text is printed in red.

For the xterm-256color in MATE which has a white background by default, the default settings of pinentry are still the opposite: the result looks strange see screenshot but it is readable :

So because the fix is easy to set TERM=xterm I think the result is now acceptable.

Perhaps the background can be painted completely black by inserting somewhere a full wclear() or werase() to erase the screen all blanks in the color_bg.

My understanding is that the ncurses library is exactly trying to avoid that unefficient operation of classical curses by its default color extension.

For completeness here's a screenshot that shows the situation on a TERM=sun-console text console with the latest code :

So in this case it looks perfect. The current code works fine for the text console with black background because the GPG2 pinentry code now is hardcoding black as background color in the non-ncurses case with color enabled.

gniibe removed a project: Restricted Project.

Fixed in 1.2.1.