* [PATCH v6 0/4] IPK signing for the gpg_sign module
@ 2016-02-19 15:45 Ioan-Adrian Ratiu
2016-02-19 15:45 ` [PATCH v6 1/4] gpg_sign: add local ipk package signing functionality Ioan-Adrian Ratiu
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Ioan-Adrian Ratiu @ 2016-02-19 15:45 UTC (permalink / raw)
To: openembedded-core
This patch series extends the gpg_sign module to support ipk signing.
v6 implements Markus' feedback. The most notable change is the sign_ipk
and detach_sign merger, as they were almost identical in functionality.
This also meant a refactoring for detach_sign and a bug fix for the
STDIN file descriptor introduced in gpg > 2.1.
Technically that STDIN bug is a feature (meh) of gpg >2.1 which breaks
existing behaviour so we have to work around it i.e. check the gpg
version and use the loopback interface. This means that gpg-agent to
which gpg >2.1 always connects needs to be running permanently.
Ioan-Adrian Ratiu (4):
gpg_sign: add local ipk package signing functionality
gpg_sign: detach_sign: fix gpg > 2.1 STDIN file descriptor
gpg_sign: export_pubkey: add signature type support
package_manager: sign IPK package feeds
meta/classes/package_ipk.bbclass | 5 +++
meta/classes/sign_ipk.bbclass | 52 ++++++++++++++++++++++++
meta/classes/sign_package_feed.bbclass | 12 +++++-
meta/lib/oe/gpg_sign.py | 74 +++++++++++++++++++++++++++-------
meta/lib/oe/package_manager.py | 17 +++++++-
5 files changed, 143 insertions(+), 17 deletions(-)
create mode 100644 meta/classes/sign_ipk.bbclass
--
2.7.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v6 1/4] gpg_sign: add local ipk package signing functionality
2016-02-19 15:45 [PATCH v6 0/4] IPK signing for the gpg_sign module Ioan-Adrian Ratiu
@ 2016-02-19 15:45 ` Ioan-Adrian Ratiu
2016-02-23 10:25 ` Markus Lehtonen
2016-02-19 15:45 ` [PATCH v6 2/4] gpg_sign: detach_sign: fix gpg > 2.1 STDIN file descriptor Ioan-Adrian Ratiu
` (3 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Ioan-Adrian Ratiu @ 2016-02-19 15:45 UTC (permalink / raw)
To: openembedded-core
Implement ipk signing inside the sign_ipk bbclass using the gpg_sign
module and configure signing similar to how rpm does it. sign_ipk uses
gpg_sign's detach_sign because its functionality is identical to package
feed signing.
IPK signing process is a bit different from rpm:
- Signatures are stored outside ipk files; opkg connects to a feed
server and downloads them to verify a package.
- Signatures are of two types (both supported by opkg): binary or
ascii armoured. By default we sign using ascii armoured.
- Public keys are stored on targets to verify ipks using the
opkg-keyrings recipe.
Signed-off-by: Ioan-Adrian Ratiu <adrian.ratiu@ni.com>
---
meta/classes/package_ipk.bbclass | 5 ++++
meta/classes/sign_ipk.bbclass | 52 ++++++++++++++++++++++++++++++++++++++++
meta/lib/oe/gpg_sign.py | 50 ++++++++++++++++++++++++++++----------
3 files changed, 94 insertions(+), 13 deletions(-)
create mode 100644 meta/classes/sign_ipk.bbclass
diff --git a/meta/classes/package_ipk.bbclass b/meta/classes/package_ipk.bbclass
index 51bee28..f64837a 100644
--- a/meta/classes/package_ipk.bbclass
+++ b/meta/classes/package_ipk.bbclass
@@ -246,6 +246,11 @@ python do_package_ipk () {
bb.utils.unlockfile(lf)
raise bb.build.FuncFailed("opkg-build execution failed")
+ if d.getVar('IPK_SIGN_PACKAGES', True) == '1':
+ ipkver = "%s-%s" % (d.getVar('PKGV'), d.getVar('PKGR'))
+ ipk_to_sign = "%s/%s_%s_%s.ipk" % (pkgoutdir, pkgname, ipkver, d.getVar('PACKAGE_ARCH', True))
+ sign_ipk(d, ipk_to_sign)
+
cleanupcontrol(root)
bb.utils.unlockfile(lf)
diff --git a/meta/classes/sign_ipk.bbclass b/meta/classes/sign_ipk.bbclass
new file mode 100644
index 0000000..a481f6d
--- /dev/null
+++ b/meta/classes/sign_ipk.bbclass
@@ -0,0 +1,52 @@
+# Class for generating signed IPK packages.
+#
+# Configuration variables used by this class:
+# IPK_GPG_PASSPHRASE_FILE
+# Path to a file containing the passphrase of the signing key.
+# IPK_GPG_NAME
+# Name of the key to sign with.
+# IPK_GPG_BACKEND
+# Optional variable for specifying the backend to use for signing.
+# Currently the only available option is 'local', i.e. local signing
+# on the build host.
+# IPK_GPG_SIGNATURE_TYPE
+# Optional variable for specifying the type of gpg signatures, can be:
+# 1. Ascii armored (ASC), default if not set
+# 2. Binary (BIN)
+# GPG_BIN
+# Optional variable for specifying the gpg binary/wrapper to use for
+# signing.
+# GPG_PATH
+# Optional variable for specifying the gnupg "home" directory:
+#
+
+inherit sanity
+
+IPK_SIGN_PACKAGES = '1'
+IPK_GPG_BACKEND ?= 'local'
+IPK_GPG_SIGNATURE_TYPE ?= 'ASC'
+
+python () {
+ # Check configuration
+ for var in ('IPK_GPG_NAME', 'IPK_GPG_PASSPHRASE_FILE'):
+ if not d.getVar(var, True):
+ raise_sanity_error("You need to define %s in the config" % var, d)
+
+ sigtype = d.getVar("IPK_GPG_SIGNATURE_TYPE", True)
+ if sigtype.upper() != "ASC" and sigtype.upper() != "BIN":
+ raise_sanity_error("Bad value for IPK_GPG_SIGNATURE_TYPE (%s), use either ASC or BIN" % sigtype)
+}
+
+def sign_ipk(d, ipk_to_sign):
+ from oe.gpg_sign import get_signer
+
+ bb.debug(1, 'Signing ipk: %s' % ipk_to_sign)
+
+ signer = get_signer(d, d.getVar('IPK_GPG_BACKEND', True))
+ sig_type = d.getVar('IPK_GPG_SIGNATURE_TYPE', True)
+ is_ascii_sig = (sig_type.upper() != "BIN")
+
+ signer.detach_sign(ipk_to_sign,
+ d.getVar('IPK_GPG_NAME', True),
+ d.getVar('IPK_GPG_PASSPHRASE_FILE', True),
+ armor=is_ascii_sig)
diff --git a/meta/lib/oe/gpg_sign.py b/meta/lib/oe/gpg_sign.py
index ada1b2f..ef47d1a 100644
--- a/meta/lib/oe/gpg_sign.py
+++ b/meta/lib/oe/gpg_sign.py
@@ -1,5 +1,6 @@
"""Helper module for GPG signing"""
import os
+import sys
import bb
import oe.utils
@@ -50,6 +51,7 @@ class LocalSigner(object):
bb.error('rpmsign failed: %s' % proc.before.strip())
raise bb.build.FuncFailed("Failed to sign RPM packages")
+
def detach_sign(self, input_file, keyid, passphrase_file, passphrase=None, armor=True):
"""Create a detached signature of a file"""
import subprocess
@@ -57,23 +59,45 @@ class LocalSigner(object):
if passphrase_file and passphrase:
raise Exception("You should use either passphrase_file of passphrase, not both")
- cmd = [self.gpg_bin, '--detach-sign', '--batch', '--no-tty', '--yes',
- '-u', keyid]
- if passphrase_file:
- cmd += ['--passphrase-file', passphrase_file]
- else:
- cmd += ['--passphrase-fd', '0']
+ cmd = [self.gpg_bin, '--detach-sign', '--batch', '--no-tty', '--yes', '-u', keyid]
+
if self.gpg_path:
cmd += ['--homedir', self.gpg_path]
if armor:
cmd += ['--armor']
- cmd.append(input_file)
- job = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- _, stderr = job.communicate(passphrase)
- if job.returncode:
- raise bb.build.FuncFailed("Failed to create signature for '%s': %s" %
- (input_file, stderr))
+
+ try:
+ keypipe = os.pipe()
+
+ if passphrase_file:
+ with open(passphrase_file) as fobj:
+ os.write(keypipe[1], fobj.readline());
+ else:
+ os.write(keypipe[1], passphrase)
+
+ cmd += ["--passphrase-fd", str(keypipe[0])]
+ cmd += [input_file]
+
+ job = subprocess.Popen(cmd, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
+ (_, stderr) = job.communicate(passphrase)
+
+ os.close(keypipe[1])
+ os.close(keypipe[0])
+
+ if job.returncode:
+ raise bb.build.FuncFailed("GPG exited with code %d: %s" %
+ (job.returncode, stderr))
+
+ except IOError as e:
+ bb.error("IO error (%s): %s" % (e.errno, e.strerror))
+ raise Exception("Failed to sign '%s'" % input_file)
+ except OSError as e:
+ bb.error("OS error (%s): %s" % (e.errno, e.strerror))
+ raise Exception("Failed to sign '%s" % input_file)
+ except:
+ bb.error("Unexpected error (%s): %s" % (sys.exc_info()[0], sys.exc_info()[1]))
+ raise Exception("Failed to sign '%s'" % input_file)
+
def verify(self, sig_file):
"""Verify signature"""
--
2.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v6 2/4] gpg_sign: detach_sign: fix gpg > 2.1 STDIN file descriptor
2016-02-19 15:45 [PATCH v6 0/4] IPK signing for the gpg_sign module Ioan-Adrian Ratiu
2016-02-19 15:45 ` [PATCH v6 1/4] gpg_sign: add local ipk package signing functionality Ioan-Adrian Ratiu
@ 2016-02-19 15:45 ` Ioan-Adrian Ratiu
2016-02-23 10:26 ` Markus Lehtonen
2016-02-19 15:45 ` [PATCH v6 3/4] gpg_sign: export_pubkey: add signature type support Ioan-Adrian Ratiu
` (2 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Ioan-Adrian Ratiu @ 2016-02-19 15:45 UTC (permalink / raw)
To: openembedded-core
Starting from v2.1 passing passwords directly to gpg does not work
anymore [1], instead a loopback interface must be used otherwise
gpg >2.1 will error out with:
"gpg: signing failed: Inappropriate ioctl for device"
gpg <2.1 does not work with the new --pinentry-mode arg and gives an
invalid option error, so we detect what is the running version of gpg
and pass it accordingly.
[1] https://wiki.archlinux.org/index.php/GnuPG#Unattended_passphrase
Signed-off-by: Ioan-Adrian Ratiu <adrian.ratiu@ni.com>
---
meta/lib/oe/gpg_sign.py | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/meta/lib/oe/gpg_sign.py b/meta/lib/oe/gpg_sign.py
index ef47d1a..9f6b0f0 100644
--- a/meta/lib/oe/gpg_sign.py
+++ b/meta/lib/oe/gpg_sign.py
@@ -66,6 +66,12 @@ class LocalSigner(object):
if armor:
cmd += ['--armor']
+ #gpg > 2.1 supports password pipes only through the loopback interface
+ #gpg < 2.1 errors out if given unknown parameters
+ gpg_ver = self.get_gpg_version()
+ if gpg_ver > 2.1:
+ cmd += ['--pinentry-mode', 'loopback']
+
try:
keypipe = os.pipe()
@@ -99,6 +105,20 @@ class LocalSigner(object):
raise Exception("Failed to sign '%s'" % input_file)
+ def get_gpg_version(self):
+ """Return the gpg version"""
+ import subprocess
+
+ job = subprocess.Popen([self.gpg_bin, "--version"], stdout=subprocess.PIPE)
+ (stdout, _) = job.communicate()
+
+ if job.returncode:
+ raise bb.build.FuncFailed("Could not get gpg version (is %s installed?)" %
+ self.gpg_bin)
+
+ return stdout.split()[2]
+
+
def verify(self, sig_file):
"""Verify signature"""
cmd = self.gpg_bin + " --verify "
--
2.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v6 3/4] gpg_sign: export_pubkey: add signature type support
2016-02-19 15:45 [PATCH v6 0/4] IPK signing for the gpg_sign module Ioan-Adrian Ratiu
2016-02-19 15:45 ` [PATCH v6 1/4] gpg_sign: add local ipk package signing functionality Ioan-Adrian Ratiu
2016-02-19 15:45 ` [PATCH v6 2/4] gpg_sign: detach_sign: fix gpg > 2.1 STDIN file descriptor Ioan-Adrian Ratiu
@ 2016-02-19 15:45 ` Ioan-Adrian Ratiu
2016-02-19 15:45 ` [PATCH v6 4/4] package_manager: sign IPK package feeds Ioan-Adrian Ratiu
2016-02-23 10:28 ` [PATCH v6 0/4] IPK signing for the gpg_sign module Markus Lehtonen
4 siblings, 0 replies; 8+ messages in thread
From: Ioan-Adrian Ratiu @ 2016-02-19 15:45 UTC (permalink / raw)
To: openembedded-core
Add support for multiple types of signatures (binary or ascii)
in export_pubkey(). There is no change in behaviour for the function,
the previous implicit default is the new parameter "armor" default.
Signed-off-by: Ioan-Adrian Ratiu <adrian.ratiu@ni.com>
---
meta/lib/oe/gpg_sign.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/meta/lib/oe/gpg_sign.py b/meta/lib/oe/gpg_sign.py
index 9f6b0f0..9b3864a 100644
--- a/meta/lib/oe/gpg_sign.py
+++ b/meta/lib/oe/gpg_sign.py
@@ -13,12 +13,14 @@ class LocalSigner(object):
self.gpg_path = d.getVar('GPG_PATH', True)
self.rpm_bin = bb.utils.which(os.getenv('PATH'), "rpm")
- def export_pubkey(self, output_file, keyid):
+ def export_pubkey(self, output_file, keyid, armor=True):
"""Export GPG public key to a file"""
- cmd = '%s --batch --yes --export --armor -o %s ' % \
+ cmd = '%s --batch --yes --export -o %s ' % \
(self.gpg_bin, output_file)
if self.gpg_path:
cmd += "--homedir %s " % self.gpg_path
+ if armor:
+ cmd += "--armor "
cmd += keyid
status, output = oe.utils.getstatusoutput(cmd)
if status:
--
2.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v6 4/4] package_manager: sign IPK package feeds
2016-02-19 15:45 [PATCH v6 0/4] IPK signing for the gpg_sign module Ioan-Adrian Ratiu
` (2 preceding siblings ...)
2016-02-19 15:45 ` [PATCH v6 3/4] gpg_sign: export_pubkey: add signature type support Ioan-Adrian Ratiu
@ 2016-02-19 15:45 ` Ioan-Adrian Ratiu
2016-02-23 10:28 ` [PATCH v6 0/4] IPK signing for the gpg_sign module Markus Lehtonen
4 siblings, 0 replies; 8+ messages in thread
From: Ioan-Adrian Ratiu @ 2016-02-19 15:45 UTC (permalink / raw)
To: openembedded-core
Create gpg signed ipk package feeds using the gpg backend if configured.
Signed-off-by: Ioan-Adrian Ratiu <adrian.ratiu@ni.com>
---
meta/classes/sign_package_feed.bbclass | 12 +++++++++++-
meta/lib/oe/package_manager.py | 17 +++++++++++++++--
2 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/meta/classes/sign_package_feed.bbclass b/meta/classes/sign_package_feed.bbclass
index 63ca02f..85c37f3 100644
--- a/meta/classes/sign_package_feed.bbclass
+++ b/meta/classes/sign_package_feed.bbclass
@@ -10,6 +10,12 @@
# Optional variable for specifying the backend to use for signing.
# Currently the only available option is 'local', i.e. local signing
# on the build host.
+# PACKAGE_FEED_GPG_SIGNATURE_TYPE
+# Optional variable for specifying the type of gpg signature, can be:
+# 1. Ascii armored (ASC), default if not set
+# 2. Binary (BIN)
+# This variable is only available for IPK feeds. It is ignored on
+# other packaging backends.
# GPG_BIN
# Optional variable for specifying the gpg binary/wrapper to use for
# signing.
@@ -20,7 +26,7 @@ inherit sanity
PACKAGE_FEED_SIGN = '1'
PACKAGE_FEED_GPG_BACKEND ?= 'local'
-
+PACKAGE_FEED_GPG_SIGNATURE_TYPE ?= 'ASC'
python () {
# Check sanity of configuration
@@ -28,6 +34,10 @@ python () {
if not d.getVar(var, True):
raise_sanity_error("You need to define %s in the config" % var, d)
+ sigtype = d.getVar("PACKAGE_FEED_GPG_SIGNATURE_TYPE", True)
+ if sigtype.upper() != "ASC" and sigtype.upper() != "BIN":
+ raise_sanity_error("Bad value for PACKAGE_FEED_GPG_SIGNATURE_TYPE (%s), use either ASC or BIN" % sigtype)
+
# Set expected location of the public key
d.setVar('PACKAGE_FEED_GPG_PUBKEY',
os.path.join(d.getVar('STAGING_ETCDIR_NATIVE', False),
diff --git a/meta/lib/oe/package_manager.py b/meta/lib/oe/package_manager.py
index b30a4da..606ba24 100644
--- a/meta/lib/oe/package_manager.py
+++ b/meta/lib/oe/package_manager.py
@@ -163,11 +163,16 @@ class OpkgIndexer(Indexer):
"MULTILIB_ARCHS"]
opkg_index_cmd = bb.utils.which(os.getenv('PATH'), "opkg-make-index")
+ if self.d.getVar('PACKAGE_FEED_SIGN', True) == '1':
+ signer = get_signer(self.d, self.d.getVar('PACKAGE_FEED_GPG_BACKEND', True))
+ else:
+ signer = None
if not os.path.exists(os.path.join(self.deploy_dir, "Packages")):
open(os.path.join(self.deploy_dir, "Packages"), "w").close()
index_cmds = []
+ index_sign_files = []
for arch_var in arch_vars:
archs = self.d.getVar(arch_var, True)
if archs is None:
@@ -186,6 +191,8 @@ class OpkgIndexer(Indexer):
index_cmds.append('%s -r %s -p %s -m %s' %
(opkg_index_cmd, pkgs_file, pkgs_file, pkgs_dir))
+ index_sign_files.append(pkgs_file)
+
if len(index_cmds) == 0:
bb.note("There are no packages in %s!" % self.deploy_dir)
return
@@ -193,9 +200,15 @@ class OpkgIndexer(Indexer):
result = oe.utils.multiprocess_exec(index_cmds, create_index)
if result:
bb.fatal('%s' % ('\n'.join(result)))
- if self.d.getVar('PACKAGE_FEED_SIGN', True) == '1':
- raise NotImplementedError('Package feed signing not implementd for ipk')
+ if signer:
+ feed_sig_type = self.d.getVar('PACKAGE_FEED_GPG_SIGNATURE_TYPE', True)
+ is_ascii_sig = (feed_sig_type.upper() != "BIN")
+ for f in index_sign_files:
+ signer.detach_sign(f,
+ self.d.getVar('PACKAGE_FEED_GPG_NAME', True),
+ self.d.getVar('PACKAGE_FEED_GPG_PASSPHRASE_FILE', True),
+ armor=is_ascii_sig)
class DpkgIndexer(Indexer):
--
2.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v6 1/4] gpg_sign: add local ipk package signing functionality
2016-02-19 15:45 ` [PATCH v6 1/4] gpg_sign: add local ipk package signing functionality Ioan-Adrian Ratiu
@ 2016-02-23 10:25 ` Markus Lehtonen
0 siblings, 0 replies; 8+ messages in thread
From: Markus Lehtonen @ 2016-02-23 10:25 UTC (permalink / raw)
To: Ioan-Adrian Ratiu, openembedded-core
Hi,
Resending as my I got a strange "Only members may post to the list."
error yesterday...
On Fri, 2016-02-19 at 17:43 +0200, Ioan-Adrian Ratiu wrote:
> Implement ipk signing inside the sign_ipk bbclass using the gpg_sign
> module and configure signing similar to how rpm does it. sign_ipk
> uses
> gpg_sign's detach_sign because its functionality is identical to
> package
> feed signing.
>
> IPK signing process is a bit different from rpm:
> - Signatures are stored outside ipk files; opkg connects to a
> feed
> server and downloads them to verify a package.
> - Signatures are of two types (both supported by opkg): binary or
> ascii armoured. By default we sign using ascii armoured.
> - Public keys are stored on targets to verify ipks using the
> opkg-keyrings recipe.
>
> Signed-off-by: Ioan-Adrian Ratiu <adrian.ratiu@ni.com>
> ---
> meta/classes/package_ipk.bbclass | 5 ++++
> meta/classes/sign_ipk.bbclass | 52
> ++++++++++++++++++++++++++++++++++++++++
> meta/lib/oe/gpg_sign.py | 50 ++++++++++++++++++++++++++++--
> --------
> 3 files changed, 94 insertions(+), 13 deletions(-)
> create mode 100644 meta/classes/sign_ipk.bbclass
>
> diff --git a/meta/classes/package_ipk.bbclass
> b/meta/classes/package_ipk.bbclass
> index 51bee28..f64837a 100644
> --- a/meta/classes/package_ipk.bbclass
> +++ b/meta/classes/package_ipk.bbclass
> @@ -246,6 +246,11 @@ python do_package_ipk () {
> bb.utils.unlockfile(lf)
> raise bb.build.FuncFailed("opkg-build execution failed")
>
> + if d.getVar('IPK_SIGN_PACKAGES', True) == '1':
> + ipkver = "%s-%s" % (d.getVar('PKGV'), d.getVar('PKGR'))
> + ipk_to_sign = "%s/%s_%s_%s.ipk" % (pkgoutdir, pkgname,
> ipkver, d.getVar('PACKAGE_ARCH', True))
> + sign_ipk(d, ipk_to_sign)
> +
> cleanupcontrol(root)
> bb.utils.unlockfile(lf)
>
> diff --git a/meta/classes/sign_ipk.bbclass
> b/meta/classes/sign_ipk.bbclass
> new file mode 100644
> index 0000000..a481f6d
> --- /dev/null
> +++ b/meta/classes/sign_ipk.bbclass
> @@ -0,0 +1,52 @@
> +# Class for generating signed IPK packages.
> +#
> +# Configuration variables used by this class:
> +# IPK_GPG_PASSPHRASE_FILE
> +# Path to a file containing the passphrase of the signing
> key.
> +# IPK_GPG_NAME
> +# Name of the key to sign with.
> +# IPK_GPG_BACKEND
> +# Optional variable for specifying the backend to use for
> signing.
> +# Currently the only available option is 'local', i.e.
> local signing
> +# on the build host.
> +# IPK_GPG_SIGNATURE_TYPE
> +# Optional variable for specifying the type of gpg
> signatures, can be:
> +# 1. Ascii armored (ASC), default if not set
> +# 2. Binary (BIN)
> +# GPG_BIN
> +# Optional variable for specifying the gpg binary/wrapper
> to use for
> +# signing.
> +# GPG_PATH
> +# Optional variable for specifying the gnupg "home"
> directory:
> +#
> +
> +inherit sanity
> +
> +IPK_SIGN_PACKAGES = '1'
> +IPK_GPG_BACKEND ?= 'local'
> +IPK_GPG_SIGNATURE_TYPE ?= 'ASC'
> +
> +python () {
> + # Check configuration
> + for var in ('IPK_GPG_NAME', 'IPK_GPG_PASSPHRASE_FILE'):
> + if not d.getVar(var, True):
> + raise_sanity_error("You need to define %s in the config"
> % var, d)
> +
> + sigtype = d.getVar("IPK_GPG_SIGNATURE_TYPE", True)
> + if sigtype.upper() != "ASC" and sigtype.upper() != "BIN":
> + raise_sanity_error("Bad value for IPK_GPG_SIGNATURE_TYPE
> (%s), use either ASC or BIN" % sigtype)
> +}
> +
> +def sign_ipk(d, ipk_to_sign):
> + from oe.gpg_sign import get_signer
> +
> + bb.debug(1, 'Signing ipk: %s' % ipk_to_sign)
> +
> + signer = get_signer(d, d.getVar('IPK_GPG_BACKEND', True))
> + sig_type = d.getVar('IPK_GPG_SIGNATURE_TYPE', True)
> + is_ascii_sig = (sig_type.upper() != "BIN")
> +
> + signer.detach_sign(ipk_to_sign,
> + d.getVar('IPK_GPG_NAME', True),
> + d.getVar('IPK_GPG_PASSPHRASE_FILE', True),
> + armor=is_ascii_sig)
> diff --git a/meta/lib/oe/gpg_sign.py b/meta/lib/oe/gpg_sign.py
> index ada1b2f..ef47d1a 100644
> --- a/meta/lib/oe/gpg_sign.py
> +++ b/meta/lib/oe/gpg_sign.py
> @@ -1,5 +1,6 @@
> """Helper module for GPG signing"""
> import os
> +import sys
>
> import bb
> import oe.utils
> @@ -50,6 +51,7 @@ class LocalSigner(object):
> bb.error('rpmsign failed: %s' % proc.before.strip())
> raise bb.build.FuncFailed("Failed to sign RPM packages")
>
> +
> def detach_sign(self, input_file, keyid, passphrase_file,
> passphrase=None, armor=True):
> """Create a detached signature of a file"""
> import subprocess
> @@ -57,23 +59,45 @@ class LocalSigner(object):
> if passphrase_file and passphrase:
> raise Exception("You should use either passphrase_file
> of passphrase, not both")
>
> - cmd = [self.gpg_bin, '--detach-sign', '--batch', '--no-tty',
> '--yes',
> - '-u', keyid]
> - if passphrase_file:
> - cmd += ['--passphrase-file', passphrase_file]
> - else:
> - cmd += ['--passphrase-fd', '0']
> + cmd = [self.gpg_bin, '--detach-sign', '--batch', '--no-tty',
> '--yes', '-u', keyid]
> +
> if self.gpg_path:
> cmd += ['--homedir', self.gpg_path]
> if armor:
> cmd += ['--armor']
> - cmd.append(input_file)
> - job = subprocess.Popen(cmd, stdin=subprocess.PIPE,
> stdout=subprocess.PIPE,
> - stderr=subprocess.PIPE)
> - _, stderr = job.communicate(passphrase)
> - if job.returncode:
> - raise bb.build.FuncFailed("Failed to create signature
> for '%s': %s" %
> - (input_file, stderr))
> +
> + try:
> + keypipe = os.pipe()
> +
> + if passphrase_file:
> + with open(passphrase_file) as fobj:
> + os.write(keypipe[1], fobj.readline());
> + else:
> + os.write(keypipe[1], passphrase)
> +
> + cmd += ["--passphrase-fd", str(keypipe[0])]
> + cmd += [input_file]
> +
> + job = subprocess.Popen(cmd, stdin=subprocess.PIPE,
> stderr=subprocess.PIPE)
> + (_, stderr) = job.communicate(passphrase)
> +
> + os.close(keypipe[1])
> + os.close(keypipe[0])
I still fail to see why you want to complicate the code with os.pipe.
Why not ditch pipe and just do something like:
if passphrase_file:
with open(passphrase_file) as fobj:
_, stderr = job.communicate(fobj.readline())
Thanks,
Markus
> +
> + if job.returncode:
> + raise bb.build.FuncFailed("GPG exited with code %d:
> %s" %
> + (job.returncode, stderr))
> +
> + except IOError as e:
> + bb.error("IO error (%s): %s" % (e.errno, e.strerror))
> + raise Exception("Failed to sign '%s'" % input_file)
> + except OSError as e:
> + bb.error("OS error (%s): %s" % (e.errno, e.strerror))
> + raise Exception("Failed to sign '%s" % input_file)
> + except:
> + bb.error("Unexpected error (%s): %s" %
> (sys.exc_info()[0], sys.exc_info()[1]))
> + raise Exception("Failed to sign '%s'" % input_file)
> +
>
> def verify(self, sig_file):
> """Verify signature"""
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v6 2/4] gpg_sign: detach_sign: fix gpg > 2.1 STDIN file descriptor
2016-02-19 15:45 ` [PATCH v6 2/4] gpg_sign: detach_sign: fix gpg > 2.1 STDIN file descriptor Ioan-Adrian Ratiu
@ 2016-02-23 10:26 ` Markus Lehtonen
0 siblings, 0 replies; 8+ messages in thread
From: Markus Lehtonen @ 2016-02-23 10:26 UTC (permalink / raw)
To: Ioan-Adrian Ratiu, openembedded-core
Hi,
Resending as my I got a strange "Only members may post to the list."
error yesterday...
On Fri, 2016-02-19 at 17:43 +0200, Ioan-Adrian Ratiu wrote:
> Starting from v2.1 passing passwords directly to gpg does not work
> anymore [1], instead a loopback interface must be used otherwise
> gpg >2.1 will error out with:
> "gpg: signing failed: Inappropriate ioctl for device"
>
> gpg <2.1 does not work with the new --pinentry-mode arg and gives an
> invalid option error, so we detect what is the running version of gpg
> and pass it accordingly.
>
> [1] https://wiki.archlinux.org/index.php/GnuPG#Unattended_passphrase
>
> Signed-off-by: Ioan-Adrian Ratiu <adrian.ratiu@ni.com>
> ---
> meta/lib/oe/gpg_sign.py | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
> diff --git a/meta/lib/oe/gpg_sign.py b/meta/lib/oe/gpg_sign.py
> index ef47d1a..9f6b0f0 100644
> --- a/meta/lib/oe/gpg_sign.py
> +++ b/meta/lib/oe/gpg_sign.py
> @@ -66,6 +66,12 @@ class LocalSigner(object):
> if armor:
> cmd += ['--armor']
>
> + #gpg > 2.1 supports password pipes only through the loopback
> interface
> + #gpg < 2.1 errors out if given unknown parameters
> + gpg_ver = self.get_gpg_version()
> + if gpg_ver > 2.1:
> + cmd += ['--pinentry-mode', 'loopback']
> +
As far as I can tell get_gpg_version returns a string. However, you
compare that with a float. This should give more correct behavior:
+ if gpg_ver > "2.1":
Thanks,
Markus
> try:
> keypipe = os.pipe()
>
> @@ -99,6 +105,20 @@ class LocalSigner(object):
> raise Exception("Failed to sign '%s'" % input_file)
>
>
> + def get_gpg_version(self):
> + """Return the gpg version"""
> + import subprocess
> +
> + job = subprocess.Popen([self.gpg_bin, "--version"],
> stdout=subprocess.PIPE)
> + (stdout, _) = job.communicate()
> +
> + if job.returncode:
> + raise bb.build.FuncFailed("Could not get gpg version (is
> %s installed?)" %
> + self.gpg_bin)
> +
> + return stdout.split()[2]
> +
> +
> def verify(self, sig_file):
> """Verify signature"""
> cmd = self.gpg_bin + " --verify "
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v6 0/4] IPK signing for the gpg_sign module
2016-02-19 15:45 [PATCH v6 0/4] IPK signing for the gpg_sign module Ioan-Adrian Ratiu
` (3 preceding siblings ...)
2016-02-19 15:45 ` [PATCH v6 4/4] package_manager: sign IPK package feeds Ioan-Adrian Ratiu
@ 2016-02-23 10:28 ` Markus Lehtonen
4 siblings, 0 replies; 8+ messages in thread
From: Markus Lehtonen @ 2016-02-23 10:28 UTC (permalink / raw)
To: Ioan-Adrian Ratiu, openembedded-core
Hi,
Resending as my I got a strange "Only members may post to the list."
error yesterday...
On Fri, 2016-02-19 at 17:45 +0200, Ioan-Adrian Ratiu wrote:
> This patch series extends the gpg_sign module to support ipk signing.
>
> v6 implements Markus' feedback. The most notable change is the
> sign_ipk
> and detach_sign merger, as they were almost identical in
> functionality.
> This also meant a refactoring for detach_sign and a bug fix for the
> STDIN file descriptor introduced in gpg > 2.1.
>
> Technically that STDIN bug is a feature (meh) of gpg >2.1 which
> breaks
> existing behaviour so we have to work around it i.e. check the gpg
> version and use the loopback interface. This means that gpg-agent to
> which gpg >2.1 always connects needs to be running permanently.
>
> Ioan-Adrian Ratiu (4):
> gpg_sign: add local ipk package signing functionality
> gpg_sign: detach_sign: fix gpg > 2.1 STDIN file descriptor
> gpg_sign: export_pubkey: add signature type support
> package_manager: sign IPK package feeds
>
> meta/classes/package_ipk.bbclass | 5 +++
> meta/classes/sign_ipk.bbclass | 52 ++++++++++++++++++++++++
> meta/classes/sign_package_feed.bbclass | 12 +++++-
> meta/lib/oe/gpg_sign.py | 74
> +++++++++++++++++++++++++++-------
> meta/lib/oe/package_manager.py | 17 +++++++-
> 5 files changed, 143 insertions(+), 17 deletions(-)
> create mode 100644 meta/classes/sign_ipk.bbclass
I just realized that it would be good to add the ipk signing key to the
signing_keys.bb recipe.
However, it'd probably be good to write it on top of Randy Witt's
rework:
http://lists.openembedded.org/pipermail/openembedded-core/2016-February
/117791.html
Thanks,
Markus
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2016-02-23 10:28 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-19 15:45 [PATCH v6 0/4] IPK signing for the gpg_sign module Ioan-Adrian Ratiu
2016-02-19 15:45 ` [PATCH v6 1/4] gpg_sign: add local ipk package signing functionality Ioan-Adrian Ratiu
2016-02-23 10:25 ` Markus Lehtonen
2016-02-19 15:45 ` [PATCH v6 2/4] gpg_sign: detach_sign: fix gpg > 2.1 STDIN file descriptor Ioan-Adrian Ratiu
2016-02-23 10:26 ` Markus Lehtonen
2016-02-19 15:45 ` [PATCH v6 3/4] gpg_sign: export_pubkey: add signature type support Ioan-Adrian Ratiu
2016-02-19 15:45 ` [PATCH v6 4/4] package_manager: sign IPK package feeds Ioan-Adrian Ratiu
2016-02-23 10:28 ` [PATCH v6 0/4] IPK signing for the gpg_sign module Markus Lehtonen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox