Package: software-properties-common Version: 0.96.20.2-2.1 Severity: important X-Debbugs-Cc: rossboy...@stanfordalumni.org
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 This is a bit involved; it took several days of debugging to get to the bottom of it. After discussing severity I'll describe the initial symptoms, then present the results of my analysis, and finally present a possible fix. **Summary** When adding a key, add-apt-repository creates a number of keys and keyrings. At the last step it tries to import the wrong key and fails; it should import the key it exported. **Severity and Scope** The package provides a single command, add-apt-repository, and it is unable to add a repository for a ppa with Ubuntu's keyserver. I don't see anything that would limit the impact to the one ppa I tried to add, or even to ppa's, though it may depend on the format of the downloaded key. It seems quite likely this is behind the unresolved bug 843946 (from 2016). **Initial Symptoms** My original goal was to build dosemu2 from source. It is available in Ubuntu but not Debian. https://github.com/dosemu2/dosemu2/wiki/Building-From-Source describes the process, the first step of which is to run the ci_preq.sh script (https://github.com/dosemu2/dosemu2/blob/devel/ci_prereq.sh). The first line of the script is `sudo add-apt-repository -y ppa:dosemu2/ppa`. I executed that command with additional debugging in a root shell, without running the rest of the script. <terminal> # date; add-apt-repository -m ppa:dosemu2/ppa Fri 03 Jun 2022 11:44:22 AM PDT More info: https://launchpad.net/~dosemu2/+archive/ubuntu/ppa Press [ENTER] to continue or ctrl-c to cancel adding it START SOURCES.LIST: ## most entries omitted to save space # deb-src http://ppa.launchpad.net/dosemu2/ppa/ubuntu kinetic main END SOURCES.LIST gpg: keybox '/tmp/tmpcjw8ab77/pubring.gpg' created gpg: keyserver receive failed: Server indicated a failure </terminal> This failure is likely unrelated to the subject of this bug. The failing command was on gpg --import from keyserver.ubuntu.com. That import was only erratically successful. Here's one that worked: gpg --verbose --debug-level 7 --no-default-keyring --no-options --homedir /tmp/tmpc20sx87y --secret-keyring /tmp/tmpc20sx87y/secring.gpg --keyring /tmp/tmpc20sx87y/pubring.gpg --keyserver hkp://keyserver.ubuntu.com:80/ --recv 6D9CD73B401A130336ED0A56EBE1B5DED2AD45D6 Finally we arrive at the relevant problem for this bug. The python scripts of software-properties-common (invoked by add-apt-repository) execute 'apt-key --keyring /etc/apt/trusted.gpg.d/dosemu2_ubuntu_ppa.gpg add /tmp/tmpc20sx87y/pubring.gpg' which executes a series of steps, the last of which is gpg --ignore-time-conflict --no-options --no-default-keyring --homedir /tmp/apt-key-gpghome.xVHD35b6q9 -v --check-trustdb --keyring /tmp/apt-key-gpghome.xVHD35b6q9/empty.gpg --keyring '/etc/apt/trusted.gpg.d/dosemu2_ubuntu_ppa.gpg' "-v - --batch --import /tmp/tmppr9n1vry/pubring.gpg" (The directory names don't match previous command because I'm mixing different runs). The result: gpg: no valid OpenPGP data found. gpg: Total number processed: 0 The error was repeatable, assuming the keyserver was responsive. It often wasn't. **Analysis** Earlier steps export the key, but the step just above (with gpg) does not use the exported key. This is likely the result of the fact that apt-key is invoked with pubring.gpg rather than the exported key. In fact, it doesn't seem *anything* uses the exported key. I presume it was exported to get it into a format that was usable. This would mean the failure arises from attempting to import a key in the wrong format. E.g., 852473 refers to this, in turn referencing 844724. I've put a fuller analysis of the program flow below. **Solution** I imported the previously exported key, export-keyring.gpg, instead of pubring.gpg. It worked. <terminal> # date; gpg -v --ignore-time-conflict --no-options --no-default-keyring - --homedir /tmp/apt-key-gpghome.xwyHmcOcK3 --no-auto-check-trustdb --trust-model always --keyring /etc/apt/trusted.gpg.d/dosemu2_ubuntu_ppa.gpg -v --batch - --import /tmp/tmpc20sx87y/export-keyring.gpg Wed 08 Jun 2022 05:34:04 PM PDT # off=0 ctb=99 tag=6 hlen=3 plen=525 :public key packet: version 4, algo 1, created 1475850017, expires 0 pkey[0]: [4096 bits] pkey[1]: [17 bits] keyid: EBE1B5DED2AD45D6 # off=528 ctb=b4 tag=13 hlen=2 plen=25 :user ID packet: "Launchpad PPA for Dosemu2" # off=555 ctb=89 tag=2 hlen=3 plen=568 :signature packet: algo 1, keyid EBE1B5DED2AD45D6 version 4, created 1475850017, md5len 0, sigclass 0x13 digest algo 2, begin of digest aa 4b hashed subpkt 2 len 4 (sig created 2016-10-07) hashed subpkt 27 len 1 (key flags: 03) hashed subpkt 11 len 5 (pref-sym-algos: 9 8 7 3 2) hashed subpkt 21 len 5 (pref-hash-algos: 8 2 9 10 11) hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1) hashed subpkt 30 len 1 (features: 01) hashed subpkt 23 len 1 (keyserver preferences: 80) subpkt 16 len 8 (issuer key ID EBE1B5DED2AD45D6) data: [4095 bits] gpg: pub rsa4096/EBE1B5DED2AD45D6 2016-10-07 Launchpad PPA for Dosemu2 gpg: writing to '/etc/apt/trusted.gpg.d/dosemu2_ubuntu_ppa.gpg' gpg: key EBE1B5DED2AD45D6: public key "Launchpad PPA for Dosemu2" imported gpg: no running gpg-agent - starting '/usr/bin/gpg-agent' gpg: waiting for the agent to come up ... (5s) gpg: connection to agent established gpg: Total number processed: 1 gpg: imported: 1 </terminal> As further confirmation, aptitude stopped complaining about an untrusted repository after this step. **Comments** Although the one substitution solved my immediate problem, there may be other places in the code, supporting other operations, that require a similar change. The unreliability of the ubuntu keyserver seems like a problem, but it's distinct from this one. The code is extremely difficult to debug, and the failures difficult to understand. Starting with add-apt-repository, one has python code, switches in the output stream (I guess to assure proper locale, but the python debugger seemed allergic to it), invocation of subprocesses. apt-key continues, invoking gpg and other programs, and even writing temporary shell scripts that invoke other temporary shell scripts (gpg.1.sh invokes gpg.0.sh, both written by apt-key). You also have to guess whether -debug1 or -debug2 will be more useful for apt-key since you can't do both--a fact that is not documented. So when there is a failure it is completely unclear what command failed or for what reason. Effective error reporting would need to flow all the way down to the scripts written by apt-key, since they are the ones that perform the actual commands. add-apt-repository's -m switch threatens/promises --massive-debug, but fell well short of that. apt-key is going away; this package should not use it, as already noted in 995895. **Appendix: Control flow** Here are some of my notes on the flow of control from add-apt-repository on down, including capturing the key commands that were executed. Indentation is nesting level, except for the actual shell commands executed which tend to be flush left. file:NN means the function is on line NN of file. There are undoubtedly many mistakes. Sequence of commands for add-apt-repository: from addkey_func() at SoftwareProperties.py:691 add_key ppa.py:384 AddPPASigningKey ppa.py:160 add_ppa_signing_key ppa.py:224 note the cleanup function is defined inside this one get_ppa_info retrieves info from URL, including the signing fingerprint tmp_keyring_dir = tempfile.mkdtemp() ppa.py:247 makes temp dir self._recv_key actually gets key ->ppa.py:165 verify_keyid_is_v4 just an integrity check call subprocess ppa.py:176 gpg --recv gives sources list ValueError: underlying buffer has been detached but then I can continue?! here's the command gpg --no-default-keyring --no-options --homedir /tmp/tmpc20sx87y --secret- keyring /tmp/tmpc20sx87y/secring.gpg --keyring /tmp/tmpc20sx87y/pubring.gpg - --keyserver hkp://keyserver.ubuntu.com:80/ --recv 6D9CD73B401A130336ED0A56EBE1B5DED2AD45D6 which prints gpg: key EBE1B5DED2AD45D6: "Launchpad PPA for Dosemu2" not changed gpg: Total number processed: 1 gpg: unchanged: 1 onwards self._export_key() ppa.py:257 -> 185 gpg --no-default-keyring --no-options --homedir /tmp/tmpc20sx87y --keyring /tmp/tmpc20sx87y/pubring.gpg --output /tmp/tmpc20sx87y/export-keyring.gpg - --export 6D9CD73B401A130336ED0A56EBE1B5DED2AD45D6 asked if I wanted to overwrite an existing file self._verify_fingerprint() -> 211 self._get_fingerprints -> 196 gpg --no-default-keyring --no-options --homedir /tmp/tmpc20sx87y --keyring /tmp/tmpc20sx87y/export-keyring.gpg --fingerprint --batch --with-colons why are we verifying a fingerprint we just got?? subprocess.check_output() on the previous command, whose output was 'tru::1:1654359237:0:3:1:5\npub:-:4096:1:EBE1B5DED2AD45D6:1475850017:::-:::scSC::::::23::0:\nfpr:::::::::6D9CD73B401A130336ED0A56EBE1B5DED2AD45D6:\nuid:-::::1475850017::0BB83C1AF9D4B9B057D465F9DEEA0D44E3CF1CC5::Launchpad PPA for Dosemu2::::::::::0:\n' fingerprint is extracted and returned back to line 267 pf add_ppa_signing_key which issues 'apt-key --keyring /etc/apt/trusted.gpg.d/dosemu2_ubuntu_ppa.gpg add /tmp/tmpc20sx87y/pubring.gpg' which is the step that failed. It does prepare_gpg_home makes tmp dir, e.g. + mktemp --directory --tmpdir apt-key-gpghome.XXXXXXXXXX + GPGHOMEDIR=/tmp/apt-key-gpghome.xVHD35b6q9 + chmod 700 /tmp/apt-key-gpghome.xVHD35b6q9 and then + gpg --ignore-time-conflict --no-options --no-default-keyring --homedir /tmp/apt-key-gpghome.xVHD35b6q9 -v --check-trustdb --keyring /tmp/apt-key-gpghome.xVHD35b6q9/empty.gpg (written to gpg.0.sh and exec with additional args --batch --import) There is no argument to --import and the comment saying this is just to force creation of some files. warn_on_script_usage (apt-key deprecated) setup_merged_keyring dearmor file name same as original since .gpg create_new_keyring if it doesn't exist make next file and set mode /etc/apt/trusted.gpg.d/dosemu2_ubuntu_ppa.gpg then make gpg.1.sh: gpg.0.sh --keyring '/etc/apt/trusted.gpg.d/dosemu2_ubuntu_ppa.gpg' "$@" Note gpg.1.sh is not executed before function returns. But GPG is redefined to invoke it. aptkey_execute then does execute: + sh /tmp/apt-key-gpghome.xVHD35b6q9/gpg.1.sh -v --batch --import /tmp/tmppr9n1vry/pubring.gpg which means (directory names inconsistent from multiple runs) + gpg --ignore-time-conflict --no-options --no-default-keyring --homedir /tmp/apt-key-gpghome.xVHD35b6q9 -v --check-trustdb --keyring /tmp/apt-key-gpghome.xVHD35b6q9/empty.gpg --keyring '/etc/apt/trusted.gpg.d/dosemu2_ubuntu_ppa.gpg' "-v - --batch --import /tmp/tmppr9n1vry/pubring.gpg" Why did it create export-keyring.gpg and then not use it? Why are there 2 keyrings? gpg: no valid OpenPGP data found. gpg: Total number processed: 0 - -- System Information: Debian Release: 11.3 APT prefers stable-security APT policy: (500, 'stable-security'), (500, 'stable') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 5.10.0-14-amd64 (SMP w/8 CPU threads) Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE not set Shell: /bin/sh linked to /usr/bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled Versions of packages software-properties-common depends on: ii ca-certificates 20210119 ii gir1.2-glib-2.0 1.66.1-1+b1 ii gir1.2-packagekitglib-1.0 1.2.2-2 ii python-apt-common 2.2.1 ii python3 3.9.2-3 ii python3-dbus 1.2.16-5 ii python3-gi 3.38.0-2 ii python3-software-properties 0.96.20.2-2.1 Versions of packages software-properties-common recommends: ii packagekit 1.2.2-2 software-properties-common suggests no packages. -----BEGIN PGP SIGNATURE----- iQFSBAEBCgA8FiEEreS674/HIyV9gBfdnAYPmOsbK2AFAmKkIgIeHHJvc3Nib3ls YW5Ac3RhbmZvcmRhbHVtbmkub3JnAAoJEJwGD5jrGytgjsUH/03lTIvjoVmKSE55 R6rKEVhb5gHy4pRkycwse0+VTWTjD5o/21Ox2FSfSnbd2hVafNdpLE97V8BzqhPw xhIzNGd/6KdppOjoW1Lq6+z3A75JqsJeYA6JCIH4E9VZ69oCUJQZqOT49OSy0mAR hvGyP+qxoiz0AKC6kzcdPEd/dv5Rvp+zlMMgiWXN9S9UJilt3bzi2SxKaEprSAbI R0aiEFzF3p7u57BgGcMXICPsJGvUeMYalSk5ghyPpIOZrQ476g9DCbCwN9K9xlWO E2hFLnNdgQuYmXWh+XxLJmfUBr8/pj/htjKu3RLLrilFmLnAt37M6gC1pXSikyAZ Q52pGfg= =aIEH -----END PGP SIGNATURE-----