Update upstream source from tag 'upstream/2020.4'

Update to upstream version '2020.4'
with Debian dir 3d4cd523c8
This commit is contained in:
Simon McVittie 2020-07-27 21:38:33 +01:00
commit c6c498db7d
129 changed files with 7441 additions and 1244 deletions

View File

@ -46,6 +46,8 @@ libostree_public_headers = \
src/libostree/ostree-repo-finder-mount.h \
src/libostree/ostree-repo-finder-override.h \
src/libostree/ostree-kernel-args.h \
src/libostree/ostree-sign.h \
src/libostree/ostree-sign-ed25519.h \
$(NULL)
# This one is generated via configure.ac, and the gtk-doc

View File

@ -95,6 +95,7 @@ libostree_1_la_SOURCES = \
src/libostree/ostree-repo-commit.c \
src/libostree/ostree-repo-pull.c \
src/libostree/ostree-repo-pull-private.h \
src/libostree/ostree-repo-pull-verify.c \
src/libostree/ostree-repo-libarchive.c \
src/libostree/ostree-repo-prune.c \
src/libostree/ostree-repo-refs.c \
@ -262,6 +263,20 @@ libostree_1_la_CFLAGS += $(OT_DEP_SELINUX_CFLAGS)
libostree_1_la_LIBADD += $(OT_DEP_SELINUX_LIBS)
endif
libostree_1_la_SOURCES += \
src/libostree/ostree-sign.c \
src/libostree/ostree-sign.h \
src/libostree/ostree-sign-dummy.c \
src/libostree/ostree-sign-dummy.h \
src/libostree/ostree-sign-ed25519.c \
src/libostree/ostree-sign-ed25519.h \
$(NULL)
if USE_LIBSODIUM
libostree_1_la_CFLAGS += $(OT_DEP_LIBSODIUM_CFLAGS)
libostree_1_la_LIBADD += $(OT_DEP_LIBSODIUM_LIBS)
endif # USE_LIBSODIUM
# XXX: work around clang being passed -fstack-clash-protection which it doesn't understand
# See: https://bugzilla.redhat.com/show_bug.cgi?id=1672012
INTROSPECTION_SCANNER_ENV = CC=gcc

View File

@ -32,7 +32,7 @@ ostree-commit.1 ostree-create-usb.1 ostree-export.1 \
ostree-config.1 ostree-diff.1 ostree-find-remotes.1 ostree-fsck.1 \
ostree-init.1 ostree-log.1 ostree-ls.1 ostree-prune.1 ostree-pull-local.1 \
ostree-pull.1 ostree-refs.1 ostree-remote.1 ostree-reset.1 \
ostree-rev-parse.1 ostree-show.1 ostree-summary.1 \
ostree-rev-parse.1 ostree-show.1 ostree-sign.1 ostree-summary.1 \
ostree-static-delta.1
if USE_LIBSOUP
man1_files += ostree-trivial-httpd.1

View File

@ -43,6 +43,7 @@ ostree_SOURCES = src/ostree/main.c \
src/ostree/ot-builtin-remote.c \
src/ostree/ot-builtin-reset.c \
src/ostree/ot-builtin-rev-parse.c \
src/ostree/ot-builtin-sign.c \
src/ostree/ot-builtin-summary.c \
src/ostree/ot-builtin-show.c \
src/ostree/ot-builtin-static-delta.c \
@ -112,7 +113,6 @@ ostree_SOURCES += \
$(NULL)
endif
if USE_CURL_OR_SOUP
ostree_SOURCES += src/ostree/ot-remote-builtin-add-cookie.c \
src/ostree/ot-remote-builtin-delete-cookie.c \
@ -162,3 +162,8 @@ if USE_LIBARCHIVE
ostree_CFLAGS += $(OT_DEP_LIBARCHIVE_CFLAGS)
ostree_LDADD += $(OT_DEP_LIBARCHIVE_LIBS)
endif
if USE_LIBSODIUM
ostree_CFLAGS += $(OT_DEP_LIBSODIUM_CFLAGS)
ostree_LDADD += $(OT_DEP_LIBSODIUM_LIBS)
endif # USE_LIBSODIUM

View File

@ -102,6 +102,7 @@ _installed_or_uninstalled_test_scripts = \
tests/test-admin-deploy-etcmerge-cornercases.sh \
tests/test-admin-deploy-uboot.sh \
tests/test-admin-deploy-grub2.sh \
tests/test-admin-deploy-nomerge.sh \
tests/test-admin-deploy-none.sh \
tests/test-admin-deploy-bootid-gc.sh \
tests/test-admin-instutil-set-kargs.sh \
@ -137,6 +138,10 @@ _installed_or_uninstalled_test_scripts = \
tests/test-summary-collections.sh \
tests/test-pull-collections.sh \
tests/test-config.sh \
tests/test-signed-commit.sh \
tests/test-signed-pull.sh \
tests/test-pre-signed-pull.sh \
tests/test-signed-pull-summary.sh \
$(NULL)
if USE_GPGME
@ -197,6 +202,7 @@ dist_installed_test_data = tests/archive-test.sh \
tests/fah-deltadata-old.tar.xz \
tests/fah-deltadata-new.tar.xz \
tests/ostree-path-traverse.tar.gz \
tests/pre-signed-pull-data.tar.gz \
tests/libtest-core.sh \
$(NULL)
@ -452,3 +458,10 @@ else
endif
INSTALL_DATA_HOOKS += install-installed-tests-extra
endif
# Just forward these
build-kola-tests:
$(MAKE) -C tests/kola
install-kola-tests:
$(MAKE) -C tests/kola install

File diff suppressed because it is too large Load Diff

View File

@ -147,7 +147,7 @@ New! See the docs online at [Read The Docs (OSTree)](https://ostree.readthedocs.
Contributing
------------
See [Contributing](CONTRIBUTING.md).
See [Contributing](docs/CONTRIBUTING.md).
Licensing

58
aclocal.m4 vendored
View File

@ -568,6 +568,47 @@ dnl
# serial 1
dnl This is a copy of AS_AC_EXPAND
dnl
dnl (C) 2003, 2004, 2005 Thomas Vander Stichele <thomas at apestaart dot org>
dnl Copying and distribution of this file, with or without modification,
dnl are permitted in any medium without royalty provided the copyright
dnl notice and this notice are preserved.
m4_define([_GOBJECT_INTROSPECTION_AS_AC_EXPAND],
[
EXP_VAR=[$1]
FROM_VAR=[$2]
dnl first expand prefix and exec_prefix if necessary
prefix_save=$prefix
exec_prefix_save=$exec_prefix
dnl if no prefix given, then use /usr/local, the default prefix
if test "x$prefix" = "xNONE"; then
prefix="$ac_default_prefix"
fi
dnl if no exec_prefix given, then use prefix
if test "x$exec_prefix" = "xNONE"; then
exec_prefix=$prefix
fi
full_var="$FROM_VAR"
dnl loop until it doesn't change anymore
while true; do
new_full_var="`eval echo $full_var`"
if test "x$new_full_var" = "x$full_var"; then break; fi
full_var=$new_full_var
done
dnl clean up
full_var=$new_full_var
AC_SUBST([$1], "$full_var")
dnl restore prefix and exec_prefix
prefix=$prefix_save
exec_prefix=$exec_prefix_save
])
m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL],
[
AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
@ -610,20 +651,25 @@ m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL],
AC_MSG_RESULT([$found_introspection])
dnl expand datadir/libdir so we can pass them to pkg-config
dnl and get paths relative to our target directories
_GOBJECT_INTROSPECTION_AS_AC_EXPAND(_GI_EXP_DATADIR, "$datadir")
_GOBJECT_INTROSPECTION_AS_AC_EXPAND(_GI_EXP_LIBDIR, "$libdir")
INTROSPECTION_SCANNER=
INTROSPECTION_COMPILER=
INTROSPECTION_GENERATE=
INTROSPECTION_GIRDIR=
INTROSPECTION_TYPELIBDIR=
if test "x$found_introspection" = "xyes"; then
INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
INTROSPECTION_SCANNER=$PKG_CONFIG_SYSROOT_DIR`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
INTROSPECTION_COMPILER=$PKG_CONFIG_SYSROOT_DIR`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
INTROSPECTION_GENERATE=$PKG_CONFIG_SYSROOT_DIR`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
INTROSPECTION_GIRDIR=`$PKG_CONFIG --define-variable=datadir="${_GI_EXP_DATADIR}" --variable=girdir gobject-introspection-1.0`
INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --define-variable=libdir="${_GI_EXP_LIBDIR}" --variable=typelibdir gobject-introspection-1.0)"
INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0`
INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0`
INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection
INTROSPECTION_MAKEFILE=$PKG_CONFIG_SYSROOT_DIR`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection
fi
AC_SUBST(INTROSPECTION_SCANNER)
AC_SUBST(INTROSPECTION_COMPILER)

View File

@ -295,6 +295,8 @@ OT_DEP_LIBARCHIVE_CFLAGS = @OT_DEP_LIBARCHIVE_CFLAGS@
OT_DEP_LIBARCHIVE_LIBS = @OT_DEP_LIBARCHIVE_LIBS@
OT_DEP_LIBMOUNT_CFLAGS = @OT_DEP_LIBMOUNT_CFLAGS@
OT_DEP_LIBMOUNT_LIBS = @OT_DEP_LIBMOUNT_LIBS@
OT_DEP_LIBSODIUM_CFLAGS = @OT_DEP_LIBSODIUM_CFLAGS@
OT_DEP_LIBSODIUM_LIBS = @OT_DEP_LIBSODIUM_LIBS@
OT_DEP_LZMA_CFLAGS = @OT_DEP_LZMA_CFLAGS@
OT_DEP_LZMA_LIBS = @OT_DEP_LZMA_LIBS@
OT_DEP_SELINUX_CFLAGS = @OT_DEP_SELINUX_CFLAGS@
@ -328,6 +330,8 @@ XSLTPROC = @XSLTPROC@
YACC = @YACC@
YEAR_VERSION = @YEAR_VERSION@
YFLAGS = @YFLAGS@
_GI_EXP_DATADIR = @_GI_EXP_DATADIR@
_GI_EXP_LIBDIR = @_GI_EXP_LIBDIR@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
@ -412,6 +416,8 @@ libostree_public_headers = \
src/libostree/ostree-repo-finder-mount.h \
src/libostree/ostree-repo-finder-override.h \
src/libostree/ostree-kernel-args.h \
src/libostree/ostree-sign.h \
src/libostree/ostree-sign-ed25519.h \
$(NULL)

View File

@ -6,7 +6,7 @@
<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
<link rel="home" href="index.html" title="OSTree API references">
<link rel="next" href="reference.html" title="API Reference">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -14,7 +14,7 @@
<div class="titlepage">
<div>
<div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">OSTree API references</p></th></tr></table></div>
<div><p class="releaseinfo">for OSTree 2020.3</p></div>
<div><p class="releaseinfo">for OSTree 2020.4</p></div>
</div>
<hr>
</div>
@ -46,6 +46,9 @@
<span class="refentrytitle"><a href="ostree-GPG-signature-verification-results.html">GPG signature verification results</a></span><span class="refpurpose"> — Inspect detached GPG signatures</span>
</dt>
<dt>
<span class="refentrytitle"><a href="ostree-Signature-management.html">Signature management</a></span><span class="refpurpose"> — Sign and verify commits</span>
</dt>
<dt>
<span class="refentrytitle"><a href="ostree-ostree-bootconfig-parser.html">ostree-bootconfig-parser</a></span><span class="refpurpose"></span>
</dt>
<dt>
@ -68,6 +71,6 @@
</dl></div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -8,7 +8,7 @@
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="reference.html" title="API Reference">
<link rel="next" href="ostree-OstreeRepo.html" title="OstreeRepo: Content-addressed object store">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -35,8 +35,8 @@
<a name="ostree-Core-repository-independent-functions.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_return">
<col class="functions_name">
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody>
<tr>
@ -472,8 +472,8 @@
<a name="ostree-Core-repository-independent-functions.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="name">
<col class="description">
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody>
<tr>
@ -2382,6 +2382,26 @@ if none</p>
<a name="ostree-commit-get-timestamp"></a><h3>ostree_commit_get_timestamp ()</h3>
<pre class="programlisting"><span class="returnvalue">guint64</span>
ostree_commit_get_timestamp (<em class="parameter"><code><span class="type">GVariant</span> *commit_variant</code></em>);</pre>
<div class="refsect3">
<a name="ostree-commit-get-timestamp.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody><tr>
<td class="parameter_name"><p>commit_variant</p></td>
<td class="parameter_description"><p>Commit object</p></td>
<td class="parameter_annotations"> </td>
</tr></tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-commit-get-timestamp.returns"></a><h4>Returns</h4>
<p> timestamp in seconds since the Unix epoch, UTC</p>
</div>
<p class="since">Since: 2016.3</p>
</div>
<hr>
<div class="refsect2">
@ -2850,6 +2870,6 @@ entry corresponds to an object in the associated commit.</p>
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -7,8 +7,8 @@
<link rel="home" href="index.html" title="OSTree API references">
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="ostree-Simple-upgrade-class.html" title="Simple upgrade class">
<link rel="next" href="ostree-ostree-bootconfig-parser.html" title="ostree-bootconfig-parser">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<link rel="next" href="ostree-Signature-management.html" title="Signature management">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -20,7 +20,7 @@
<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
<td><a accesskey="u" href="reference.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
<td><a accesskey="p" href="ostree-Simple-upgrade-class.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
<td><a accesskey="n" href="ostree-ostree-bootconfig-parser.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
<td><a accesskey="n" href="ostree-Signature-management.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
</tr></table>
<div class="refentry">
<a name="ostree-GPG-signature-verification-results"></a><div class="titlepage"></div>
@ -35,8 +35,8 @@
<a name="ostree-GPG-signature-verification-results.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_return">
<col class="functions_name">
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody>
<tr>
@ -110,8 +110,8 @@
<a name="ostree-GPG-signature-verification-results.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="name">
<col class="description">
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody>
<tr>
@ -564,7 +564,7 @@ These may be returned by any API which creates or verifies signatures.</p>
<td class="enum_member_name"><p><a name="OSTREE-GPG-ERROR-EXPIRED-KEY:CAPS"></a>OSTREE_GPG_ERROR_EXPIRED_KEY</p></td>
<td class="enum_member_description">
<p>A signature was found, but the key used to
sign it has expired. Since: 2020.1.</p>
sign it has expired. Since: 2020.1.</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
@ -572,7 +572,7 @@ These may be returned by any API which creates or verifies signatures.</p>
<td class="enum_member_name"><p><a name="OSTREE-GPG-ERROR-REVOKED-KEY:CAPS"></a>OSTREE_GPG_ERROR_REVOKED_KEY</p></td>
<td class="enum_member_description">
<p>A signature was found, but the key used to
sign it has been revoked. Since: 2020.1.</p>
sign it has been revoked. Since: 2020.1.</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
@ -605,116 +605,116 @@ The attribute's <span class="type">GVariantType</span> is shown in brackets.</p>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-VALID:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_VALID</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_BOOLEAN</span>] Is the signature valid?</p>
<p>[<span class="type">G_VARIANT_TYPE_BOOLEAN</span>] Is the signature valid?</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-SIG-EXPIRED:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_SIG_EXPIRED</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_BOOLEAN</span>] Has the signature expired?</p>
<p>[<span class="type">G_VARIANT_TYPE_BOOLEAN</span>] Has the signature expired?</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-KEY-EXPIRED:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_KEY_EXPIRED</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_BOOLEAN</span>] Has the signing key expired?</p>
<p>[<span class="type">G_VARIANT_TYPE_BOOLEAN</span>] Has the signing key expired?</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-KEY-REVOKED:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_KEY_REVOKED</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_BOOLEAN</span>] Has the signing key been revoked?</p>
<p>[<span class="type">G_VARIANT_TYPE_BOOLEAN</span>] Has the signing key been revoked?</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-KEY-MISSING:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_KEY_MISSING</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_BOOLEAN</span>] Is the signing key missing?</p>
<p>[<span class="type">G_VARIANT_TYPE_BOOLEAN</span>] Is the signing key missing?</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-FINGERPRINT:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_STRING</span>] Fingerprint of the signing key</p>
<p>[<span class="type">G_VARIANT_TYPE_STRING</span>] Fingerprint of the signing key</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-TIMESTAMP:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_TIMESTAMP</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_INT64</span>] Signature creation Unix timestamp</p>
<p>[<span class="type">G_VARIANT_TYPE_INT64</span>] Signature creation Unix timestamp</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-EXP-TIMESTAMP:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_EXP_TIMESTAMP</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_INT64</span>] Signature expiration Unix timestamp (0 if no
expiration)</p>
<p>[<span class="type">G_VARIANT_TYPE_INT64</span>] Signature expiration Unix timestamp (0 if no
expiration)</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-PUBKEY-ALGO-NAME:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_PUBKEY_ALGO_NAME</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_STRING</span>] Name of the public key algorithm used to create
the signature</p>
<p>[<span class="type">G_VARIANT_TYPE_STRING</span>] Name of the public key algorithm used to create
the signature</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-HASH-ALGO-NAME:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_HASH_ALGO_NAME</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_STRING</span>] Name of the hash algorithm used to create the
signature</p>
<p>[<span class="type">G_VARIANT_TYPE_STRING</span>] Name of the hash algorithm used to create the
signature</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-USER-NAME:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_USER_NAME</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_STRING</span>] The name of the signing key's primary user</p>
<p>[<span class="type">G_VARIANT_TYPE_STRING</span>] The name of the signing key's primary user</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-USER-EMAIL:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_USER_EMAIL</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_STRING</span>] The email address of the signing key's primary
user</p>
<p>[<span class="type">G_VARIANT_TYPE_STRING</span>] The email address of the signing key's primary
user</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-FINGERPRINT-PRIMARY:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_STRING</span>] Fingerprint of the signing key's primary key
(will be the same as OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT if the
the signature is already from the primary key rather than a subkey,
and will be the empty string if the key is missing.)</p>
<p>[<span class="type">G_VARIANT_TYPE_STRING</span>] Fingerprint of the signing key's primary key
(will be the same as OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT if the
the signature is already from the primary key rather than a subkey,
and will be the empty string if the key is missing.)</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-KEY-EXP-TIMESTAMP:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_INT64</span>] Key expiration Unix timestamp (0 if no
expiration or if the key is missing)</p>
<p>[<span class="type">G_VARIANT_TYPE_INT64</span>] Key expiration Unix timestamp (0 if no
expiration or if the key is missing)</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-ATTR-KEY-EXP-TIMESTAMP-PRIMARY:CAPS"></a>OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY</p></td>
<td class="enum_member_description">
<p> [<span class="type">G_VARIANT_TYPE_INT64</span>] Key expiration Unix timestamp of the signing key's
primary key (will be the same as OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP
if the signing key is the primary key and 0 if no expiration or if the key
is missing)</p>
<p>[<span class="type">G_VARIANT_TYPE_INT64</span>] Key expiration Unix timestamp of the signing key's
primary key (will be the same as OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP
if the signing key is the primary key and 0 if no expiration or if the key
is missing)</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
@ -739,7 +739,7 @@ for future variations.</p>
<tbody><tr>
<td class="enum_member_name"><p><a name="OSTREE-GPG-SIGNATURE-FORMAT-DEFAULT:CAPS"></a>OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT</p></td>
<td class="enum_member_description">
<p> Use the default output format</p>
<p>Use the default output format</p>
</td>
<td class="enum_member_annotations"> </td>
</tr></tbody>
@ -749,6 +749,6 @@ for future variations.</p>
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -8,7 +8,7 @@
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="ostree-OstreeRepo.html" title="OstreeRepo: Content-addressed object store">
<link rel="next" href="ostree-Root-partition-mount-point.html" title="Root partition mount point">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -35,8 +35,8 @@
<a name="ostree-In-memory-modifiable-filesystem-tree.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_return">
<col class="functions_name">
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody>
<tr>
@ -172,8 +172,8 @@
<a name="ostree-In-memory-modifiable-filesystem-tree.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="name">
<col class="description">
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody><tr>
<td class="typedef_keyword">typedef</td>
@ -622,6 +622,6 @@ the contents will be loaded only when needed.</p>
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -8,7 +8,7 @@
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="ostree-Core-repository-independent-functions.html" title="Core repository-independent functions">
<link rel="next" href="ostree-In-memory-modifiable-filesystem-tree.html" title="In-memory modifiable filesystem tree">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -35,8 +35,8 @@
<a name="ostree-OstreeRepo.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_return">
<col class="functions_name">
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody>
<tr>
@ -695,6 +695,14 @@
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-OstreeRepo.html#ostree-repo-commit-modifier-set-sepolicy-from-commit" title="ostree_repo_commit_modifier_set_sepolicy_from_commit ()">ostree_repo_commit_modifier_set_sepolicy_from_commit</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">void</span>
</td>
<td class="function_name">
@ -1156,8 +1164,8 @@
<a name="ostree-OstreeRepo.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="name">
<col class="description">
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody>
<tr>
@ -5232,6 +5240,48 @@ policy wins.</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-repo-commit-modifier-set-sepolicy-from-commit"></a><h3>ostree_repo_commit_modifier_set_sepolicy_from_commit ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_repo_commit_modifier_set_sepolicy_from_commit
(<em class="parameter"><code><a class="link" href="ostree-OstreeRepo.html#OstreeRepoCommitModifier" title="OstreeRepoCommitModifier"><span class="type">OstreeRepoCommitModifier</span></a> *modifier</code></em>,
<em class="parameter"><code><a class="link" href="ostree-OstreeRepo.html#OstreeRepo" title="OstreeRepo"><span class="type">OstreeRepo</span></a> *repo</code></em>,
<em class="parameter"><code>const <span class="type">char</span> *rev</code></em>,
<em class="parameter"><code><span class="type">GCancellable</span> *cancellable</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
<p>In many cases, one wants to create a "derived" commit from base commit.
SELinux policy labels are part of that base commit. This API allows
one to easily set up SELinux labeling from a base commit.</p>
<div class="refsect3">
<a name="ostree-repo-commit-modifier-set-sepolicy-from-commit.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody>
<tr>
<td class="parameter_name"><p>modifier</p></td>
<td class="parameter_description"><p>Commit modifier</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>repo</p></td>
<td class="parameter_description"><p>OSTree repo containing <em class="parameter"><code>rev</code></em>
</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>rev</p></td>
<td class="parameter_description"><p>Find SELinux policy from this base commit</p></td>
<td class="parameter_annotations"> </td>
</tr>
</tbody>
</table></div>
</div>
</div>
<hr>
<div class="refsect2">
<a name="ostree-repo-commit-modifier-set-devino-cache"></a><h3>ostree_repo_commit_modifier_set_devino_cache ()</h3>
<pre class="programlisting"><span class="returnvalue">void</span>
ostree_repo_commit_modifier_set_devino_cache
@ -7415,11 +7465,15 @@ string to pull the latest commit for that ref</p></li>
<li class="listitem"><p>override-remote-name (s): If local, add this remote to refspec</p></li>
<li class="listitem"><p>gpg-verify (b): GPG verify commits</p></li>
<li class="listitem"><p>gpg-verify-summary (b): GPG verify summary</p></li>
<li class="listitem"><p>disable-sign-verify (b): Disable signapi verification of commits</p></li>
<li class="listitem"><p>disable-sign-verify-summary (b): Disable signapi verification of the summary</p></li>
<li class="listitem"><p>depth (i): How far in the history to traverse; default is 0, -1 means infinite</p></li>
<li class="listitem"><p>per-object-fsync (b): Perform disk writes more slowly, avoiding a single large I/O sync</p></li>
<li class="listitem"><p>disable-static-deltas (b): Do not use static deltas</p></li>
<li class="listitem"><p>require-static-deltas (b): Require static deltas</p></li>
<li class="listitem"><p>override-commit-ids (as): Array of specific commit IDs to fetch for refs</p></li>
<li class="listitem"><p>timestamp-check (b): Verify commit timestamps are newer than current (when pulling via ref); Since: 2017.11</p></li>
<li class="listitem"><p>timestamp-check-from-rev (s): Verify that all fetched commit timestamps are newer than timestamp of given rev; Since: 2020.4</p></li>
<li class="listitem"><p>metadata-size-restriction (t): Restrict metadata objects to a maximum number of bytes; 0 to disable. Since: 2018.9</p></li>
<li class="listitem"><p>dry-run (b): Only print information on what will be downloaded (requires static deltas)</p></li>
<li class="listitem"><p>override-url (s): Fetch objects from this URL if remote specifies no metalink in options</p></li>
@ -8344,7 +8398,7 @@ by <a class="link" href="ostree-OstreeRepo.html#ostree-repo-load-commit" title="
<td class="enum_member_name"><p><a name="OSTREE-REPO-COMMIT-STATE-NORMAL:CAPS"></a>OSTREE_REPO_COMMIT_STATE_NORMAL</p></td>
<td class="enum_member_description">
<p>Commit is complete. This is the default.
(Since: 2017.14.)</p>
(Since: 2017.14.)</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
@ -8352,7 +8406,7 @@ by <a class="link" href="ostree-OstreeRepo.html#ostree-repo-load-commit" title="
<td class="enum_member_name"><p><a name="OSTREE-REPO-COMMIT-STATE-PARTIAL:CAPS"></a>OSTREE_REPO_COMMIT_STATE_PARTIAL</p></td>
<td class="enum_member_description">
<p>One or more objects are missing from the
local copy of the commit, but metadata is present. (Since: 2015.7.)</p>
local copy of the commit, but metadata is present. (Since: 2015.7.)</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
@ -8360,7 +8414,7 @@ by <a class="link" href="ostree-OstreeRepo.html#ostree-repo-load-commit" title="
<td class="enum_member_name"><p><a name="OSTREE-REPO-COMMIT-STATE-FSCK-PARTIAL:CAPS"></a>OSTREE_REPO_COMMIT_STATE_FSCK_PARTIAL</p></td>
<td class="enum_member_description">
<p>One or more objects are missing from the
local copy of the commit, due to an fsck --delete. (Since: 2019.4.)</p>
local copy of the commit, due to an fsck --delete. (Since: 2019.4.)</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
@ -8816,6 +8870,6 @@ as - List of pack file checksums in which this object appears</p>
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -8,7 +8,7 @@
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="ostree-Root-partition-mount-point.html" title="Root partition mount point">
<link rel="next" href="ostree-SELinux-policy-management.html" title="SELinux policy management">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -35,8 +35,8 @@
<a name="ostree-Progress-notification-system-for-asynchronous-operations.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_return">
<col class="functions_name">
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody>
<tr>
@ -158,8 +158,8 @@
<a name="ostree-Progress-notification-system-for-asynchronous-operations.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="name">
<col class="description">
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody><tr>
<td class="typedef_keyword">typedef</td>
@ -298,17 +298,17 @@ function returns.</p>
9
10
11</pre></td>
<td class="listing_code"><pre class="programlisting"><span class="usertype">guint32</span><span class="normal"> outstanding_fetches</span><span class="symbol">;</span>
<span class="usertype">guint64</span><span class="normal"> bytes_received</span><span class="symbol">;</span>
<span class="usertype">g_autofree</span><span class="normal"> </span><span class="usertype">gchar</span><span class="normal"> </span><span class="symbol">*</span><span class="normal">status </span><span class="symbol">=</span><span class="normal"> NULL</span><span class="symbol">;</span>
<span class="function">g_autoptr</span><span class="symbol">(</span><span class="normal">GVariant</span><span class="symbol">)</span><span class="normal"> refs_variant </span><span class="symbol">=</span><span class="normal"> NULL</span><span class="symbol">;</span>
<td class="listing_code"><pre class="programlisting"><span class="n">guint32</span> <span class="n">outstanding_fetches</span><span class="p">;</span>
<span class="n">guint64</span> <span class="n">bytes_received</span><span class="p">;</span>
<span class="n">g_autofree</span> <span class="n">gchar</span> <span class="o">*</span><span class="n">status</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">g_autoptr</span><span class="p">(</span><span class="n">GVariant</span><span class="p">)</span> <span class="n">refs_variant</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="function"><a href="ostree-Progress-notification-system-for-asynchronous-operations.html#ostree-async-progress-get">ostree_async_progress_get</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">progress</span><span class="symbol">,</span>
<span class="normal"> </span><span class="string">"outstanding-fetches"</span><span class="symbol">,</span><span class="normal"> </span><span class="string">"u"</span><span class="symbol">,</span><span class="normal"> </span><span class="symbol">&amp;</span><span class="normal">outstanding_fetches</span><span class="symbol">,</span>
<span class="normal"> </span><span class="string">"bytes-received"</span><span class="symbol">,</span><span class="normal"> </span><span class="string">"t"</span><span class="symbol">,</span><span class="normal"> </span><span class="symbol">&amp;</span><span class="normal">bytes_received</span><span class="symbol">,</span>
<span class="normal"> </span><span class="string">"status"</span><span class="symbol">,</span><span class="normal"> </span><span class="string">"s"</span><span class="symbol">,</span><span class="normal"> </span><span class="symbol">&amp;</span><span class="normal">status</span><span class="symbol">,</span>
<span class="normal"> </span><span class="string">"refs"</span><span class="symbol">,</span><span class="normal"> </span><span class="string">"@a{ss}"</span><span class="symbol">,</span><span class="normal"> </span><span class="symbol">&amp;</span><span class="normal">refs_variant</span><span class="symbol">,</span>
<span class="normal"> NULL</span><span class="symbol">);</span></pre></td>
<span class="n">ostree_async_progress_get</span> <span class="p">(</span><span class="n">progress</span><span class="p">,</span>
<span class="s">&quot;outstanding-fetches&quot;</span><span class="p">,</span> <span class="s">&quot;u&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">outstanding_fetches</span><span class="p">,</span>
<span class="s">&quot;bytes-received&quot;</span><span class="p">,</span> <span class="s">&quot;t&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">bytes_received</span><span class="p">,</span>
<span class="s">&quot;status&quot;</span><span class="p">,</span> <span class="s">&quot;s&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">status</span><span class="p">,</span>
<span class="s">&quot;refs&quot;</span><span class="p">,</span> <span class="s">&quot;@a{ss}&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">refs_variant</span><span class="p">,</span>
<span class="nb">NULL</span><span class="p">);</span></pre></td>
</tr>
</tbody>
</table>
@ -452,15 +452,15 @@ parameters, so they may be floating.</p>
7
8
9</pre></td>
<td class="listing_code"><pre class="programlisting"><span class="usertype">guint32</span><span class="normal"> outstanding_fetches </span><span class="symbol">=</span><span class="normal"> </span><span class="number">15</span><span class="symbol">;</span>
<span class="usertype">guint64</span><span class="normal"> bytes_received </span><span class="symbol">=</span><span class="normal"> </span><span class="number">1000</span><span class="symbol">;</span>
<td class="listing_code"><pre class="programlisting"><span class="n">guint32</span> <span class="n">outstanding_fetches</span> <span class="o">=</span> <span class="mi">15</span><span class="p">;</span>
<span class="n">guint64</span> <span class="n">bytes_received</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">;</span>
<span class="function"><a href="ostree-Progress-notification-system-for-asynchronous-operations.html#ostree-async-progress-set">ostree_async_progress_set</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">progress</span><span class="symbol">,</span>
<span class="normal"> </span><span class="string">"outstanding-fetches"</span><span class="symbol">,</span><span class="normal"> </span><span class="string">"u"</span><span class="symbol">,</span><span class="normal"> outstanding_fetches</span><span class="symbol">,</span>
<span class="normal"> </span><span class="string">"bytes-received"</span><span class="symbol">,</span><span class="normal"> </span><span class="string">"t"</span><span class="symbol">,</span><span class="normal"> bytes_received</span><span class="symbol">,</span>
<span class="normal"> </span><span class="string">"status"</span><span class="symbol">,</span><span class="normal"> </span><span class="string">"s"</span><span class="symbol">,</span><span class="normal"> </span><span class="string">"Updated status"</span><span class="symbol">,</span>
<span class="normal"> </span><span class="string">"refs"</span><span class="symbol">,</span><span class="normal"> </span><span class="string">"@a{ss}"</span><span class="symbol">,</span><span class="normal"> </span><span class="function">g_variant_new_parsed</span><span class="normal"> </span><span class="symbol">(</span><span class="string">"@a{ss} {}"</span><span class="symbol">),</span>
<span class="normal"> NULL</span><span class="symbol">);</span></pre></td>
<span class="n">ostree_async_progress_set</span> <span class="p">(</span><span class="n">progress</span><span class="p">,</span>
<span class="s">&quot;outstanding-fetches&quot;</span><span class="p">,</span> <span class="s">&quot;u&quot;</span><span class="p">,</span> <span class="n">outstanding_fetches</span><span class="p">,</span>
<span class="s">&quot;bytes-received&quot;</span><span class="p">,</span> <span class="s">&quot;t&quot;</span><span class="p">,</span> <span class="n">bytes_received</span><span class="p">,</span>
<span class="s">&quot;status&quot;</span><span class="p">,</span> <span class="s">&quot;s&quot;</span><span class="p">,</span> <span class="s">&quot;Updated status&quot;</span><span class="p">,</span>
<span class="s">&quot;refs&quot;</span><span class="p">,</span> <span class="s">&quot;@a{ss}&quot;</span><span class="p">,</span> <span class="n">g_variant_new_parsed</span> <span class="p">(</span><span class="s">&quot;@a{ss} {}&quot;</span><span class="p">),</span>
<span class="nb">NULL</span><span class="p">);</span></pre></td>
</tr>
</tbody>
</table>
@ -589,6 +589,6 @@ events will be queued.</p>
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -8,7 +8,7 @@
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="ostree-In-memory-modifiable-filesystem-tree.html" title="In-memory modifiable filesystem tree">
<link rel="next" href="ostree-Progress-notification-system-for-asynchronous-operations.html" title="Progress notification system for asynchronous operations">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -35,8 +35,8 @@
<a name="ostree-Root-partition-mount-point.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_return">
<col class="functions_name">
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody>
<tr>
@ -390,8 +390,8 @@
<a name="ostree-Root-partition-mount-point.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="name">
<col class="description">
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody>
<tr>
@ -2125,6 +2125,6 @@ later, instead.</p>
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -8,7 +8,7 @@
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="ostree-Progress-notification-system-for-asynchronous-operations.html" title="Progress notification system for asynchronous operations">
<link rel="next" href="ostree-Simple-upgrade-class.html" title="Simple upgrade class">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -35,8 +35,8 @@
<a name="ostree-SELinux-policy-management.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_return">
<col class="functions_name">
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody>
<tr>
@ -116,8 +116,8 @@
<a name="ostree-SELinux-policy-management.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="name">
<col class="description">
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody>
<tr>
@ -486,6 +486,6 @@ ostree_sepolicy_fscreatecon_cleanup (<em class="parameter"><code><span class="ty
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -0,0 +1,865 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Signature management: OSTree API references</title>
<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
<link rel="home" href="index.html" title="OSTree API references">
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="ostree-GPG-signature-verification-results.html" title="GPG signature verification results">
<link rel="next" href="ostree-ostree-bootconfig-parser.html" title="ostree-bootconfig-parser">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
<td width="100%" align="left" class="shortcuts">
<a href="#" class="shortcut">Top</a><span id="nav_description">  <span class="dim">|</span> 
<a href="#ostree-Signature-management.description" class="shortcut">Description</a></span>
</td>
<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
<td><a accesskey="u" href="reference.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
<td><a accesskey="p" href="ostree-GPG-signature-verification-results.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
<td><a accesskey="n" href="ostree-ostree-bootconfig-parser.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
</tr></table>
<div class="refentry">
<a name="ostree-Signature-management"></a><div class="titlepage"></div>
<div class="refnamediv"><table width="100%"><tr>
<td valign="top">
<h2><span class="refentrytitle"><a name="ostree-Signature-management.top_of_page"></a>Signature management</span></h2>
<p>Signature management — Sign and verify commits</p>
</td>
<td class="gallery_image" valign="top" align="right"></td>
</tr></table></div>
<div class="refsect1">
<a name="ostree-Signature-management.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody>
<tr>
<td class="function_type">
<span class="returnvalue">GPtrArray</span> *
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-get-all" title="ostree_sign_get_all ()">ostree_sign_get_all</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-commit" title="ostree_sign_commit ()">ostree_sign_commit</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-commit-verify" title="ostree_sign_commit_verify ()">ostree_sign_commit_verify</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-data" title="ostree_sign_data ()">ostree_sign_data</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-data-verify" title="ostree_sign_data_verify ()">ostree_sign_data_verify</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="returnvalue">OstreeSign</span></a> *
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-get-by-name" title="ostree_sign_get_by_name ()">ostree_sign_get_by_name</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">const <span class="returnvalue">gchar</span> *
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-get-name" title="ostree_sign_get_name ()">ostree_sign_get_name</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-add-pk" title="ostree_sign_add_pk ()">ostree_sign_add_pk</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-clear-keys" title="ostree_sign_clear_keys ()">ostree_sign_clear_keys</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-load-pk" title="ostree_sign_load_pk ()">ostree_sign_load_pk</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">const <span class="returnvalue">gchar</span> *
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-metadata-format" title="ostree_sign_metadata_format ()">ostree_sign_metadata_format</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">const <span class="returnvalue">gchar</span> *
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-metadata-key" title="ostree_sign_metadata_key ()">ostree_sign_metadata_key</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-set-pk" title="ostree_sign_set_pk ()">ostree_sign_set_pk</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-set-sk" title="ostree_sign_set_sk ()">ostree_sign_set_sk</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-Signature-management.html#ostree-sign-summary" title="ostree_sign_summary ()">ostree_sign_summary</a> <span class="c_punctuation">()</span>
</td>
</tr>
</tbody>
</table></div>
</div>
<div class="refsect1">
<a name="ostree-Signature-management.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody><tr>
<td class="datatype_keyword"> </td>
<td class="function_name"><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign">OstreeSign</a></td>
</tr></tbody>
</table></div>
</div>
<div class="refsect1">
<a name="ostree-Signature-management.description"></a><h2>Description</h2>
<p>An <a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> interface allows to select and use any available engine
for signing or verifying the commit object or summary file.</p>
</div>
<div class="refsect1">
<a name="ostree-Signature-management.functions_details"></a><h2>Functions</h2>
<div class="refsect2">
<a name="ostree-sign-get-all"></a><h3>ostree_sign_get_all ()</h3>
<pre class="programlisting"><span class="returnvalue">GPtrArray</span> *
ostree_sign_get_all (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
<p>Return an array with newly allocated instances of all available
signing engines; they will not be initialized.</p>
<div class="refsect3">
<a name="ostree-sign-get-all.returns"></a><h4>Returns</h4>
<p>an array of signing engines. </p>
<p><span class="annotation">[<a href="http://foldoc.org/transfer%20full"><span class="acronym">transfer full</span></a>][<a href="http://foldoc.org/element-type"><span class="acronym">element-type</span></a> OstreeSign]</span></p>
</div>
<p class="since">Since: 2020.2</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sign-commit"></a><h3>ostree_sign_commit ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_sign_commit (<em class="parameter"><code><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> *self</code></em>,
<em class="parameter"><code><a class="link" href="ostree-OstreeRepo.html#OstreeRepo" title="OstreeRepo"><span class="type">OstreeRepo</span></a> *repo</code></em>,
<em class="parameter"><code>const <span class="type">gchar</span> *commit_checksum</code></em>,
<em class="parameter"><code><span class="type">GCancellable</span> *cancellable</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
<p>Add a signature to a commit.</p>
<p>Depending of the signing engine used you will need to load
the secret key with <a class="link" href="ostree-Signature-management.html#ostree-sign-set-sk" title="ostree_sign_set_sk ()"><span class="type">ostree_sign_set_sk</span></a>.</p>
<div class="refsect3">
<a name="ostree-sign-commit.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody>
<tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>an <a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> object</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>repo</p></td>
<td class="parameter_description"><p>an <span class="type">OsreeRepo</span> object</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>commit_checksum</p></td>
<td class="parameter_description"><p>SHA256 of given commit to sign</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>cancellable</p></td>
<td class="parameter_description"><p>A <span class="type">GCancellable</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>error</p></td>
<td class="parameter_description"><p>a <span class="type">GError</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
</tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-sign-commit.returns"></a><h4>Returns</h4>
<p> <em class="parameter"><code>TRUE</code></em>
if commit has been signed successfully,
<em class="parameter"><code>FALSE</code></em>
in case of error (<em class="parameter"><code>error</code></em>
will contain the reason).</p>
</div>
<p class="since">Since: 2020.2</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sign-commit-verify"></a><h3>ostree_sign_commit_verify ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_sign_commit_verify (<em class="parameter"><code><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> *self</code></em>,
<em class="parameter"><code><a class="link" href="ostree-OstreeRepo.html#OstreeRepo" title="OstreeRepo"><span class="type">OstreeRepo</span></a> *repo</code></em>,
<em class="parameter"><code>const <span class="type">gchar</span> *commit_checksum</code></em>,
<em class="parameter"><code><span class="type">char</span> **out_success_message</code></em>,
<em class="parameter"><code><span class="type">GCancellable</span> *cancellable</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
<p>Verify if commit is signed with known key.</p>
<p>Depending of the signing engine used you will need to load
the public key(s) for verification with <a class="link" href="ostree-Signature-management.html#ostree-sign-set-pk" title="ostree_sign_set_pk ()"><span class="type">ostree_sign_set_pk</span></a>,
<a class="link" href="ostree-Signature-management.html#ostree-sign-add-pk" title="ostree_sign_add_pk ()"><span class="type">ostree_sign_add_pk</span></a> and/or <a class="link" href="ostree-Signature-management.html#ostree-sign-load-pk" title="ostree_sign_load_pk ()"><span class="type">ostree_sign_load_pk</span></a>.</p>
<div class="refsect3">
<a name="ostree-sign-commit-verify.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody>
<tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>an <a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> object</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>repo</p></td>
<td class="parameter_description"><p>an <span class="type">OsreeRepo</span> object</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>commit_checksum</p></td>
<td class="parameter_description"><p>SHA256 of given commit to verify</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>cancellable</p></td>
<td class="parameter_description"><p>A <span class="type">GCancellable</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>error</p></td>
<td class="parameter_description"><p>a <span class="type">GError</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
</tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-sign-commit-verify.returns"></a><h4>Returns</h4>
<p> <em class="parameter"><code>TRUE</code></em>
if commit has been verified successfully,
<em class="parameter"><code>FALSE</code></em>
in case of error or no valid keys are available (<em class="parameter"><code>error</code></em>
will contain the reason).</p>
</div>
<p class="since">Since: 2020.2</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sign-data"></a><h3>ostree_sign_data ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_sign_data (<em class="parameter"><code><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> *self</code></em>,
<em class="parameter"><code><span class="type">GBytes</span> *data</code></em>,
<em class="parameter"><code><span class="type">GBytes</span> **signature</code></em>,
<em class="parameter"><code><span class="type">GCancellable</span> *cancellable</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
<p>Sign the given <em class="parameter"><code>data</code></em>
with pre-loaded secret key.</p>
<p>Depending of the signing engine used you will need to load
the secret key with <a class="link" href="ostree-Signature-management.html#ostree-sign-set-sk" title="ostree_sign_set_sk ()"><span class="type">ostree_sign_set_sk</span></a>.</p>
<div class="refsect3">
<a name="ostree-sign-data.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody>
<tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>an <a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> object</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>data</p></td>
<td class="parameter_description"><p>the raw data to be signed with pre-loaded secret key</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>signature</p></td>
<td class="parameter_description"><p>in case of success will contain signature</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>cancellable</p></td>
<td class="parameter_description"><p>A <span class="type">GCancellable</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>error</p></td>
<td class="parameter_description"><p>a <span class="type">GError</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
</tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-sign-data.returns"></a><h4>Returns</h4>
<p> <em class="parameter"><code>TRUE</code></em>
if <em class="parameter"><code>data</code></em>
has been signed successfully,
<em class="parameter"><code>FALSE</code></em>
in case of error (<em class="parameter"><code>error</code></em>
will contain the reason).</p>
</div>
<p class="since">Since: 2020.2</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sign-data-verify"></a><h3>ostree_sign_data_verify ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_sign_data_verify (<em class="parameter"><code><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> *self</code></em>,
<em class="parameter"><code><span class="type">GBytes</span> *data</code></em>,
<em class="parameter"><code><span class="type">GVariant</span> *signatures</code></em>,
<em class="parameter"><code><span class="type">char</span> **out_success_message</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
<p>Verify given data against signatures with pre-loaded public keys.</p>
<p>Depending of the signing engine used you will need to load
the public key(s) with <a class="link" href="ostree-Signature-management.html#ostree-sign-set-pk" title="ostree_sign_set_pk ()"><span class="type">ostree_sign_set_pk</span></a>, <a class="link" href="ostree-Signature-management.html#ostree-sign-add-pk" title="ostree_sign_add_pk ()"><span class="type">ostree_sign_add_pk</span></a>
or <a class="link" href="ostree-Signature-management.html#ostree-sign-load-pk" title="ostree_sign_load_pk ()"><span class="type">ostree_sign_load_pk</span></a>.</p>
<div class="refsect3">
<a name="ostree-sign-data-verify.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody>
<tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>an <a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> object</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>data</p></td>
<td class="parameter_description"><p>the raw data to check</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>signatures</p></td>
<td class="parameter_description"><p>the signatures to be checked</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>error</p></td>
<td class="parameter_description"><p>a <span class="type">GError</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
</tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-sign-data-verify.returns"></a><h4>Returns</h4>
<p> <em class="parameter"><code>TRUE</code></em>
if <em class="parameter"><code>data</code></em>
has been signed at least with any single valid key,
<em class="parameter"><code>FALSE</code></em>
in case of error or no valid keys are available (<em class="parameter"><code>error</code></em>
will contain the reason).</p>
</div>
<p class="since">Since: 2020.2</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sign-get-by-name"></a><h3>ostree_sign_get_by_name ()</h3>
<pre class="programlisting"><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="returnvalue">OstreeSign</span></a> *
ostree_sign_get_by_name (<em class="parameter"><code>const <span class="type">gchar</span> *name</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
<p>Create a new instance of a signing engine.</p>
<div class="refsect3">
<a name="ostree-sign-get-by-name.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody>
<tr>
<td class="parameter_name"><p>name</p></td>
<td class="parameter_description"><p>the name of desired signature engine</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>error</p></td>
<td class="parameter_description"><p>return location for a <span class="type">GError</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
</tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-sign-get-by-name.returns"></a><h4>Returns</h4>
<p>New signing engine, or <code class="literal">NULL</code> if the engine is not known. </p>
<p><span class="annotation">[<a href="http://foldoc.org/transfer%20full"><span class="acronym">transfer full</span></a>]</span></p>
</div>
<p class="since">Since: 2020.2</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sign-get-name"></a><h3>ostree_sign_get_name ()</h3>
<pre class="programlisting">const <span class="returnvalue">gchar</span> *
ostree_sign_get_name (<em class="parameter"><code><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> *self</code></em>);</pre>
<p>Return the pointer to the name of currently used/selected signing engine.</p>
<div class="refsect3">
<a name="ostree-sign-get-name.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody><tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>an <a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> object</p></td>
<td class="parameter_annotations"> </td>
</tr></tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-sign-get-name.returns"></a><h4>Returns</h4>
<p>pointer to the name
<em class="parameter"><code>NULL</code></em>
in case of error (unlikely). </p>
<p><span class="annotation">[<a href="http://foldoc.org/transfer%20none"><span class="acronym">transfer none</span></a>]</span></p>
</div>
<p class="since">Since: 2020.2</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sign-add-pk"></a><h3>ostree_sign_add_pk ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_sign_add_pk (<em class="parameter"><code><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> *self</code></em>,
<em class="parameter"><code><span class="type">GVariant</span> *public_key</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
<p>Add the public key for verification. Could be called multiple times for
adding all needed keys to be used for verification.</p>
<p>The <em class="parameter"><code>public_key</code></em>
argument depends of the particular engine implementation.</p>
<div class="refsect3">
<a name="ostree-sign-add-pk.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody>
<tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>an <a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> object</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>public_key</p></td>
<td class="parameter_description"><p>single public key to be added</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>error</p></td>
<td class="parameter_description"><p>a <span class="type">GError</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
</tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-sign-add-pk.returns"></a><h4>Returns</h4>
<p> <em class="parameter"><code>TRUE</code></em>
in case if the key could be added successfully,
<em class="parameter"><code>FALSE</code></em>
in case of error (<em class="parameter"><code>error</code></em>
will contain the reason).</p>
</div>
<p class="since">Since: 2020.2</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sign-clear-keys"></a><h3>ostree_sign_clear_keys ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_sign_clear_keys (<em class="parameter"><code><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> *self</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
<p>Clear all previously preloaded secret and public keys.</p>
<div class="refsect3">
<a name="ostree-sign-clear-keys.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody>
<tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>an <a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> object</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>error</p></td>
<td class="parameter_description"><p>a <span class="type">GError</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
</tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-sign-clear-keys.returns"></a><h4>Returns</h4>
<p> <em class="parameter"><code>TRUE</code></em>
in case if no errors, <em class="parameter"><code>FALSE</code></em>
in case of error</p>
</div>
<p class="since">Since: 2020.2</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sign-load-pk"></a><h3>ostree_sign_load_pk ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_sign_load_pk (<em class="parameter"><code><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> *self</code></em>,
<em class="parameter"><code><span class="type">GVariant</span> *options</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
<p>Load public keys for verification from anywhere.
It is expected that all keys would be added to already pre-loaded keys.</p>
<p>The <em class="parameter"><code>options</code></em>
argument depends of the particular engine implementation.</p>
<p>For example, <em class="parameter"><code>ed25515</code></em>
engine could use following string-formatted options:</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem"><p><em class="parameter"><code>filename</code></em>
-- single file to use to load keys from</p></li>
<li class="listitem"><p><em class="parameter"><code>basedir</code></em>
-- directory containing subdirectories
'trusted.ed25519.d' and 'revoked.ed25519.d' with appropriate
public keys. Used for testing and re-definition of system-wide
directories if defaults are not suitable for any reason.</p></li>
</ul></div>
<div class="refsect3">
<a name="ostree-sign-load-pk.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody>
<tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>an <a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> object</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>options</p></td>
<td class="parameter_description"><p>any options</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>error</p></td>
<td class="parameter_description"><p>a <span class="type">GError</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
</tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-sign-load-pk.returns"></a><h4>Returns</h4>
<p> <em class="parameter"><code>TRUE</code></em>
in case if at least one key could be load successfully,
<em class="parameter"><code>FALSE</code></em>
in case of error (<em class="parameter"><code>error</code></em>
will contain the reason).</p>
</div>
<p class="since">Since: 2020.2</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sign-metadata-format"></a><h3>ostree_sign_metadata_format ()</h3>
<pre class="programlisting">const <span class="returnvalue">gchar</span> *
ostree_sign_metadata_format (<em class="parameter"><code><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> *self</code></em>);</pre>
<p>Return the pointer to the string with format used in (detached) metadata for
current signing engine.</p>
<div class="refsect3">
<a name="ostree-sign-metadata-format.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody><tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>an <a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> object</p></td>
<td class="parameter_annotations"> </td>
</tr></tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-sign-metadata-format.returns"></a><h4>Returns</h4>
<p>pointer to the metadata format,
<em class="parameter"><code>NULL</code></em>
in case of error (unlikely). </p>
<p><span class="annotation">[<a href="http://foldoc.org/transfer%20none"><span class="acronym">transfer none</span></a>]</span></p>
</div>
<p class="since">Since: 2020.2</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sign-metadata-key"></a><h3>ostree_sign_metadata_key ()</h3>
<pre class="programlisting">const <span class="returnvalue">gchar</span> *
ostree_sign_metadata_key (<em class="parameter"><code><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> *self</code></em>);</pre>
<p>Return the pointer to the name of the key used in (detached) metadata for
current signing engine.</p>
<div class="refsect3">
<a name="ostree-sign-metadata-key.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody><tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>an <a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> object</p></td>
<td class="parameter_annotations"> </td>
</tr></tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-sign-metadata-key.returns"></a><h4>Returns</h4>
<p>pointer to the metadata key name,
<em class="parameter"><code>NULL</code></em>
in case of error (unlikely). </p>
<p><span class="annotation">[<a href="http://foldoc.org/transfer%20none"><span class="acronym">transfer none</span></a>]</span></p>
</div>
<p class="since">Since: 2020.2</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sign-set-pk"></a><h3>ostree_sign_set_pk ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_sign_set_pk (<em class="parameter"><code><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> *self</code></em>,
<em class="parameter"><code><span class="type">GVariant</span> *public_key</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
<p>Set the public key for verification. It is expected what all
previously pre-loaded public keys will be dropped.</p>
<p>The <em class="parameter"><code>public_key</code></em>
argument depends of the particular engine implementation.</p>
<div class="refsect3">
<a name="ostree-sign-set-pk.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody>
<tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>an <a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> object</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>public_key</p></td>
<td class="parameter_description"><p>single public key to be added</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>error</p></td>
<td class="parameter_description"><p>a <span class="type">GError</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
</tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-sign-set-pk.returns"></a><h4>Returns</h4>
<p> <em class="parameter"><code>TRUE</code></em>
in case if the key could be set successfully,
<em class="parameter"><code>FALSE</code></em>
in case of error (<em class="parameter"><code>error</code></em>
will contain the reason).</p>
</div>
<p class="since">Since: 2020.2</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sign-set-sk"></a><h3>ostree_sign_set_sk ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_sign_set_sk (<em class="parameter"><code><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> *self</code></em>,
<em class="parameter"><code><span class="type">GVariant</span> *secret_key</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
<p>Set the secret key to be used for signing data, commits and summary.</p>
<p>The <em class="parameter"><code>secret_key</code></em>
argument depends of the particular engine implementation.</p>
<div class="refsect3">
<a name="ostree-sign-set-sk.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody>
<tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>an <a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> object</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>secret_key</p></td>
<td class="parameter_description"><p>secret key to be added</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>error</p></td>
<td class="parameter_description"><p>a <span class="type">GError</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
</tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-sign-set-sk.returns"></a><h4>Returns</h4>
<p> <em class="parameter"><code>TRUE</code></em>
in case if the key could be set successfully,
<em class="parameter"><code>FALSE</code></em>
in case of error (<em class="parameter"><code>error</code></em>
will contain the reason).</p>
</div>
<p class="since">Since: 2020.2</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sign-summary"></a><h3>ostree_sign_summary ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_sign_summary (<em class="parameter"><code><a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign"><span class="type">OstreeSign</span></a> *self</code></em>,
<em class="parameter"><code><a class="link" href="ostree-OstreeRepo.html#OstreeRepo" title="OstreeRepo"><span class="type">OstreeRepo</span></a> *repo</code></em>,
<em class="parameter"><code><span class="type">GVariant</span> *keys</code></em>,
<em class="parameter"><code><span class="type">GCancellable</span> *cancellable</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
<p>Add a signature to a summary file.
Based on ostree_repo_add_gpg_signature_summary implementation.</p>
<div class="refsect3">
<a name="ostree-sign-summary.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody>
<tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>Self</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>repo</p></td>
<td class="parameter_description"><p>ostree repository</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>keys</p></td>
<td class="parameter_description"><p>keys -- GVariant containing keys as GVarints specific to signature type.</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>cancellable</p></td>
<td class="parameter_description"><p>A <span class="type">GCancellable</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>error</p></td>
<td class="parameter_description"><p>a <span class="type">GError</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
</tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-sign-summary.returns"></a><h4>Returns</h4>
<p> <em class="parameter"><code>TRUE</code></em>
if summary file has been signed with all provided keys</p>
</div>
</div>
</div>
<div class="refsect1">
<a name="ostree-Signature-management.other_details"></a><h2>Types and Values</h2>
<div class="refsect2">
<a name="OstreeSign"></a><h3>OstreeSign</h3>
<pre class="programlisting">typedef struct _OstreeSign OstreeSign;</pre>
</div>
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -8,7 +8,7 @@
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="ostree-SELinux-policy-management.html" title="SELinux policy management">
<link rel="next" href="ostree-GPG-signature-verification-results.html" title="GPG signature verification results">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -35,8 +35,8 @@
<a name="ostree-Simple-upgrade-class.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_return">
<col class="functions_name">
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody>
<tr>
@ -134,8 +134,8 @@
<a name="ostree-Simple-upgrade-class.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="name">
<col class="description">
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody>
<tr>
@ -710,6 +710,6 @@ with /etc, and update the bootloader configuration.</p>
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -6,9 +6,9 @@
<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
<link rel="home" href="index.html" title="OSTree API references">
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="ostree-GPG-signature-verification-results.html" title="GPG signature verification results">
<link rel="prev" href="ostree-Signature-management.html" title="Signature management">
<link rel="next" href="ostree-ostree-chain-input-stream.html" title="ostree-chain-input-stream">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -19,7 +19,7 @@
</td>
<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
<td><a accesskey="u" href="reference.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
<td><a accesskey="p" href="ostree-GPG-signature-verification-results.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
<td><a accesskey="p" href="ostree-Signature-management.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
<td><a accesskey="n" href="ostree-ostree-chain-input-stream.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
</tr></table>
<div class="refentry">
@ -35,8 +35,8 @@
<a name="ostree-ostree-bootconfig-parser.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_return">
<col class="functions_name">
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody>
<tr>
@ -109,8 +109,8 @@
<a name="ostree-ostree-bootconfig-parser.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="name">
<col class="description">
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody><tr>
<td class="datatype_keyword"> </td>
@ -256,6 +256,6 @@ ostree_bootconfig_parser_get (<em class="parameter"><code><a class="link" href="
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -8,7 +8,7 @@
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="ostree-ostree-bootconfig-parser.html" title="ostree-bootconfig-parser">
<link rel="next" href="ostree-ostree-checksum-input-stream.html" title="ostree-checksum-input-stream">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -35,8 +35,8 @@
<a name="ostree-ostree-chain-input-stream.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_return">
<col class="functions_name">
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody><tr>
<td class="function_type">
@ -52,8 +52,8 @@
<a name="ostree-ostree-chain-input-stream.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="name">
<col class="description">
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody><tr>
<td class="datatype_keyword">struct</td>
@ -84,6 +84,6 @@ ostree_chain_input_stream_new (<em class="parameter"><code><span class="type">GP
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -8,7 +8,7 @@
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="ostree-ostree-chain-input-stream.html" title="ostree-chain-input-stream">
<link rel="next" href="ostree-ostree-deployment.html" title="ostree-deployment">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -35,8 +35,8 @@
<a name="ostree-ostree-checksum-input-stream.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_return">
<col class="functions_name">
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody><tr>
<td class="function_type">
@ -52,8 +52,8 @@
<a name="ostree-ostree-checksum-input-stream.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="name">
<col class="description">
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody><tr>
<td class="datatype_keyword">struct</td>
@ -85,6 +85,6 @@ ostree_checksum_input_stream_new (<em class="parameter"><code><span class="type"
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -8,7 +8,7 @@
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="ostree-ostree-checksum-input-stream.html" title="ostree-checksum-input-stream">
<link rel="next" href="ostree-ostree-diff.html" title="ostree-diff">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -35,8 +35,8 @@
<a name="ostree-ostree-deployment.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_return">
<col class="functions_name">
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody>
<tr>
@ -218,8 +218,8 @@
<a name="ostree-ostree-deployment.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="name">
<col class="description">
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody><tr>
<td class="datatype_keyword"> </td>
@ -642,6 +642,6 @@ ostree_deployment_unlocked_state_to_string
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -8,7 +8,7 @@
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="ostree-ostree-deployment.html" title="ostree-deployment">
<link rel="next" href="ostree-ostree-repo-file.html" title="ostree-repo-file">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -35,8 +35,8 @@
<a name="ostree-ostree-diff.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_return">
<col class="functions_name">
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody>
<tr>
@ -86,8 +86,8 @@
<a name="ostree-ostree-diff.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="name">
<col class="description">
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody>
<tr>
@ -364,6 +364,6 @@ ostree_diff_print (<em class="parameter"><code><span class="type">GFile</span> *
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -7,7 +7,7 @@
<link rel="home" href="index.html" title="OSTree API references">
<link rel="up" href="reference.html" title="API Reference">
<link rel="prev" href="ostree-ostree-diff.html" title="ostree-diff">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -34,8 +34,8 @@
<a name="ostree-ostree-repo-file.functions"></a><h2>Functions</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="functions_return">
<col class="functions_name">
<col width="150px" class="functions_proto_type">
<col class="functions_proto_name">
</colgroup>
<tbody>
<tr>
@ -138,8 +138,8 @@
<a name="ostree-ostree-repo-file.other"></a><h2>Types and Values</h2>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="name">
<col class="description">
<col width="150px" class="other_proto_type">
<col class="other_proto_name">
</colgroup>
<tbody><tr>
<td class="typedef_keyword">typedef</td>
@ -357,6 +357,6 @@ ostree_repo_file_tree_query_child (<em class="parameter"><code><a class="link" h
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -10,6 +10,7 @@
<sub name="SELinux policy management" link="ostree-SELinux-policy-management.html"/>
<sub name="Simple upgrade class" link="ostree-Simple-upgrade-class.html"/>
<sub name="GPG signature verification results" link="ostree-GPG-signature-verification-results.html"/>
<sub name="Signature management" link="ostree-Signature-management.html"/>
<sub name="ostree-bootconfig-parser" link="ostree-ostree-bootconfig-parser.html"/>
<sub name="ostree-chain-input-stream" link="ostree-ostree-chain-input-stream.html"/>
<sub name="ostree-checksum-input-stream" link="ostree-ostree-checksum-input-stream.html"/>
@ -67,7 +68,7 @@
<keyword type="function" name="ostree_validate_structureof_dirtree ()" link="ostree-Core-repository-independent-functions.html#ostree-validate-structureof-dirtree"/>
<keyword type="function" name="ostree_validate_structureof_dirmeta ()" link="ostree-Core-repository-independent-functions.html#ostree-validate-structureof-dirmeta"/>
<keyword type="function" name="ostree_commit_get_parent ()" link="ostree-Core-repository-independent-functions.html#ostree-commit-get-parent"/>
<keyword type="function" name="ostree_commit_get_timestamp ()" link="ostree-Core-repository-independent-functions.html#ostree-commit-get-timestamp"/>
<keyword type="function" name="ostree_commit_get_timestamp ()" link="ostree-Core-repository-independent-functions.html#ostree-commit-get-timestamp" since="2016.3"/>
<keyword type="function" name="ostree_commit_get_content_checksum ()" link="ostree-Core-repository-independent-functions.html#ostree-commit-get-content-checksum" since="2018.2"/>
<keyword type="function" name="ostree_commit_get_object_sizes ()" link="ostree-Core-repository-independent-functions.html#ostree-commit-get-object-sizes" since="2020.1"/>
<keyword type="function" name="ostree_commit_sizes_entry_new ()" link="ostree-Core-repository-independent-functions.html#ostree-commit-sizes-entry-new" since="2020.1"/>
@ -171,6 +172,7 @@
<keyword type="function" name="OstreeRepoCommitModifierXattrCallback ()" link="ostree-OstreeRepo.html#OstreeRepoCommitModifierXattrCallback"/>
<keyword type="function" name="ostree_repo_commit_modifier_set_xattr_callback ()" link="ostree-OstreeRepo.html#ostree-repo-commit-modifier-set-xattr-callback"/>
<keyword type="function" name="ostree_repo_commit_modifier_set_sepolicy ()" link="ostree-OstreeRepo.html#ostree-repo-commit-modifier-set-sepolicy"/>
<keyword type="function" name="ostree_repo_commit_modifier_set_sepolicy_from_commit ()" link="ostree-OstreeRepo.html#ostree-repo-commit-modifier-set-sepolicy-from-commit"/>
<keyword type="function" name="ostree_repo_commit_modifier_set_devino_cache ()" link="ostree-OstreeRepo.html#ostree-repo-commit-modifier-set-devino-cache" since="2017.13"/>
<keyword type="function" name="ostree_repo_commit_modifier_ref ()" link="ostree-OstreeRepo.html#ostree-repo-commit-modifier-ref"/>
<keyword type="function" name="ostree_repo_commit_modifier_unref ()" link="ostree-OstreeRepo.html#ostree-repo-commit-modifier-unref"/>
@ -362,6 +364,22 @@
<keyword type="typedef" name="OstreeGpgVerifyResult" link="ostree-GPG-signature-verification-results.html#OstreeGpgVerifyResult"/>
<keyword type="enum" name="enum OstreeGpgSignatureAttr" link="ostree-GPG-signature-verification-results.html#OstreeGpgSignatureAttr"/>
<keyword type="enum" name="enum OstreeGpgSignatureFormatFlags" link="ostree-GPG-signature-verification-results.html#OstreeGpgSignatureFormatFlags"/>
<keyword type="function" name="ostree_sign_get_all ()" link="ostree-Signature-management.html#ostree-sign-get-all" since="2020.2"/>
<keyword type="function" name="ostree_sign_commit ()" link="ostree-Signature-management.html#ostree-sign-commit" since="2020.2"/>
<keyword type="function" name="ostree_sign_commit_verify ()" link="ostree-Signature-management.html#ostree-sign-commit-verify" since="2020.2"/>
<keyword type="function" name="ostree_sign_data ()" link="ostree-Signature-management.html#ostree-sign-data" since="2020.2"/>
<keyword type="function" name="ostree_sign_data_verify ()" link="ostree-Signature-management.html#ostree-sign-data-verify" since="2020.2"/>
<keyword type="function" name="ostree_sign_get_by_name ()" link="ostree-Signature-management.html#ostree-sign-get-by-name" since="2020.2"/>
<keyword type="function" name="ostree_sign_get_name ()" link="ostree-Signature-management.html#ostree-sign-get-name" since="2020.2"/>
<keyword type="function" name="ostree_sign_add_pk ()" link="ostree-Signature-management.html#ostree-sign-add-pk" since="2020.2"/>
<keyword type="function" name="ostree_sign_clear_keys ()" link="ostree-Signature-management.html#ostree-sign-clear-keys" since="2020.2"/>
<keyword type="function" name="ostree_sign_load_pk ()" link="ostree-Signature-management.html#ostree-sign-load-pk" since="2020.2"/>
<keyword type="function" name="ostree_sign_metadata_format ()" link="ostree-Signature-management.html#ostree-sign-metadata-format" since="2020.2"/>
<keyword type="function" name="ostree_sign_metadata_key ()" link="ostree-Signature-management.html#ostree-sign-metadata-key" since="2020.2"/>
<keyword type="function" name="ostree_sign_set_pk ()" link="ostree-Signature-management.html#ostree-sign-set-pk" since="2020.2"/>
<keyword type="function" name="ostree_sign_set_sk ()" link="ostree-Signature-management.html#ostree-sign-set-sk" since="2020.2"/>
<keyword type="function" name="ostree_sign_summary ()" link="ostree-Signature-management.html#ostree-sign-summary"/>
<keyword type="struct" name="OstreeSign" link="ostree-Signature-management.html#OstreeSign"/>
<keyword type="function" name="ostree_bootconfig_parser_new ()" link="ostree-ostree-bootconfig-parser.html#ostree-bootconfig-parser-new"/>
<keyword type="function" name="ostree_bootconfig_parser_clone ()" link="ostree-ostree-bootconfig-parser.html#ostree-bootconfig-parser-clone"/>
<keyword type="function" name="ostree_bootconfig_parser_parse ()" link="ostree-ostree-bootconfig-parser.html#ostree-bootconfig-parser-parse"/>

View File

@ -8,7 +8,7 @@
<link rel="up" href="index.html" title="OSTree API references">
<link rel="prev" href="index.html" title="OSTree API references">
<link rel="next" href="ostree-Core-repository-independent-functions.html" title="Core repository-independent functions">
<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
<meta name="generator" content="GTK-Doc V1.32 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -48,6 +48,9 @@
<span class="refentrytitle"><a href="ostree-GPG-signature-verification-results.html">GPG signature verification results</a></span><span class="refpurpose"> — Inspect detached GPG signatures</span>
</dt>
<dt>
<span class="refentrytitle"><a href="ostree-Signature-management.html">Signature management</a></span><span class="refpurpose"> — Sign and verify commits</span>
</dt>
<dt>
<span class="refentrytitle"><a href="ostree-ostree-bootconfig-parser.html">ostree-bootconfig-parser</a></span><span class="refpurpose"></span>
</dt>
<dt>
@ -947,6 +950,10 @@ OstreeRepoFinderResultv, typedef in ostree-repo-finder
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-OstreeRepo.html#ostree-repo-commit-modifier-set-sepolicy-from-commit" title="ostree_repo_commit_modifier_set_sepolicy_from_commit ()">ostree_repo_commit_modifier_set_sepolicy_from_commit</a>, function in <a class="link" href="ostree-OstreeRepo.html" title="OstreeRepo: Content-addressed object store">OstreeRepo</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-OstreeRepo.html#ostree-repo-commit-modifier-set-xattr-callback" title="ostree_repo_commit_modifier_set_xattr_callback ()">ostree_repo_commit_modifier_set_xattr_callback</a>, function in <a class="link" href="ostree-OstreeRepo.html" title="OstreeRepo: Content-addressed object store">OstreeRepo</a>
</dt>
<dd></dd>
@ -1632,6 +1639,70 @@ ostree_repo_transaction_set_collection_ref, function in ostree-misc-experimental
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#OstreeSign" title="OstreeSign">OstreeSign</a>, struct in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-add-pk" title="ostree_sign_add_pk ()">ostree_sign_add_pk</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-clear-keys" title="ostree_sign_clear_keys ()">ostree_sign_clear_keys</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-commit" title="ostree_sign_commit ()">ostree_sign_commit</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-commit-verify" title="ostree_sign_commit_verify ()">ostree_sign_commit_verify</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-data" title="ostree_sign_data ()">ostree_sign_data</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-data-verify" title="ostree_sign_data_verify ()">ostree_sign_data_verify</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-get-all" title="ostree_sign_get_all ()">ostree_sign_get_all</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-get-by-name" title="ostree_sign_get_by_name ()">ostree_sign_get_by_name</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-get-name" title="ostree_sign_get_name ()">ostree_sign_get_name</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-load-pk" title="ostree_sign_load_pk ()">ostree_sign_load_pk</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-metadata-format" title="ostree_sign_metadata_format ()">ostree_sign_metadata_format</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-metadata-key" title="ostree_sign_metadata_key ()">ostree_sign_metadata_key</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-set-pk" title="ostree_sign_set_pk ()">ostree_sign_set_pk</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-set-sk" title="ostree_sign_set_sk ()">ostree_sign_set_sk</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Signature-management.html#ostree-sign-summary" title="ostree_sign_summary ()">ostree_sign_summary</a>, function in <a class="link" href="ostree-Signature-management.html" title="Signature management">Signature management</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-OstreeRepo.html#OstreeStaticDeltaGenerateOpt" title="enum OstreeStaticDeltaGenerateOpt">OstreeStaticDeltaGenerateOpt</a>, enum in <a class="link" href="ostree-OstreeRepo.html" title="OstreeRepo: Content-addressed object store">OstreeRepo</a>
</dt>
<dd></dd>
@ -1953,6 +2024,6 @@ OSTREE_YEAR_VERSION, macro in ostree-version
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.29</div>
<hr>Generated by GTK-Doc V1.32</div>
</body>
</html>

View File

@ -293,29 +293,11 @@ h2 .extralinks, h3 .extralinks
font-weight: normal;
}
acronym,abbr
acronym,abbr
{
border-bottom: 1px dotted gray;
}
/* code listings */
.listing_code .programlisting .normal,
.listing_code .programlisting .normal a,
.listing_code .programlisting .number,
.listing_code .programlisting .cbracket,
.listing_code .programlisting .symbol { color: #555753; }
.listing_code .programlisting .comment,
.listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */
.listing_code .programlisting .function,
.listing_code .programlisting .function a,
.listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */
.listing_code .programlisting .string { color: #ad7fa8; } /* tango: plum */
.listing_code .programlisting .keyword,
.listing_code .programlisting .usertype,
.listing_code .programlisting .type,
.listing_code .programlisting .type a { color: #4e9a06; } /* tango: chameleon 3 */
.listing_frame {
/* tango:sky blue 1 */
border: solid 1px #729fcf;
@ -481,3 +463,71 @@ acronym,abbr
}
}
.hll { background-color: #ffffcc }
.c { color: #408080; font-style: italic } /* Comment */
.err { border: 1px solid #FF0000 } /* Error */
.k { color: #008000; font-weight: bold } /* Keyword */
.o { color: #666666 } /* Operator */
.ch { color: #408080; font-style: italic } /* Comment.Hashbang */
.cm { color: #408080; font-style: italic } /* Comment.Multiline */
.cp { color: #BC7A00 } /* Comment.Preproc */
.cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
.c1 { color: #408080; font-style: italic } /* Comment.Single */
.cs { color: #408080; font-style: italic } /* Comment.Special */
.gd { color: #A00000 } /* Generic.Deleted */
.ge { font-style: italic } /* Generic.Emph */
.gr { color: #FF0000 } /* Generic.Error */
.gh { color: #000080; font-weight: bold } /* Generic.Heading */
.gi { color: #00A000 } /* Generic.Inserted */
.go { color: #888888 } /* Generic.Output */
.gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.gs { font-weight: bold } /* Generic.Strong */
.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.gt { color: #0044DD } /* Generic.Traceback */
.kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.kp { color: #008000 } /* Keyword.Pseudo */
.kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.kt { color: #B00040 } /* Keyword.Type */
.m { color: #666666 } /* Literal.Number */
.s { color: #BA2121 } /* Literal.String */
.na { color: #7D9029 } /* Name.Attribute */
.nb { color: #008000 } /* Name.Builtin */
.nc { color: #0000FF; font-weight: bold } /* Name.Class */
.no { color: #880000 } /* Name.Constant */
.nd { color: #AA22FF } /* Name.Decorator */
.ni { color: #999999; font-weight: bold } /* Name.Entity */
.ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.nf { color: #0000FF } /* Name.Function */
.nl { color: #A0A000 } /* Name.Label */
.nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.nt { color: #008000; font-weight: bold } /* Name.Tag */
.nv { color: #19177C } /* Name.Variable */
.ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.w { color: #bbbbbb } /* Text.Whitespace */
.mb { color: #666666 } /* Literal.Number.Bin */
.mf { color: #666666 } /* Literal.Number.Float */
.mh { color: #666666 } /* Literal.Number.Hex */
.mi { color: #666666 } /* Literal.Number.Integer */
.mo { color: #666666 } /* Literal.Number.Oct */
.sa { color: #BA2121 } /* Literal.String.Affix */
.sb { color: #BA2121 } /* Literal.String.Backtick */
.sc { color: #BA2121 } /* Literal.String.Char */
.dl { color: #BA2121 } /* Literal.String.Delimiter */
.sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.s2 { color: #BA2121 } /* Literal.String.Double */
.se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.sh { color: #BA2121 } /* Literal.String.Heredoc */
.si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.sx { color: #008000 } /* Literal.String.Other */
.sr { color: #BB6688 } /* Literal.String.Regex */
.s1 { color: #BA2121 } /* Literal.String.Single */
.ss { color: #19177C } /* Literal.String.Symbol */
.bp { color: #008000 } /* Name.Builtin.Pseudo */
.fm { color: #0000FF } /* Name.Function.Magic */
.vc { color: #19177C } /* Name.Variable.Class */
.vg { color: #19177C } /* Name.Variable.Global */
.vi { color: #19177C } /* Name.Variable.Instance */
.vm { color: #19177C } /* Name.Variable.Magic */
.il { color: #666666 } /* Literal.Number.Integer.Long */

View File

@ -21,6 +21,7 @@
<xi:include href="xml/ostree-sepolicy.xml"/>
<xi:include href="xml/ostree-sysroot-upgrader.xml"/>
<xi:include href="xml/ostree-gpg-verify-result.xml"/>
<xi:include href="xml/ostree-sign.xml"/>
<xi:include href="xml/ostree-bootconfig-parser.xml"/>
<xi:include href="xml/ostree-chain-input-stream.xml"/>
<xi:include href="xml/ostree-checksum-input-stream.xml"/>

View File

@ -379,6 +379,7 @@ ostree_repo_commit_modifier_new
OstreeRepoCommitModifierXattrCallback
ostree_repo_commit_modifier_set_xattr_callback
ostree_repo_commit_modifier_set_sepolicy
ostree_repo_commit_modifier_set_sepolicy_from_commit
ostree_repo_commit_modifier_set_devino_cache
ostree_repo_commit_modifier_ref
ostree_repo_commit_modifier_unref
@ -704,3 +705,25 @@ ostree_kernel_args_from_string
ostree_kernel_args_to_strv
ostree_kernel_args_to_string
</SECTION>
<SECTION>
<FILE>ostree-sign</FILE>
OstreeSign
ostree_sign_get_all
ostree_sign_commit
ostree_sign_commit_verify
ostree_sign_data
ostree_sign_data_verify
ostree_sign_get_by_name
ostree_sign_get_name
ostree_sign_add_pk
ostree_sign_clear_keys
ostree_sign_load_pk
ostree_sign_metadata_format
ostree_sign_metadata_key
ostree_sign_set_pk
ostree_sign_set_sk
ostree_sign_summary
<SUBSECTION Standard>
ostree_sign_get_type
</SECTION>

View File

@ -22,6 +22,7 @@ ostree_repo_finder_result_get_type
ostree_repo_get_type
ostree_repo_transaction_stats_get_type
ostree_sepolicy_get_type
ostree_sign_get_type
ostree_sysroot_get_type
ostree_sysroot_upgrader_flags_get_type
ostree_sysroot_upgrader_get_type

View File

@ -1 +1 @@
2020.3
2020.4

View File

@ -1484,6 +1484,48 @@ _ostree_show() {
return 0
}
_ostree_sign() {
local boolean_options="
$main_boolean_options
--delete -d
--verify -v
"
local options_with_args="
--sign-type
--keys-file
--keys-dir
--repo
"
local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )
case "$prev" in
--keys-file|--keys-dir|--repo)
__ostree_compreply_dirs_only
return 0
;;
$options_with_args_glob )
return 0
;;
esac
case "$cur" in
-*)
local all_options="$boolean_options $options_with_args"
__ostree_compreply_all_options
;;
*)
local argpos=$( __ostree_pos_first_nonflag $( __ostree_to_alternatives "$options_with_args" ) )
if [ $cword -eq $argpos ]; then
__ostree_compreply_commits
fi
esac
return 0
}
_ostree_static_delta_apply_offline() {
local boolean_options="
$main_boolean_options
@ -1747,6 +1789,7 @@ _ostree() {
reset
rev-parse
show
sign
static-delta
summary
"

View File

@ -25,10 +25,10 @@ AS_IF([test $enable_otmpfile = yes], [], [
AC_ARG_ENABLE(wrpseudo-compat,
[AS_HELP_STRING([--enable-wrpseudo-compat],
[Disable use syscall() and filesystem calls to for compatibility with wrpseudo [default=no]])],,
[Disable use of syscall() in some cases for compatibility with pseudo [default=no]])],,
[enable_wrpseudo_compat=no])
AS_IF([test $enable_wrpseudo_compat = no], [], [
AC_DEFINE([ENABLE_WRPSEUDO_COMPAT], 1, [Define if we should be compatible with wrpseudo])])
AC_DEFINE([ENABLE_WRPSEUDO_COMPAT], 1, [Define if we should be compatible with pseudo])])
dnl end LIBGLNX_CONFIGURE
])

View File

@ -21,7 +21,7 @@
/* Define if we should avoid using O_TMPFILE */
#undef DISABLE_OTMPFILE
/* Define if we should be compatible with wrpseudo */
/* Define if we should be compatible with pseudo */
#undef ENABLE_WRPSEUDO_COMPAT
/* The system grub2-mkconfig executable name */
@ -73,6 +73,9 @@
/* Define if we have libmount.pc */
#undef HAVE_LIBMOUNT
/* Define if using libsodium */
#undef HAVE_LIBSODIUM
/* Define if we have libsoup.pc */
#undef HAVE_LIBSOUP

222
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for libostree 2020.3.
# Generated by GNU Autoconf 2.69 for libostree 2020.4.
#
# Report bugs to <walters@verbum.org>.
#
@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libostree'
PACKAGE_TARNAME='libostree'
PACKAGE_VERSION='2020.3'
PACKAGE_STRING='libostree 2020.3'
PACKAGE_VERSION='2020.4'
PACKAGE_STRING='libostree 2020.4'
PACKAGE_BUGREPORT='walters@verbum.org'
PACKAGE_URL=''
@ -719,6 +719,10 @@ GTKDOC_MKPDF
GTKDOC_REBASE
GTKDOC_CHECK_PATH
GTKDOC_CHECK
USE_LIBSODIUM_FALSE
USE_LIBSODIUM_TRUE
OT_DEP_LIBSODIUM_LIBS
OT_DEP_LIBSODIUM_CFLAGS
USE_GPGME_FALSE
USE_GPGME_TRUE
GPG_ERROR_CONFIG
@ -741,6 +745,8 @@ INTROSPECTION_GIRDIR
INTROSPECTION_GENERATE
INTROSPECTION_COMPILER
INTROSPECTION_SCANNER
_GI_EXP_LIBDIR
_GI_EXP_DATADIR
USE_CURL_OR_SOUP_FALSE
USE_CURL_OR_SOUP_TRUE
HAVE_LIBSOUP_CLIENT_CERTS_FALSE
@ -933,6 +939,7 @@ enable_trivial_httpd_cmdline
enable_introspection
with_gpgme
with_gpgme_prefix
with_ed25519_libsodium
with_html_dir
enable_gtk_doc
enable_gtk_doc_html
@ -996,6 +1003,8 @@ OT_DEP_GPGME_CFLAGS
OT_DEP_GPGME_LIBS
OT_DEP_GPG_ERROR_CFLAGS
OT_DEP_GPG_ERROR_LIBS
OT_DEP_LIBSODIUM_CFLAGS
OT_DEP_LIBSODIUM_LIBS
GTKDOC_DEPS_CFLAGS
GTKDOC_DEPS_LIBS
OT_DEP_LIBARCHIVE_CFLAGS
@ -1552,7 +1561,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures libostree 2020.3 to adapt to many kinds of systems.
\`configure' configures libostree 2020.4 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1622,7 +1631,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of libostree 2020.3:";;
short | recursive ) echo "Configuration of libostree 2020.4:";;
esac
cat <<\_ACEOF
@ -1651,8 +1660,8 @@ Optional Features:
Enable always building tests during 'make all'
--disable-otmpfile Disable use of O_TMPFILE [default=no]
--enable-wrpseudo-compat
Disable use syscall() and filesystem calls to for
compatibility with wrpseudo [default=no]
Disable use of syscall() in some cases for
compatibility with pseudo [default=no]
--disable-glibtest do not try to compile and run a test GLIB program
--disable-http2 Disable use of http2 (default: no)
--enable-libsoup-client-certs
@ -1690,6 +1699,8 @@ Optional Packages:
--with-soup Use libsoup [default=yes]
--with-gpgme Use gpgme [default=yes]
--with-gpgme-prefix=PFX prefix where GPGME is installed (optional)
--with-ed25519-libsodium
Use libsodium for ed25519 [default=no]
--with-html-dir=PATH path to installed docs
--without-libarchive Do not use libarchive
--without-selinux Do not use SELinux
@ -1782,6 +1793,10 @@ Some influential environment variables:
C compiler flags for OT_DEP_GPG_ERROR, overriding pkg-config
OT_DEP_GPG_ERROR_LIBS
linker flags for OT_DEP_GPG_ERROR, overriding pkg-config
OT_DEP_LIBSODIUM_CFLAGS
C compiler flags for OT_DEP_LIBSODIUM, overriding pkg-config
OT_DEP_LIBSODIUM_LIBS
linker flags for OT_DEP_LIBSODIUM, overriding pkg-config
GTKDOC_DEPS_CFLAGS
C compiler flags for GTKDOC_DEPS, overriding pkg-config
GTKDOC_DEPS_LIBS
@ -1881,7 +1896,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
libostree configure 2020.3
libostree configure 2020.4
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -2353,7 +2368,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by libostree $as_me 2020.3, which was
It was created by libostree $as_me 2020.4, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -3221,7 +3236,7 @@ fi
# Define the identity of the package.
PACKAGE='libostree'
VERSION='2020.3'
VERSION='2020.4'
# Some tools Automake needs.
@ -5955,9 +5970,9 @@ test -n "$YACC" || YACC="yacc"
YEAR_VERSION=2020
RELEASE_VERSION=3
RELEASE_VERSION=4
PACKAGE_VERSION=2020.3
PACKAGE_VERSION=2020.4
if echo "$CFLAGS" | grep -q -E -e '-Werror($| )'; then :
@ -15477,20 +15492,77 @@ esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $found_introspection" >&5
$as_echo "$found_introspection" >&6; }
EXP_VAR=_GI_EXP_DATADIR
FROM_VAR="$datadir"
prefix_save=$prefix
exec_prefix_save=$exec_prefix
if test "x$prefix" = "xNONE"; then
prefix="$ac_default_prefix"
fi
if test "x$exec_prefix" = "xNONE"; then
exec_prefix=$prefix
fi
full_var="$FROM_VAR"
while true; do
new_full_var="`eval echo $full_var`"
if test "x$new_full_var" = "x$full_var"; then break; fi
full_var=$new_full_var
done
full_var=$new_full_var
_GI_EXP_DATADIR="$full_var"
prefix=$prefix_save
exec_prefix=$exec_prefix_save
EXP_VAR=_GI_EXP_LIBDIR
FROM_VAR="$libdir"
prefix_save=$prefix
exec_prefix_save=$exec_prefix
if test "x$prefix" = "xNONE"; then
prefix="$ac_default_prefix"
fi
if test "x$exec_prefix" = "xNONE"; then
exec_prefix=$prefix
fi
full_var="$FROM_VAR"
while true; do
new_full_var="`eval echo $full_var`"
if test "x$new_full_var" = "x$full_var"; then break; fi
full_var=$new_full_var
done
full_var=$new_full_var
_GI_EXP_LIBDIR="$full_var"
prefix=$prefix_save
exec_prefix=$exec_prefix_save
INTROSPECTION_SCANNER=
INTROSPECTION_COMPILER=
INTROSPECTION_GENERATE=
INTROSPECTION_GIRDIR=
INTROSPECTION_TYPELIBDIR=
if test "x$found_introspection" = "xyes"; then
INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
INTROSPECTION_SCANNER=$PKG_CONFIG_SYSROOT_DIR`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
INTROSPECTION_COMPILER=$PKG_CONFIG_SYSROOT_DIR`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
INTROSPECTION_GENERATE=$PKG_CONFIG_SYSROOT_DIR`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
INTROSPECTION_GIRDIR=`$PKG_CONFIG --define-variable=datadir="${_GI_EXP_DATADIR}" --variable=girdir gobject-introspection-1.0`
INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --define-variable=libdir="${_GI_EXP_LIBDIR}" --variable=typelibdir gobject-introspection-1.0)"
INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0`
INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0`
INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection
INTROSPECTION_MAKEFILE=$PKG_CONFIG_SYSROOT_DIR`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection
fi
@ -16076,6 +16148,111 @@ else
fi
LIBSODIUM_DEPENDENCY="1.0.14"
# Check whether --with-ed25519_libsodium was given.
if test "${with_ed25519_libsodium+set}" = set; then :
withval=$with_ed25519_libsodium;
else
with_ed25519_libsodium=no
fi
if test x$with_ed25519_libsodium != xno; then :
$as_echo "#define HAVE_LIBSODIUM 1" >>confdefs.h
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_LIBSODIUM" >&5
$as_echo_n "checking for OT_DEP_LIBSODIUM... " >&6; }
if test -n "$OT_DEP_LIBSODIUM_CFLAGS"; then
pkg_cv_OT_DEP_LIBSODIUM_CFLAGS="$OT_DEP_LIBSODIUM_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsodium >= \$LIBSODIUM_DEPENDENCY\""; } >&5
($PKG_CONFIG --exists --print-errors "libsodium >= $LIBSODIUM_DEPENDENCY") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_OT_DEP_LIBSODIUM_CFLAGS=`$PKG_CONFIG --cflags "libsodium >= $LIBSODIUM_DEPENDENCY" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$OT_DEP_LIBSODIUM_LIBS"; then
pkg_cv_OT_DEP_LIBSODIUM_LIBS="$OT_DEP_LIBSODIUM_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsodium >= \$LIBSODIUM_DEPENDENCY\""; } >&5
($PKG_CONFIG --exists --print-errors "libsodium >= $LIBSODIUM_DEPENDENCY") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_OT_DEP_LIBSODIUM_LIBS=`$PKG_CONFIG --libs "libsodium >= $LIBSODIUM_DEPENDENCY" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test $pkg_failed = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
OT_DEP_LIBSODIUM_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsodium >= $LIBSODIUM_DEPENDENCY" 2>&1`
else
OT_DEP_LIBSODIUM_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsodium >= $LIBSODIUM_DEPENDENCY" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$OT_DEP_LIBSODIUM_PKG_ERRORS" >&5
have_libsodium=no
elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
have_libsodium=no
else
OT_DEP_LIBSODIUM_CFLAGS=$pkg_cv_OT_DEP_LIBSODIUM_CFLAGS
OT_DEP_LIBSODIUM_LIBS=$pkg_cv_OT_DEP_LIBSODIUM_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
have_libsodium=yes
fi
if test x$have_libsodium = xno ; then :
as_fn_error $? "Need LIBSODIUM version $LIBSODIUM_DEPENDENCY or later" "$LINENO" 5
fi
OSTREE_FEATURES="$OSTREE_FEATURES sign-ed25519"
else
with_ed25519_libsodium=no
fi
if test "x$have_libsodium" = xyes; then
USE_LIBSODIUM_TRUE=
USE_LIBSODIUM_FALSE='#'
else
USE_LIBSODIUM_TRUE='#'
USE_LIBSODIUM_FALSE=
fi
LIBARCHIVE_DEPENDENCY="libarchive >= 2.8.0"
# What's in RHEL7.2.
FUSE_DEPENDENCY="fuse >= 2.9.2"
@ -18339,6 +18516,10 @@ if test -z "${USE_GPGME_TRUE}" && test -z "${USE_GPGME_FALSE}"; then
as_fn_error $? "conditional \"USE_GPGME\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${USE_LIBSODIUM_TRUE}" && test -z "${USE_LIBSODIUM_FALSE}"; then
as_fn_error $? "conditional \"USE_LIBSODIUM\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${HAVE_GTK_DOC_TRUE}" && test -z "${HAVE_GTK_DOC_FALSE}"; then
as_fn_error $? "conditional \"HAVE_GTK_DOC\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@ -18844,7 +19025,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by libostree $as_me 2020.3, which was
This file was extended by libostree $as_me 2020.4, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -18910,7 +19091,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
libostree config.status 2020.3
libostree config.status 2020.4
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@ -20616,6 +20797,7 @@ echo "
cryptographic checksums: $with_crypto
systemd: $with_libsystemd
libmount: $with_libmount
libsodium (ed25519 signatures): $with_ed25519_libsodium
libarchive (parse tar files directly): $with_libarchive
static deltas: yes (always enabled now)
O_TMPFILE: $enable_otmpfile

View File

@ -2,12 +2,12 @@ AC_PREREQ([2.63])
dnl To do a release: follow the instructions to update libostree-released.sym from
dnl libostree-devel.sym, update the checksum in test-symbols.sh, set is_release_build=yes
dnl below. Then make another post-release commit to bump the version and set
dnl is_release_build=yes
dnl is_release_build=no.
dnl Seed the release notes with `git-shortlog-with-prs <previous-release>..`. Then use
dnl `git-evtag` to create the tag and push it. Finally, create a GitHub release and attach
dnl the tarball from `make dist`.
m4_define([year_version], [2020])
m4_define([release_version], [3])
m4_define([release_version], [4])
m4_define([package_version], [year_version.release_version])
AC_INIT([libostree], [package_version], [walters@verbum.org])
is_release_build=yes
@ -242,6 +242,21 @@ dnl to link to it directly.
)
AM_CONDITIONAL(USE_GPGME, test "x$have_gpgme" = xyes)
LIBSODIUM_DEPENDENCY="1.0.14"
AC_ARG_WITH(ed25519_libsodium,
AS_HELP_STRING([--with-ed25519-libsodium], [Use libsodium for ed25519 @<:@default=no@:>@]),
[], [with_ed25519_libsodium=no])
AS_IF([test x$with_ed25519_libsodium != xno], [
AC_DEFINE([HAVE_LIBSODIUM], 1, [Define if using libsodium])
PKG_CHECK_MODULES(OT_DEP_LIBSODIUM, libsodium >= $LIBSODIUM_DEPENDENCY, have_libsodium=yes, have_libsodium=no)
AS_IF([ test x$have_libsodium = xno ], [
AC_MSG_ERROR([Need LIBSODIUM version $LIBSODIUM_DEPENDENCY or later])
])
OSTREE_FEATURES="$OSTREE_FEATURES sign-ed25519"
], with_ed25519_libsodium=no )
AM_CONDITIONAL(USE_LIBSODIUM, test "x$have_libsodium" = xyes)
LIBARCHIVE_DEPENDENCY="libarchive >= 2.8.0"
# What's in RHEL7.2.
FUSE_DEPENDENCY="fuse >= 2.9.2"
@ -626,6 +641,7 @@ echo "
cryptographic checksums: $with_crypto
systemd: $with_libsystemd
libmount: $with_libmount
libsodium (ed25519 signatures): $with_ed25519_libsodium
libarchive (parse tar files directly): $with_libarchive
static deltas: yes (always enabled now)
O_TMPFILE: $enable_otmpfile

View File

@ -1,4 +1,4 @@
libglnx is the successor to libgsystem: https://git.gnome.org/browse/libgsystem
libglnx is the successor to [libgsystem](https://gitlab.gnome.org/Archive/libgsystem).
It is for modules which depend on both GLib and Linux, intended to be
used as a git submodule.

View File

@ -49,7 +49,9 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GMainContext, g_main_context_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GMainLoop, g_main_loop_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GSource, g_source_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GMappedFile, g_mapped_file_unref)
#if GLIB_CHECK_VERSION(2, 36, 0)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GMarkupParseContext, g_markup_parse_context_unref)
#endif
G_DEFINE_AUTOPTR_CLEANUP_FUNC(gchar, g_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GNode, g_node_destroy)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GOptionContext, g_option_context_free)
@ -75,11 +77,15 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GVariant, g_variant_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GVariantBuilder, g_variant_builder_unref)
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GVariantBuilder, g_variant_builder_clear)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GVariantIter, g_variant_iter_free)
#if GLIB_CHECK_VERSION(2, 40, 0)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GVariantDict, g_variant_dict_unref)
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GVariantDict, g_variant_dict_clear)
#endif
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GVariantType, g_variant_type_free)
#if GLIB_CHECK_VERSION(2, 40, 0)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GSubprocess, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GSubprocessLauncher, g_object_unref)
#endif
/* Add GObject-based types as needed. */
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GAsyncResult, g_object_unref)
@ -101,7 +107,9 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GMount, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GOutputStream, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GSocket, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GSocketAddress, g_object_unref)
#if GLIB_CHECK_VERSION(2, 36, 0)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GTask, g_object_unref)
#endif
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GTlsCertificate, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GTlsDatabase, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GTlsInteraction, g_object_unref)

View File

@ -27,6 +27,26 @@
G_BEGIN_DECLS
#if !GLIB_CHECK_VERSION(2, 34, 0)
#define g_clear_pointer(pp, destroy) \
G_STMT_START { \
G_STATIC_ASSERT (sizeof *(pp) == sizeof (gpointer)); \
/* Only one access, please; work around type aliasing */ \
union { char *in; gpointer *out; } _pp; \
gpointer _p; \
/* This assignment is needed to avoid a gcc warning */ \
GDestroyNotify _destroy = (GDestroyNotify) (destroy); \
\
_pp.in = (char *) (pp); \
_p = *_pp.out; \
if (_p) \
{ \
*_pp.out = NULL; \
_destroy (_p); \
} \
} G_STMT_END
#endif
#if !GLIB_CHECK_VERSION(2, 44, 0)
#define g_strv_contains glnx_strv_contains
@ -43,4 +63,16 @@ gboolean glnx_set_object (GObject **object_ptr,
#endif /* !GLIB_CHECK_VERSION(2, 44, 0) */
#ifndef g_assert_nonnull
#define g_assert_nonnull(x) g_assert (x != NULL)
#endif
#ifndef g_assert_null
#define g_assert_null(x) g_assert (x == NULL)
#endif
#if !GLIB_CHECK_VERSION (2, 38, 0)
#define g_test_skip(s) g_test_message ("SKIP: %s", s)
#endif
G_END_DECLS

View File

@ -37,6 +37,7 @@
#include <glnx-errors.h>
#include <glnx-xattrs.h>
#include <glnx-backport-autoptr.h>
#include <glnx-backports.h>
#include <glnx-local-alloc.h>
#include <glnx-missing.h>
@ -825,7 +826,7 @@ glnx_regfile_copy_bytes (int fdf, int fdt, off_t max_bytes)
have_cfr = 0;
try_cfr = false;
}
else if (errno == EXDEV)
else if (G_IN_SET (errno, EXDEV, EOPNOTSUPP))
/* We won't try cfr again for this run, but let's be
* conservative and not mark it as available/unavailable until
* we know for sure.
@ -938,7 +939,7 @@ glnx_regfile_copy_bytes (int fdf, int fdt, off_t max_bytes)
gboolean
glnx_file_copy_at (int src_dfd,
const char *src_subpath,
struct stat *src_stbuf,
const struct stat *src_stbuf,
int dest_dfd,
const char *dest_subpath,
GLnxFileCopyFlags copyflags,

View File

@ -193,7 +193,7 @@ typedef enum {
gboolean
glnx_file_copy_at (int src_dfd,
const char *src_subpath,
struct stat *src_stbuf,
const struct stat *src_stbuf,
int dest_dfd,
const char *dest_subpath,
GLnxFileCopyFlags copyflags,

View File

@ -25,10 +25,10 @@ AS_IF([test $enable_otmpfile = yes], [], [
AC_ARG_ENABLE(wrpseudo-compat,
[AS_HELP_STRING([--enable-wrpseudo-compat],
[Disable use syscall() and filesystem calls to for compatibility with wrpseudo [default=no]])],,
[Disable use of syscall() in some cases for compatibility with pseudo [default=no]])],,
[enable_wrpseudo_compat=no])
AS_IF([test $enable_wrpseudo_compat = no], [], [
AC_DEFINE([ENABLE_WRPSEUDO_COMPAT], 1, [Define if we should be compatible with wrpseudo])])
AC_DEFINE([ENABLE_WRPSEUDO_COMPAT], 1, [Define if we should be compatible with pseudo])])
dnl end LIBGLNX_CONFIGURE
])

View File

@ -23,6 +23,8 @@
#include <errno.h>
#include <glib/gstdio.h>
#include "libglnx.h"
struct _GLnxTestAutoTempDir
@ -63,4 +65,10 @@ _glnx_test_auto_temp_dir_leave (_GLnxTestAutoTempDir *dir)
glnx_tmpdir_delete (&dir->temp_dir, NULL, &error);
g_assert_no_error (error);
g_close (dir->old_cwd_fd, &error);
g_assert_no_error (error);
g_free (dir->old_cwd);
g_free (dir);
}

View File

@ -45,4 +45,4 @@ void _glnx_test_auto_temp_dir_leave (_GLnxTestAutoTempDir *dir);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(_GLnxTestAutoTempDir, _glnx_test_auto_temp_dir_leave);
#define _GLNX_TEST_SCOPED_TEMP_DIR \
g_autoptr(_GLnxTestAutoTempDir) temp_dir = _glnx_test_auto_temp_dir_enter ()
G_GNUC_UNUSED g_autoptr(_GLnxTestAutoTempDir) temp_dir = _glnx_test_auto_temp_dir_enter ()

View File

@ -218,7 +218,11 @@ test_xattr_races (void)
/* FIXME - this deadlocks for me on 4.9.4-201.fc25.x86_64, whether
* using overlayfs or xfs as source/dest.
*/
#if GLIB_CHECK_VERSION (2, 36, 0)
const guint nprocs = MAX (4, g_get_num_processors ());
#else
const guint nprocs = 4;
#endif
struct XattrWorker wdata[nprocs];
GThread *threads[nprocs];
g_autoptr(GError) local_error = NULL;

View File

@ -68,7 +68,7 @@ Boston, MA 02111-1307, USA.
<variablelist>
<varlistentry>
<term><option>--user-mode</option>,<option> -u</option></term>
<term><option>--user-mode</option>, <option>-U</option></term>
<listitem><para>
Do not change file ownership or initialize extended attributes.
@ -108,6 +108,14 @@ Boston, MA 02111-1307, USA.
directories. Requires <literal>-H</literal>.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--whiteouts</option></term>
<listitem><para>
Process whiteout files (Docker style).
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--allow-noent</option></term>
@ -131,6 +139,69 @@ Boston, MA 02111-1307, USA.
Process many checkouts from input file.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--fsync</option>="POLICY"</term>
<listitem><para>
POLICY is a boolean which specifies whether fsync should be
used or not. Default to true.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--require-hardlinks</option>,
<option>-H</option></term>
<listitem><para>
Do not fall back to full copies if hardlinking fails.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--force-copy-zerosized</option>,
<option>-z</option></term>
<listitem><para>
Do not hardlink zero-sized files.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--force-copy</option>, <option>-C</option></term>
<listitem><para>
Never hardlink (but may reflink if available).
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--bareuseronly-dirs</option>,
<option>-M</option></term>
<listitem><para>
Suppress mode bits outside of 0775 for directories (suid,
world writable, etc.).
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--skip-list</option>="FILE"</term>
<listitem><para>
Skip checking out the absolute file paths listed in FILE,
one per line.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--selinux-policy</option></term>
<listitem><para>
Set SELinux labels based on policy in root filesystem PATH
(may be /). This implies <literal>--force-copy</literal>.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -106,6 +106,15 @@ Boston, MA 02111-1307, USA.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--base</option>="REV"</term>
<listitem><para>
Start from the content in a commit. This differs from <literal>--tree=ref=REV</literal> in that no commit modifiers are applied. This is usually what you want when
creating a derived commit. This is also used for <literal>--selinux-policy-from-base</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--add-metadata-string</option>="KEY=VALUE"</term>
@ -251,6 +260,39 @@ Boston, MA 02111-1307, USA.
POLICY is a boolean which specifies whether fsync should be used or not. Default to true.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-s, --sign-type</option></term>
<listitem><para>
Use particular signature engine. Currently
available <arg choice="plain">ed25519</arg> and <arg choice="plain">dummy</arg>
signature types.
The default is <arg choice="plain">ed25519</arg>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--sign</option>="KEY-ID"</term>
<listitem><para>
There <literal>KEY-ID</literal> is:
<variablelist>
<varlistentry>
<term><option>for ed25519:</option></term>
<listitem><para>
<literal>base64</literal>-encoded secret key for commit signing.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>for dummy:</option></term>
<listitem><para>
ASCII-string used as secret key.
</para></listitem>
</varlistentry>
</variablelist>
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -51,7 +51,7 @@ Boston, MA 02111-1307, USA.
<refsynopsisdiv>
<cmdsynopsis>
<command>ostree diff</command> <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="req">REV</arg> <arg choice="req">TARGETDIR</arg>
<command>ostree diff</command> <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="req">REV_OR_DIR</arg> <arg choice="req">REV_OR_DIR</arg>
</cmdsynopsis>
</refsynopsisdiv>
@ -59,7 +59,7 @@ Boston, MA 02111-1307, USA.
<title>Description</title>
<para>
Compare directory TARGETDIR against revision REV. Shows files and directories modified, added, and deleted. If there is a file in TARGETDIR not in REV, it will show with an "A" for "added". If a file in REV is not in TARGETDIR, it shows "D" for "deleted". "M" for "modified" will also show.
Compare a directory or revision against another directory or revision. If REV_OR_DIR starts with `/` or `./`, it is interpreted as a directory, otherwise a revision. Shows files and directories modified, added, and deleted. If there is a file in the second REV_OR_DIR not in the first, it will show with an "A" for "added". If a file in the first REV_OR_DIR is not in the second, it shows "D" for "deleted". "M" for "modified" will also show.
</para>
</refsect1>

View File

@ -116,6 +116,16 @@ Boston, MA 02111-1307, USA.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--mirror</option></term>
<listitem><para>
Do a mirror pull (see the documentation for
<command>ostree pull --mirror</command>). This option can
only be used in combination with <option>--pull</option>.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

152
man/ostree-sign.xml Normal file
View File

@ -0,0 +1,152 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
Copyright 2019 Denis Pynkin <denis.pynkin@collabora.com>
SPDX-License-Identifier: LGPL-2.0+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
-->
<refentry id="ostree">
<refentryinfo>
<title>ostree sign</title>
<productname>OSTree</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Colin</firstname>
<surname>Walters</surname>
<email>walters@verbum.org</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>ostree sign</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>ostree-sign</refname>
<refpurpose>Sign a commit</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>ostree sign</command> <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="req">COMMIT</arg> <arg choice="req" rep="repeat">KEY-ID</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Add a new signature to a commit.
Note that currently, this will append a new signature even if
the commit is already signed with a given key.
</para>
<para>
There are several "well-known" system places for `ed25519` trusted and revoked public keys -- expected single <literal>base64</literal>-encoded key per line.
</para>
<para>Files:
<itemizedlist>
<listitem><para><filename>/etc/ostree/trusted.ed25519</filename></para></listitem>
<listitem><para><filename>/etc/ostree/revoked.ed25519</filename></para></listitem>
<listitem><para><filename>/usr/share/ostree/trusted.ed25519</filename></para></listitem>
<listitem><para><filename>/usr/share/ostree/revoked.ed25519</filename></para></listitem>
</itemizedlist>
</para>
<para>Directories containing files with keys:
<itemizedlist>
<listitem><para><filename>/etc/ostree/trusted.ed25519.d</filename></para></listitem>
<listitem><para><filename>/etc/ostree/revoked.ed25519.d</filename></para></listitem>
<listitem><para><filename>/usr/share/ostree/trusted.ed25519.d</filename></para></listitem>
<listitem><para><filename>/usr/share/ostree/rvokeded.ed25519.d</filename></para></listitem>
</itemizedlist>
</para>
</refsect1>
<refsect1>
<title>Options</title>
<variablelist>
<varlistentry>
<term><option>KEY-ID</option></term>
<listitem><para>
<variablelist>
<varlistentry>
<term><option>for ed25519:</option></term>
<listitem><para>
<literal>base64</literal>-encoded secret (for signing) or public key (for verifying).
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>for dummy:</option></term>
<listitem><para>
ASCII-string used as secret key and public key.
</para></listitem>
</varlistentry>
</variablelist>
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--verify</option></term>
<listitem><para>
Verify signatures
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-s, --sign-type</option></term>
<listitem><para>
Use particular signature mechanism. Currently
available <arg choice="plain">ed25519</arg> and <arg choice="plain">dummy</arg>
signature types.
The default is <arg choice="plain">ed25519</arg>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--keys-file</option></term>
<listitem><para>
Read key(s) from file <filename>filename</filename>.
</para></listitem>
<listitem><para>
Valid for <literal>ed25519</literal> signature type.
For <literal>ed25519</literal> this file must contain <literal>base64</literal>-encoded
secret key(s) (for signing) or public key(s) (for verifying) per line.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--keys-dir</option></term>
<listitem><para>
Redefine the system path, where to search files and subdirectories with
well-known and revoked keys.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
</refentry>

View File

@ -51,7 +51,7 @@ Boston, MA 02111-1307, USA.
<refsynopsisdiv>
<cmdsynopsis>
<command>ostree summary</command> <arg choice="opt">--gpg-sign=KEYID</arg> <arg choice="opt">--gpg-homedir=HOMEDIR</arg> <arg choice="req">--update</arg> <arg choice="opt" rep="repeat">--add-metadata=<replaceable>KEY</replaceable>=<replaceable>VALUE</replaceable></arg>
<command>ostree summary</command> <arg choice="opt">--gpg-sign=KEYID</arg> <arg choice="opt">--gpg-homedir=HOMEDIR</arg> <arg choice="opt">--sign=KEYID</arg> <arg choice="opt">--sign-type=ENGINE</arg> <arg choice="req">--update</arg> <arg choice="opt" rep="repeat">--add-metadata=<replaceable>KEY</replaceable>=<replaceable>VALUE</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
@ -139,6 +139,39 @@ Boston, MA 02111-1307, USA.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--sign-type</option>=ENGINE</term>
<listitem><para>
Use particular signature engine. Currently
available <arg choice="plain">ed25519</arg> and <arg choice="plain">dummy</arg>
signature types.
The default is <arg choice="plain">ed25519</arg>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--sign</option>="KEY-ID"</term>
<listitem><para>
There <literal>KEY-ID</literal> is:
<variablelist>
<varlistentry>
<term><option>for ed25519:</option></term>
<listitem><para>
<literal>base64</literal>-encoded secret key for commit signing.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>for dummy:</option></term>
<listitem><para>
ASCII-string used as secret key.
</para></listitem>
</varlistentry>
</variablelist>
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -127,6 +127,18 @@ Boston, MA 02111-1307, USA.
</listitem>
</varlistentry>
<varlistentry>
<term><varname>per-object-fsync</varname></term>
<listitem><para>By default, OSTree will batch fsync() after
writing everything; however, this can cause latency spikes
for other processes which are also invoking fsync().
Turn on this boolean to reduce potential latency spikes,
at the cost of slowing down OSTree updates. You most
likely want this on by default for "background" OS updates.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>min-free-space-percent</varname></term>
<listitem>

View File

@ -26,6 +26,16 @@ if ! test -d /ostree/repo; then
exit 0
fi
# Gracefully exit if the grub2 configuration has BLS enabled,
# and the installed version has support for the blscfg module.
# Since there is no need to create menu entries for that case.
# See: https://src.fedoraproject.org/rpms/grub2/c/7c2bab5e98d
. /etc/default/grub
if test -f /boot/grub2/.grub2-blscfg-supported && \
test "${GRUB_ENABLE_BLSCFG}" = "true"; then
exit 0
fi
# Make sure we're in the right environment
if ! test -n "${GRUB_DEVICE}"; then
echo "This script must be run as a child of grub2-mkconfig" 1>&2

View File

@ -23,7 +23,7 @@ Documentation=man:ostree(1)
ConditionPathExists=/run/ostree-booted
DefaultDependencies=no
RequiresMountsFor=/sysroot
RequiresMountsFor=/sysroot /boot
After=local-fs.target
Before=basic.target final.target
# We want to make sure the transaction logs are persisted to disk:
@ -39,3 +39,11 @@ ExecStop=/usr/bin/ostree admin finalize-staged
# here is that people don't get an upgrade. We need to handle
# cases with slow rotational media, etc.
TimeoutStopSec=5m
# OSTree should never touch /var at all...except, we need to remove
# the /var/.updated flag, so we can't just `InaccessiblePaths=/var` right now.
# For now, let's at least use ProtectHome just so we have some sandboxing
# of that.
ProtectHome=yes
# And we shouldn't affect the current deployment's /etc.
ReadOnlyPaths=/etc
# We write to /sysroot and /boot of course.

View File

@ -23,6 +23,7 @@ ConditionKernelCommandLine=ostree
ConditionPathExists=/etc/initrd-release
OnFailure=emergency.target
After=sysroot.mount
Requires=sysroot.mount
Before=initrd-root-fs.target
[Service]

View File

@ -17,12 +17,6 @@
Boston, MA 02111-1307, USA.
***/
/* Add new symbols here. Release commits should copy this section into -released.sym. */
LIBOSTREE_2020.2 {
global:
someostree_symbol_deleteme;
} LIBOSTREE_2020.1;
/* Stub section for the stable release *after* this development one; don't
* edit this other than to update the year. This is just a copy/paste
* source. Replace $LASTSTABLE with the last stable version, and $NEWVERSION

View File

@ -593,6 +593,28 @@ global:
ostree_sysroot_set_mount_namespace_in_use;
} LIBOSTREE_2019.6;
/* Add new symbols here. Release commits should copy this section into -released.sym. */
LIBOSTREE_2020.4 {
global:
ostree_repo_commit_modifier_set_sepolicy_from_commit;
ostree_sign_get_type;
ostree_sign_get_all;
ostree_sign_commit;
ostree_sign_commit_verify;
ostree_sign_data;
ostree_sign_data_verify;
ostree_sign_get_by_name;
ostree_sign_get_name;
ostree_sign_clear_keys;
ostree_sign_load_pk;
ostree_sign_metadata_format;
ostree_sign_metadata_key;
ostree_sign_set_pk;
ostree_sign_add_pk;
ostree_sign_set_sk;
ostree_sign_summary;
} LIBOSTREE_2020.1;
/* No new symbols in 2020.2 */
/* NOTE: Only add more content here in release commits! See the

View File

@ -73,6 +73,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinderOverride, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinderResult, ostree_repo_finder_result_free)
G_DEFINE_AUTO_CLEANUP_FREE_FUNC (OstreeRepoFinderResultv, ostree_repo_finder_result_freev, NULL)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeSign, g_object_unref)
#endif
G_END_DECLS

View File

@ -144,6 +144,10 @@ create_config_from_boot_loader_entries (OstreeBootloaderUboot *self,
if (val)
g_ptr_array_add (new_lines, g_strdup_printf ("fdt_file%s=%s", index_suffix, val));
val = ostree_bootconfig_parser_get (config, "fdtdir");
if (val)
g_ptr_array_add (new_lines, g_strdup_printf ("fdtdir%s=%s", index_suffix, val));
val = ostree_bootconfig_parser_get (config, "options");
if (val)
{

View File

@ -24,7 +24,6 @@
#include "ostree-cmdprivate.h"
#include "ostree-repo-private.h"
#include "ostree-core-private.h"
#include "ostree-repo-pull-private.h"
#include "ostree-repo-static-delta-private.h"
#include "ostree-sysroot-private.h"
#include "ostree-bootloader-grub2.h"

View File

@ -2376,6 +2376,13 @@ ostree_commit_get_parent (GVariant *commit_variant)
return ostree_checksum_from_bytes_v (bytes);
}
/**
* ostree_commit_get_timestamp:
* @commit_variant: Commit object
*
* Returns: timestamp in seconds since the Unix epoch, UTC
* Since: 2016.3
*/
guint64
ostree_commit_get_timestamp (GVariant *commit_variant)
{

View File

@ -212,6 +212,19 @@ typedef enum {
* Since: 2014.9
*/
#define OSTREE_COMMIT_META_KEY_VERSION "version"
/**
* OSTREE_COMMIT_META_KEY_ARCHITECTURE:
*
* GVariant type `s`. Intended to describe the CPU architecture. This is a freeform string, and some distributions
* which have existing package managers might want to match that schema. If you
* don't have a prior schema, it's recommended to use `uname -m` by default (i.e. the Linux kernel schema). In the future
* ostree might include a builtin function to compare architectures.
*
* Since: 2020.4
*/
#define OSTREE_COMMIT_META_KEY_ARCHITECTURE "ostree.architecture"
/**
* OSTREE_COMMIT_META_KEY_ENDOFLIFE_REBASE:
*

View File

@ -202,6 +202,7 @@ _ostree_fetcher_should_retry_request (const GError *error,
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT) ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_HOST_NOT_FOUND) ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE) ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT) ||
#if !GLIB_CHECK_VERSION(2, 44, 0)
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE) ||
#else

View File

@ -134,7 +134,7 @@ GVariant * ostree_gpg_verify_result_get_all (OstreeGpgVerifyResult *result,
* for future variations.
**/
typedef enum {
OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT = 0
OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT = (0 << 0),
} OstreeGpgSignatureFormatFlags;
_OSTREE_PUBLIC

View File

@ -51,15 +51,33 @@
#define FICLONE _IOW(0x94, 9, int)
#endif
/* If fsync is enabled and we're in a txn, we write into a staging dir for
* commit, but we also allow direct writes into objects/ for e.g. hardlink
* imports.
/* Understanding ostree's fsync strategy
*
* A long time ago, ostree used to invoke fsync() on each object,
* then move it into the objects directory. However, it turned
* out to be a *lot* faster to write the objects into a separate "staging"
* directory (letting the filesystem handle writeback how it likes)
* and then only walk over each of the files, fsync(), then rename()
* into place. See also https://lwn.net/Articles/789024/
*
* (We also support a "disable fsync entirely" mode, where you don't
* care about integrity; e.g. test suites using disposable VMs).
*
* This "delayed fsync" pattern though is much worse for other concurrent processes
* like databases because it forces a lot to go through the filesystem
* journal at once once we do the sync. So now we support a `per_object_fsync`
* option that again invokes `fsync()` directly. This also notably
* provides "backpressure", ensuring we aren't queuing up a huge amount
* of I/O at once.
*/
/* The directory where we place content */
static int
commit_dest_dfd (OstreeRepo *self)
{
if (self->in_transaction && !self->disable_fsync)
if (self->per_object_fsync)
return self->objects_dir_fd;
else if (self->in_transaction && !self->disable_fsync)
return self->commit_stagedir.fd;
else
return self->objects_dir_fd;
@ -420,7 +438,7 @@ commit_loose_regfile_object (OstreeRepo *self,
/* Ensure that in case of a power cut, these files have the data we
* want. See http://lwn.net/Articles/322823/
*/
if (!self->in_transaction && !self->disable_fsync)
if (!self->disable_fsync && self->per_object_fsync)
{
if (fsync (tmpf->fd) == -1)
return glnx_throw_errno_prefix (error, "fsync");
@ -1835,6 +1853,52 @@ ostree_repo_prepare_transaction (OstreeRepo *self,
return TRUE;
}
/* Synchronize the directories holding the objects */
static gboolean
fsync_object_dirs (OstreeRepo *self,
GCancellable *cancellable,
GError **error)
{
GLNX_AUTO_PREFIX_ERROR ("fsync objdirs", error);
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
if (self->disable_fsync)
return TRUE; /* No fsync? Nothing to do then. */
if (!glnx_dirfd_iterator_init_at (self->objects_dir_fd, ".", FALSE, &dfd_iter, error))
return FALSE;
while (TRUE)
{
struct dirent *dent;
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error))
return FALSE;
if (dent == NULL)
break;
if (dent->d_type != DT_DIR)
continue;
/* All object directories only have two character entries */
if (strlen (dent->d_name) != 2)
continue;
glnx_autofd int target_dir_fd = -1;
if (!glnx_opendirat (self->objects_dir_fd, dent->d_name, FALSE,
&target_dir_fd, error))
return FALSE;
/* This synchronizes the directory to ensure all the objects we wrote
* are there. We need to do this before removing the .commitpartial
* stamp (or have a ref point to the commit).
*/
if (fsync (target_dir_fd) == -1)
return glnx_throw_errno_prefix (error, "fsync");
}
/* In case we created any loose object subdirs, make sure they are on disk */
if (fsync (self->objects_dir_fd) == -1)
return glnx_throw_errno_prefix (error, "fsync");
return TRUE;
}
/* Called for commit, to iterate over the "staging" directory and rename all the
* objects into the primary objects/ location. Notably this is called only after
* syncfs() has potentially been invoked to ensure that all objects have been
@ -1856,10 +1920,6 @@ rename_pending_loose_objects (OstreeRepo *self,
while (TRUE)
{
struct dirent *dent;
gboolean renamed_some_object = FALSE;
g_auto(GLnxDirFdIterator) child_dfd_iter = { 0, };
char loose_objpath[_OSTREE_LOOSE_PATH_MAX];
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error))
return FALSE;
if (dent == NULL)
@ -1872,10 +1932,12 @@ rename_pending_loose_objects (OstreeRepo *self,
if (strlen (dent->d_name) != 2)
continue;
g_auto(GLnxDirFdIterator) child_dfd_iter = { 0, };
if (!glnx_dirfd_iterator_init_at (dfd_iter.fd, dent->d_name, FALSE,
&child_dfd_iter, error))
return FALSE;
char loose_objpath[_OSTREE_LOOSE_PATH_MAX];
loose_objpath[0] = dent->d_name[0];
loose_objpath[1] = dent->d_name[1];
loose_objpath[2] = '/';
@ -1899,41 +1961,13 @@ rename_pending_loose_objects (OstreeRepo *self,
if (!glnx_renameat (child_dfd_iter.fd, loose_objpath + 3,
self->objects_dir_fd, loose_objpath, error))
return FALSE;
renamed_some_object = TRUE;
}
if (renamed_some_object && !self->disable_fsync)
{
/* Ensure that in the case of a power cut all the directory metadata that
we want has reached the disk. In particular, we want this before we
update the refs to point to these objects. */
glnx_autofd int target_dir_fd = -1;
loose_objpath[2] = 0;
if (!glnx_opendirat (self->objects_dir_fd,
loose_objpath, FALSE,
&target_dir_fd,
error))
return FALSE;
if (fsync (target_dir_fd) == -1)
return glnx_throw_errno_prefix (error, "fsync");
}
}
/* In case we created any loose object subdirs, make sure they are on disk */
if (!self->disable_fsync)
{
if (fsync (self->objects_dir_fd) == -1)
return glnx_throw_errno_prefix (error, "fsync");
}
return TRUE;
}
/* Try to lock a transaction stage directory created by
/* Try to lock and delete a transaction stage directory created by
* ostree_repo_prepare_transaction().
*/
static gboolean
@ -1943,6 +1977,9 @@ cleanup_txn_dir (OstreeRepo *self,
GCancellable *cancellable,
GError **error)
{
const char *errprefix = glnx_strjoina ("Cleaning up txn dir ", path);
GLNX_AUTO_PREFIX_ERROR (errprefix, error);
g_auto(GLnxLockFile) lockfile = { 0, };
gboolean did_lock;
@ -2008,7 +2045,7 @@ cleanup_tmpdir (OstreeRepo *self,
continue;
/* Handle transaction tmpdirs */
if (_ostree_repo_is_locked_tmpdir (dent->d_name))
if (_ostree_repo_has_staging_prefix (dent->d_name) && S_ISDIR (stbuf.st_mode))
{
if (!cleanup_txn_dir (self, dfd_iter.fd, dent->d_name, cancellable, error))
return FALSE;
@ -2374,6 +2411,9 @@ ostree_repo_commit_transaction (OstreeRepo *self,
if (!rename_pending_loose_objects (self, cancellable, error))
return FALSE;
if (!fsync_object_dirs (self, cancellable, error))
return FALSE;
g_debug ("txn commit %s", glnx_basename (self->commit_stagedir.path));
if (!glnx_tmpdir_delete (&self->commit_stagedir, cancellable, error))
return FALSE;
@ -4227,9 +4267,11 @@ ostree_repo_commit_modifier_unref (OstreeRepoCommitModifier *modifier)
if (modifier->xattr_destroy)
modifier->xattr_destroy (modifier->xattr_user_data);
g_clear_object (&modifier->sepolicy);
g_clear_pointer (&modifier->devino_cache, (GDestroyNotify)g_hash_table_unref);
g_clear_object (&modifier->sepolicy);
(void) glnx_tmpdir_delete (&modifier->sepolicy_tmpdir, NULL, NULL);
g_free (modifier);
return;
}
@ -4279,6 +4321,60 @@ ostree_repo_commit_modifier_set_sepolicy (OstreeRepoCommitModifier
modifier->sepolicy = sepolicy ? g_object_ref (sepolicy) : NULL;
}
/**
* ostree_repo_commit_modifier_set_sepolicy_from_commit:
* @modifier: Commit modifier
* @repo: OSTree repo containing @rev
* @rev: Find SELinux policy from this base commit
* @cancellable:
* @error:
*
* In many cases, one wants to create a "derived" commit from base commit.
* SELinux policy labels are part of that base commit. This API allows
* one to easily set up SELinux labeling from a base commit.
*/
gboolean
ostree_repo_commit_modifier_set_sepolicy_from_commit (OstreeRepoCommitModifier *modifier,
OstreeRepo *repo,
const char *rev,
GCancellable *cancellable,
GError **error)
{
GLNX_AUTO_PREFIX_ERROR ("setting sepolicy from commit", error);
g_autofree char *commit = NULL;
g_autoptr(GFile) root = NULL;
if (!ostree_repo_read_commit (repo, rev, &root, &commit, cancellable, error))
return FALSE;
const char policypath[] = "usr/etc/selinux";
g_autoptr(GFile) policyroot = g_file_get_child (root, policypath);
if (!g_file_query_exists (policyroot, NULL))
return TRUE; /* No policy, nothing to do */
GLnxTmpDir tmpdir = {0,};
if (!glnx_mkdtemp ("ostree-commit-sepolicy-XXXXXX", 0700, &tmpdir, error))
return FALSE;
if (!glnx_shutil_mkdir_p_at (tmpdir.fd, "usr/etc", 0755, cancellable, error))
return FALSE;
OstreeRepoCheckoutAtOptions coopts = {0,};
coopts.mode = OSTREE_REPO_CHECKOUT_MODE_USER;
coopts.subpath = glnx_strjoina ("/", policypath);
if (!ostree_repo_checkout_at (repo, &coopts, tmpdir.fd, policypath, commit, cancellable, error))
return glnx_prefix_error (error, "policy checkout");
g_autoptr(OstreeSePolicy) policy = ostree_sepolicy_new_at (tmpdir.fd, cancellable, error);
if (!policy)
return glnx_prefix_error (error, "reading policy");
ostree_repo_commit_modifier_set_sepolicy (modifier, policy);
/* Transfer ownership */
modifier->sepolicy_tmpdir = tmpdir;
tmpdir.initialized = FALSE;
return TRUE;
}
/**
* ostree_repo_commit_modifier_set_devino_cache:
* @modifier: Modifier

View File

@ -24,9 +24,11 @@
#include "ostree-core.h"
#include "ostree-types.h"
#ifndef __GI_SCANNER__
#ifndef G_GNUC_DEPRECATED_FOR
# define G_GNUC_DEPRECATED_FOR(x)
#endif
#endif
G_BEGIN_DECLS

View File

@ -1358,7 +1358,7 @@ ostree_repo_finder_avahi_init (OstreeRepoFinderAvahi *self)
}
/**
* ostree_repo-finder_avahi_new:
* ostree_repo_finder_avahi_new:
* @context: (transfer none) (nullable): a #GMainContext for processing Avahi
* events in, or %NULL to use the current thread-default
*

View File

@ -38,13 +38,17 @@ G_BEGIN_DECLS
#define _OSTREE_MAX_OUTSTANDING_FETCHER_REQUESTS 8
#define _OSTREE_MAX_OUTSTANDING_DELTAPART_REQUESTS 2
/* In most cases, writing to disk should be much faster than
* fetching from the network, so we shouldn't actually hit
* this. But if using pipelining and e.g. pulling over LAN
* (or writing to slow media), we can have a runaway
* situation towards EMFILE.
/* We want some parallelism with disk writes, but we also
* want to avoid starting tens or hundreds of threads
* (via GTask) all writing to disk. Eventually we may
* use io_uring which handles backpressure correctly.
* Also, in "immediate fsync" mode, this helps provide
* much more backpressure, helping our I/O patterns
* be nicer for any concurrent processes, such as etcd
* or other databases.
* https://github.com/openshift/machine-config-operator/issues/1897
* */
#define _OSTREE_MAX_OUTSTANDING_WRITE_REQUESTS 16
#define _OSTREE_MAX_OUTSTANDING_WRITE_REQUESTS 3
/* Well-known keys for the additional metadata field in a summary file. */
#define OSTREE_SUMMARY_LAST_MODIFIED "ostree.summary.last-modified"
@ -76,6 +80,7 @@ struct OstreeRepoCommitModifier {
GDestroyNotify xattr_destroy;
gpointer xattr_user_data;
GLnxTmpDir sepolicy_tmpdir;
OstreeSePolicy *sepolicy;
GHashTable *devino_cache;
};
@ -146,6 +151,7 @@ struct OstreeRepo {
GError *writable_error;
gboolean in_transaction;
gboolean disable_fsync;
gboolean per_object_fsync;
gboolean disable_xattrs;
guint zlib_compression_level;
GHashTable *loose_object_devino_hash;
@ -246,7 +252,7 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd,
GError **error);
gboolean
_ostree_repo_is_locked_tmpdir (const char *filename);
_ostree_repo_has_staging_prefix (const char *filename);
gboolean
_ostree_repo_try_lock_tmpdir (int tmpdir_dfd,
@ -373,9 +379,9 @@ _ostree_repo_verify_commit_internal (OstreeRepo *self,
#endif /* OSTREE_DISABLE_GPGME */
typedef enum {
_OSTREE_REPO_IMPORT_FLAGS_NONE,
_OSTREE_REPO_IMPORT_FLAGS_TRUSTED,
_OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY,
_OSTREE_REPO_IMPORT_FLAGS_NONE = 0,
_OSTREE_REPO_IMPORT_FLAGS_TRUSTED = (1 << 0),
_OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY = (1 << 1),
} OstreeRepoImportFlags;
gboolean
@ -501,4 +507,10 @@ _ostree_tmpf_fsverity (OstreeRepo *self,
GLnxTmpfile *tmpf,
GError **error);
gboolean
_ostree_repo_verify_bindings (const char *collection_id,
const char *ref_name,
GVariant *commit,
GError **error);
G_END_DECLS

View File

@ -21,14 +21,151 @@
#pragma once
#include "ostree-core.h"
#include "ostree-repo-private.h"
#include "ostree-fetcher-util.h"
#include "ostree-remote-private.h"
G_BEGIN_DECLS
typedef enum {
OSTREE_FETCHER_SECURITY_STATE_CA_PINNED,
OSTREE_FETCHER_SECURITY_STATE_TLS,
OSTREE_FETCHER_SECURITY_STATE_INSECURE,
} OstreeFetcherSecurityState;
typedef struct {
OstreeRepo *repo;
int tmpdir_dfd;
OstreeRepoPullFlags flags;
char *remote_name;
char *remote_refspec_name;
OstreeRepoMode remote_mode;
OstreeFetcher *fetcher;
OstreeFetcherSecurityState fetcher_security_state;
GPtrArray *meta_mirrorlist; /* List of base URIs for fetching metadata */
GPtrArray *content_mirrorlist; /* List of base URIs for fetching content */
OstreeRepo *remote_repo_local;
GPtrArray *localcache_repos; /* Array<OstreeRepo> */
GMainContext *main_context;
GCancellable *cancellable;
OstreeAsyncProgress *progress;
GVariant *extra_headers;
char *append_user_agent;
gboolean dry_run;
gboolean dry_run_emitted_progress;
gboolean legacy_transaction_resuming;
guint n_network_retries;
enum {
OSTREE_PULL_PHASE_FETCHING_REFS,
OSTREE_PULL_PHASE_FETCHING_OBJECTS
} phase;
gint n_scanned_metadata;
gboolean gpg_verify;
gboolean gpg_verify_summary;
gboolean require_static_deltas;
gboolean disable_static_deltas;
gboolean has_tombstone_commits;
GBytes *summary_data;
GBytes *summary_data_sig;
GVariant *summary;
GHashTable *summary_deltas_checksums;
GHashTable *ref_original_commits; /* Maps checksum to commit, used by timestamp checks */
GHashTable *verified_commits; /* Set<checksum> of commits that have been verified */
GHashTable *signapi_verified_commits; /* Map<checksum,verification> of commits that have been signapi verified */
GHashTable *ref_keyring_map; /* Maps OstreeCollectionRef to keyring remote name */
GPtrArray *static_delta_superblocks;
GHashTable *expected_commit_sizes; /* Maps commit checksum to known size */
GHashTable *commit_to_depth; /* Maps commit checksum maximum depth */
GHashTable *scanned_metadata; /* Maps object name to itself */
GHashTable *fetched_detached_metadata; /* Map<checksum,GVariant> */
GHashTable *requested_metadata; /* Maps object name to itself */
GHashTable *requested_content; /* Maps checksum to itself */
GHashTable *requested_fallback_content; /* Maps checksum to itself */
GHashTable *pending_fetch_metadata; /* Map<ObjectName,FetchObjectData> */
GHashTable *pending_fetch_content; /* Map<checksum,FetchObjectData> */
GHashTable *pending_fetch_delta_superblocks; /* Set<FetchDeltaSuperData> */
GHashTable *pending_fetch_deltaparts; /* Set<FetchStaticDeltaData> */
guint n_outstanding_metadata_fetches;
guint n_outstanding_metadata_write_requests;
guint n_outstanding_content_fetches;
guint n_outstanding_content_write_requests;
guint n_outstanding_deltapart_fetches;
guint n_outstanding_deltapart_write_requests;
guint n_total_deltaparts;
guint n_total_delta_fallbacks;
guint64 fetched_deltapart_size; /* How much of the delta we have now */
guint64 total_deltapart_size;
guint64 total_deltapart_usize;
gint n_requested_metadata;
gint n_requested_content;
guint n_fetched_deltaparts;
guint n_fetched_deltapart_fallbacks;
guint n_fetched_metadata;
guint n_fetched_content;
/* Objects imported via hardlink/reflink/copying or --localcache-repo*/
guint n_imported_metadata;
guint n_imported_content;
gboolean timestamp_check; /* Verify commit timestamps */
char *timestamp_check_from_rev;
int maxdepth;
guint64 max_metadata_size;
guint64 start_time;
gboolean is_mirror;
gboolean trusted_http_direct;
gboolean is_commit_only;
OstreeRepoImportFlags importflags;
GPtrArray *signapi_commit_verifiers;
GPtrArray *signapi_summary_verifiers;
GPtrArray *dirs;
gboolean have_previous_bytes;
guint64 previous_bytes_sec;
guint64 previous_total_downloaded;
GError *cached_async_error;
GError **async_error;
gboolean caught_error;
GQueue scan_object_queue;
GSource *idle_src;
} OtPullData;
gboolean
_ostree_repo_verify_bindings (const char *collection_id,
const char *ref_name,
GVariant *commit,
GError **error);
_signapi_init_for_remote (OstreeRepo *repo,
const char *remote_name,
GPtrArray **out_commit_verifiers,
GPtrArray **out_summary_verifiers,
GError **error);
gboolean
_sign_verify_for_remote (GPtrArray *signers,
GBytes *signed_data,
GVariant *metadata,
char **out_success_message,
GError **error);
gboolean
_verify_unwritten_commit (OtPullData *pull_data,
const char *checksum,
GVariant *commit,
GVariant *detached_metadata,
const OstreeCollectionRef *ref,
GCancellable *cancellable,
GError **error);
gboolean
_process_gpg_verify_result (OtPullData *pull_data,
const char *checksum,
OstreeGpgVerifyResult *result,
GError **error);
G_END_DECLS

View File

@ -0,0 +1,401 @@
/*
* Copyright (C) 2020 Red Hat, Inc.
* Copyright © 2017 Endless Mobile, Inc.
*
* SPDX-License-Identifier: LGPL-2.0+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "libglnx.h"
#include "ostree.h"
#include "otutil.h"
#include "ostree-repo-pull-private.h"
#include "ostree-repo-private.h"
#include "ostree-core-private.h"
#include "ostree-repo-static-delta-private.h"
#include "ostree-metalink.h"
#include "ostree-fetcher-util.h"
#include "ostree-remote-private.h"
#include "ot-fs-utils.h"
#include <gio/gunixinputstream.h>
#include <sys/statvfs.h>
#ifdef HAVE_LIBSYSTEMD
#include <systemd/sd-journal.h>
#endif
#include "ostree-sign.h"
static gboolean
get_signapi_remote_option (OstreeRepo *repo,
OstreeSign *sign,
const char *remote_name,
const char *keysuffix,
char **out_value,
GError **error)
{
g_autofree char *key = g_strdup_printf ("verification-%s-%s", ostree_sign_get_name (sign), keysuffix);
return ostree_repo_get_remote_option (repo, remote_name, key, NULL, out_value, error);
}
/* _signapi_load_public_keys:
*
* Load public keys according remote's configuration:
* inlined key passed via config option `verification-<signapi>-key` or
* file name with public keys via `verification-<signapi>-file` option.
*
* If both options are set then load all all public keys
* both from file and inlined in config.
*
* Returns: %FALSE if any source is configured but nothing has been loaded.
* Returns: %TRUE if no configuration or any key loaded.
* */
static gboolean
_signapi_load_public_keys (OstreeSign *sign,
OstreeRepo *repo,
const gchar *remote_name,
gboolean required,
GError **error)
{
g_autofree gchar *pk_ascii = NULL;
g_autofree gchar *pk_file = NULL;
gboolean loaded_from_file = TRUE;
gboolean loaded_inlined = TRUE;
if (!get_signapi_remote_option (repo, sign, remote_name, "file", &pk_file, error))
return FALSE;
if (!get_signapi_remote_option (repo, sign, remote_name, "key", &pk_ascii, error))
return FALSE;
/* return TRUE if there is no configuration for remote */
if ((pk_file == NULL) &&(pk_ascii == NULL))
{
/* It is expected what remote may have verification file as
* a part of configuration. Hence there is not a lot of sense
* for automatic resolve of per-remote keystore file as it
* used in find_keyring () for GPG.
* If it is needed to add the similar mechanism, it is preferable
* to pass the path to ostree_sign_load_pk () via GVariant options
* and call it here for loading with method and file structure
* specific for signature type.
*/
if (required)
return glnx_throw (error, "No keys found for required signapi type %s", ostree_sign_get_name (sign));
return TRUE;
}
if (pk_file != NULL)
{
g_autoptr (GError) local_error = NULL;
g_autoptr (GVariantBuilder) builder = NULL;
g_autoptr (GVariant) options = NULL;
builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (builder, "{sv}", "filename", g_variant_new_string (pk_file));
options = g_variant_builder_end (builder);
if (ostree_sign_load_pk (sign, options, &local_error))
loaded_from_file = TRUE;
else
{
return glnx_throw (error, "Failed loading '%s' keys from '%s",
ostree_sign_get_name (sign), pk_file);
}
}
if (pk_ascii != NULL)
{
g_autoptr (GError) local_error = NULL;
g_autoptr (GVariant) pk = g_variant_new_string(pk_ascii);
/* Add inlined public key */
if (loaded_from_file)
loaded_inlined = ostree_sign_add_pk (sign, pk, &local_error);
else
loaded_inlined = ostree_sign_set_pk (sign, pk, &local_error);
if (!loaded_inlined)
{
return glnx_throw (error, "Failed loading '%s' keys from inline `verification-key`",
ostree_sign_get_name (sign));
}
}
/* Return true if able to load from any source */
if (!(loaded_from_file || loaded_inlined))
return glnx_throw (error, "No keys found");
return TRUE;
}
static gboolean
string_is_gkeyfile_truthy (const char *value,
gboolean *out_truth)
{
/* See https://gitlab.gnome.org/GNOME/glib/-/blob/20fb5bf868added5aec53c013ae85ec78ba2eedc/glib/gkeyfile.c#L4528 */
if (g_str_equal (value, "true") || g_str_equal (value, "1"))
{
*out_truth = TRUE;
return TRUE;
}
else if (g_str_equal (value, "false") || g_str_equal (value, "0"))
{
*out_truth = FALSE;
return TRUE;
}
return FALSE;
}
static gboolean
verifiers_from_config (OstreeRepo *repo,
const char *remote_name,
const char *key,
GPtrArray **out_verifiers,
GError **error)
{
g_autoptr(GPtrArray) verifiers = NULL;
g_autofree char *raw_value = NULL;
if (!ostree_repo_get_remote_option (repo, remote_name,
key, NULL,
&raw_value, error))
return FALSE;
if (raw_value == NULL || g_str_equal (raw_value, ""))
{
*out_verifiers = NULL;
return TRUE;
}
gboolean sign_verify_bool = FALSE;
/* Is the value "truthy" according to GKeyFile's rules? If so,
* then we take this to be "accept signatures from any compiled
* type that happens to have keys configured".
*/
if (string_is_gkeyfile_truthy (raw_value, &sign_verify_bool))
{
if (sign_verify_bool)
{
verifiers = ostree_sign_get_all ();
for (guint i = 0; i < verifiers->len; i++)
{
OstreeSign *sign = verifiers->pdata[i];
/* Try to load public key(s) according remote's configuration;
* this one is optional.
*/
if (!_signapi_load_public_keys (sign, repo, remote_name, FALSE, error))
return FALSE;
}
}
}
else
{
/* If the value isn't "truthy", then it must be an explicit list */
g_auto(GStrv) sign_types = NULL;
if (!ostree_repo_get_remote_list_option (repo, remote_name,
key, &sign_types,
error))
return FALSE;
verifiers = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
for (char **iter = sign_types; iter && *iter; iter++)
{
const char *sign_type = *iter;
OstreeSign *verifier = ostree_sign_get_by_name (sign_type, error);
if (!verifier)
return FALSE;
if (!_signapi_load_public_keys (verifier, repo, remote_name, TRUE, error))
return FALSE;
g_ptr_array_add (verifiers, verifier);
}
g_assert_cmpuint (verifiers->len, >=, 1);
}
*out_verifiers = g_steal_pointer (&verifiers);
return TRUE;
}
/* Create a new array of OstreeSign objects and load the public
* keys as described by the remote configuration. If the
* remote does not have signing verification enabled, then
* the resulting verifier list will be NULL.
*/
gboolean
_signapi_init_for_remote (OstreeRepo *repo,
const char *remote_name,
GPtrArray **out_commit_verifiers,
GPtrArray **out_summary_verifiers,
GError **error)
{
g_autoptr(GPtrArray) commit_verifiers = NULL;
g_autoptr(GPtrArray) summary_verifiers = NULL;
if (!verifiers_from_config (repo, remote_name, "sign-verify", &commit_verifiers, error))
return FALSE;
if (!verifiers_from_config (repo, remote_name, "sign-verify-summary", &summary_verifiers, error))
return FALSE;
ot_transfer_out_value (out_commit_verifiers, &commit_verifiers);
ot_transfer_out_value (out_summary_verifiers, &summary_verifiers);
return TRUE;
}
/* Iterate over the configured verifiers, and require the commit is signed
* by at least one.
*/
gboolean
_sign_verify_for_remote (GPtrArray *verifiers,
GBytes *signed_data,
GVariant *metadata,
char **out_success_message,
GError **error)
{
guint n_invalid_signatures = 0;
g_autoptr (GError) last_sig_error = NULL;
gboolean found_sig = FALSE;
g_assert (out_success_message == NULL || *out_success_message == NULL);
g_assert_cmpuint (verifiers->len, >=, 1);
for (guint i = 0; i < verifiers->len; i++)
{
OstreeSign *sign = verifiers->pdata[i];
const gchar *signature_key = ostree_sign_metadata_key (sign);
GVariantType *signature_format = (GVariantType *) ostree_sign_metadata_format (sign);
g_autoptr (GVariant) signatures =
g_variant_lookup_value (metadata, signature_key, signature_format);
/* If not found signatures for requested signature subsystem */
if (!signatures)
continue;
found_sig = TRUE;
g_autofree char *success_message = NULL;
/* Return true if any signature fit to pre-loaded public keys.
* If no keys configured -- then system configuration will be used */
if (!ostree_sign_data_verify (sign,
signed_data,
signatures,
&success_message,
last_sig_error ? NULL : &last_sig_error))
{
n_invalid_signatures++;
continue;
}
/* Accept the first valid signature */
if (out_success_message)
*out_success_message = g_steal_pointer (&success_message);
return TRUE;
}
if (!found_sig)
return glnx_throw (error, "No signatures found");
g_assert (last_sig_error);
g_propagate_error (error, g_steal_pointer (&last_sig_error));
if (n_invalid_signatures > 1)
glnx_prefix_error (error, "(%d other invalid signatures)", n_invalid_signatures-1);
return FALSE;
}
#ifndef OSTREE_DISABLE_GPGME
gboolean
_process_gpg_verify_result (OtPullData *pull_data,
const char *checksum,
OstreeGpgVerifyResult *result,
GError **error)
{
const char *error_prefix = glnx_strjoina ("Commit ", checksum);
GLNX_AUTO_PREFIX_ERROR(error_prefix, error);
if (result == NULL)
return FALSE;
/* Allow callers to output the results immediately. */
g_signal_emit_by_name (pull_data->repo,
"gpg-verify-result",
checksum, result);
if (!ostree_gpg_verify_result_require_valid_signature (result, error))
return FALSE;
/* We now check both *before* writing the commit, and after. Because the
* behavior used to be only verifiying after writing, we need to handle
* the case of "written but not verified". But we also don't want to check
* twice, as that'd result in duplicate signals.
*/
g_hash_table_add (pull_data->verified_commits, g_strdup (checksum));
return TRUE;
}
#endif /* OSTREE_DISABLE_GPGME */
gboolean
_verify_unwritten_commit (OtPullData *pull_data,
const char *checksum,
GVariant *commit,
GVariant *detached_metadata,
const OstreeCollectionRef *ref,
GCancellable *cancellable,
GError **error)
{
/* Shouldn't happen, but see comment in process_gpg_verify_result() */
if ((!pull_data->gpg_verify || g_hash_table_contains (pull_data->verified_commits, checksum))
&& (!pull_data->signapi_commit_verifiers || g_hash_table_contains (pull_data->signapi_verified_commits, checksum)))
return TRUE;
g_autoptr(GBytes) signed_data = g_variant_get_data_as_bytes (commit);
#ifndef OSTREE_DISABLE_GPGME
if (pull_data->gpg_verify)
{
const char *keyring_remote = NULL;
if (ref != NULL)
keyring_remote = g_hash_table_lookup (pull_data->ref_keyring_map, ref);
if (keyring_remote == NULL)
keyring_remote = pull_data->remote_name;
g_autoptr(OstreeGpgVerifyResult) result =
_ostree_repo_gpg_verify_with_metadata (pull_data->repo, signed_data,
detached_metadata,
keyring_remote,
NULL, NULL, cancellable, error);
if (!_process_gpg_verify_result (pull_data, checksum, result, error))
return FALSE;
}
#endif /* OSTREE_DISABLE_GPGME */
if (pull_data->signapi_commit_verifiers)
{
/* Nothing to check if detached metadata is absent */
if (detached_metadata == NULL)
return glnx_throw (error, "Can't verify commit without detached metadata");
g_autofree char *success_message = NULL;
if (!_sign_verify_for_remote (pull_data->signapi_commit_verifiers, signed_data, detached_metadata, &success_message, error))
return glnx_prefix_error (error, "Can't verify commit");
/* Mark the commit as verified to avoid double verification
* see process_verify_result () for rationale */
g_hash_table_insert (pull_data->signapi_verified_commits, g_strdup (checksum), g_steal_pointer (&success_message));
}
return TRUE;
}

View File

@ -30,16 +30,12 @@
#include "ostree.h"
#include "otutil.h"
#include "ostree-repo-pull-private.h"
#include "ostree-repo-private.h"
#ifdef HAVE_LIBCURL_OR_LIBSOUP
#include "ostree-core-private.h"
#include "ostree-repo-static-delta-private.h"
#include "ostree-metalink.h"
#include "ostree-fetcher-util.h"
#include "ostree-remote-private.h"
#include "ot-fs-utils.h"
#include "ostree-repo-finder.h"
#include "ostree-repo-finder-config.h"
@ -65,114 +61,6 @@
* `n-network-retries` pull option. */
#define DEFAULT_N_NETWORK_RETRIES 5
typedef enum {
OSTREE_FETCHER_SECURITY_STATE_CA_PINNED,
OSTREE_FETCHER_SECURITY_STATE_TLS,
OSTREE_FETCHER_SECURITY_STATE_INSECURE,
} OstreeFetcherSecurityState;
typedef struct {
OstreeRepo *repo;
int tmpdir_dfd;
OstreeRepoPullFlags flags;
char *remote_name;
char *remote_refspec_name;
OstreeRepoMode remote_mode;
OstreeFetcher *fetcher;
OstreeFetcherSecurityState fetcher_security_state;
GPtrArray *meta_mirrorlist; /* List of base URIs for fetching metadata */
GPtrArray *content_mirrorlist; /* List of base URIs for fetching content */
OstreeRepo *remote_repo_local;
GPtrArray *localcache_repos; /* Array<OstreeRepo> */
GMainContext *main_context;
GCancellable *cancellable;
OstreeAsyncProgress *progress;
GVariant *extra_headers;
char *append_user_agent;
gboolean dry_run;
gboolean dry_run_emitted_progress;
gboolean legacy_transaction_resuming;
guint n_network_retries;
enum {
OSTREE_PULL_PHASE_FETCHING_REFS,
OSTREE_PULL_PHASE_FETCHING_OBJECTS
} phase;
gint n_scanned_metadata;
gboolean gpg_verify;
gboolean gpg_verify_summary;
gboolean require_static_deltas;
gboolean disable_static_deltas;
gboolean has_tombstone_commits;
GBytes *summary_data;
GBytes *summary_data_sig;
GVariant *summary;
GHashTable *summary_deltas_checksums;
GHashTable *ref_original_commits; /* Maps checksum to commit, used by timestamp checks */
GHashTable *verified_commits; /* Set<checksum> of commits that have been verified */
GHashTable *ref_keyring_map; /* Maps OstreeCollectionRef to keyring remote name */
GPtrArray *static_delta_superblocks;
GHashTable *expected_commit_sizes; /* Maps commit checksum to known size */
GHashTable *commit_to_depth; /* Maps commit checksum maximum depth */
GHashTable *scanned_metadata; /* Maps object name to itself */
GHashTable *fetched_detached_metadata; /* Map<checksum,GVariant> */
GHashTable *requested_metadata; /* Maps object name to itself */
GHashTable *requested_content; /* Maps checksum to itself */
GHashTable *requested_fallback_content; /* Maps checksum to itself */
GHashTable *pending_fetch_metadata; /* Map<ObjectName,FetchObjectData> */
GHashTable *pending_fetch_content; /* Map<checksum,FetchObjectData> */
GHashTable *pending_fetch_delta_superblocks; /* Set<FetchDeltaSuperData> */
GHashTable *pending_fetch_deltaparts; /* Set<FetchStaticDeltaData> */
guint n_outstanding_metadata_fetches;
guint n_outstanding_metadata_write_requests;
guint n_outstanding_content_fetches;
guint n_outstanding_content_write_requests;
guint n_outstanding_deltapart_fetches;
guint n_outstanding_deltapart_write_requests;
guint n_total_deltaparts;
guint n_total_delta_fallbacks;
guint64 fetched_deltapart_size; /* How much of the delta we have now */
guint64 total_deltapart_size;
guint64 total_deltapart_usize;
gint n_requested_metadata;
gint n_requested_content;
guint n_fetched_deltaparts;
guint n_fetched_deltapart_fallbacks;
guint n_fetched_metadata;
guint n_fetched_content;
/* Objects imported via hardlink/reflink/copying or --localcache-repo*/
guint n_imported_metadata;
guint n_imported_content;
gboolean timestamp_check; /* Verify commit timestamps */
int maxdepth;
guint64 max_metadata_size;
guint64 start_time;
gboolean is_mirror;
gboolean trusted_http_direct;
gboolean is_commit_only;
OstreeRepoImportFlags importflags;
GPtrArray *dirs;
gboolean have_previous_bytes;
guint64 previous_bytes_sec;
guint64 previous_total_downloaded;
GError *cached_async_error;
GError **async_error;
gboolean caught_error;
GQueue scan_object_queue;
GSource *idle_src;
} OtPullData;
typedef struct {
OtPullData *pull_data;
GVariant *object;
@ -260,14 +148,6 @@ static gboolean scan_one_metadata_object (OtPullData *pull_data,
GCancellable *cancellable,
GError **error);
static void scan_object_queue_data_free (ScanObjectQueueData *scan_data);
static gboolean
ostree_verify_unwritten_commit (OtPullData *pull_data,
const char *checksum,
GVariant *commit,
GVariant *detached_metadata,
const OstreeCollectionRef *ref,
GCancellable *cancellable,
GError **error);
static gboolean
update_progress (gpointer user_data)
@ -1119,7 +999,10 @@ content_fetch_on_complete (GObject *object,
if (!ostree_content_stream_parse (TRUE, tmpf_input, stbuf.st_size, FALSE,
&file_in, &file_info, &xattrs,
cancellable, error))
goto out;
{
g_prefix_error (error, "Parsing %s: ", checksum_obj);
goto out;
}
if (verifying_bareuseronly)
{
@ -1309,8 +1192,8 @@ meta_fetch_on_complete (GObject *object,
* metadata into this hash.
*/
GVariant *detached_data = g_hash_table_lookup (pull_data->fetched_detached_metadata, checksum);
if (!ostree_verify_unwritten_commit (pull_data, checksum, metadata, detached_data,
fetch_data->requested_ref, pull_data->cancellable, error))
if (!_verify_unwritten_commit (pull_data, checksum, metadata, detached_data,
fetch_data->requested_ref, pull_data->cancellable, error))
goto out;
if (!ostree_repo_mark_commit_partial (pull_data->repo, checksum, TRUE, error))
@ -1434,75 +1317,6 @@ static_deltapart_fetch_on_complete (GObject *object,
g_clear_pointer (&fetch_data, fetch_static_delta_data_free);
}
#ifndef OSTREE_DISABLE_GPGME
static gboolean
process_verify_result (OtPullData *pull_data,
const char *checksum,
OstreeGpgVerifyResult *result,
GError **error)
{
const char *error_prefix = glnx_strjoina ("Commit ", checksum);
GLNX_AUTO_PREFIX_ERROR(error_prefix, error);
if (result == NULL)
return FALSE;
/* Allow callers to output the results immediately. */
g_signal_emit_by_name (pull_data->repo,
"gpg-verify-result",
checksum, result);
if (!ostree_gpg_verify_result_require_valid_signature (result, error))
return FALSE;
/* We now check both *before* writing the commit, and after. Because the
* behavior used to be only verifiying after writing, we need to handle
* the case of "written but not verified". But we also don't want to check
* twice, as that'd result in duplicate signals.
*/
g_hash_table_add (pull_data->verified_commits, g_strdup (checksum));
return TRUE;
}
#endif /* OSTREE_DISABLE_GPGME */
static gboolean
ostree_verify_unwritten_commit (OtPullData *pull_data,
const char *checksum,
GVariant *commit,
GVariant *detached_metadata,
const OstreeCollectionRef *ref,
GCancellable *cancellable,
GError **error)
{
#ifndef OSTREE_DISABLE_GPGME
if (pull_data->gpg_verify)
{
const char *keyring_remote = NULL;
/* Shouldn't happen, but see comment in process_verify_result() */
if (g_hash_table_contains (pull_data->verified_commits, checksum))
return TRUE;
if (ref != NULL)
keyring_remote = g_hash_table_lookup (pull_data->ref_keyring_map, ref);
if (keyring_remote == NULL)
keyring_remote = pull_data->remote_name;
g_autoptr(GBytes) signed_data = g_variant_get_data_as_bytes (commit);
g_autoptr(OstreeGpgVerifyResult) result =
_ostree_repo_gpg_verify_with_metadata (pull_data->repo, signed_data,
detached_metadata,
keyring_remote,
NULL, NULL, cancellable, error);
if (!process_verify_result (pull_data, checksum, result, error))
return FALSE;
}
#endif /* OSTREE_DISABLE_GPGME */
return TRUE;
}
static gboolean
commitstate_is_partial (OtPullData *pull_data,
OstreeRepoCommitState commitstate)
@ -1513,109 +1327,6 @@ commitstate_is_partial (OtPullData *pull_data,
#endif /* HAVE_LIBCURL_OR_LIBSOUP */
/**
* _ostree_repo_verify_bindings:
* @collection_id: (nullable): Locally specified collection ID for the remote
* the @commit was retrieved from, or %NULL if none is configured
* @ref_name: (nullable): Ref name the commit was retrieved using, or %NULL if
* the commit was retrieved by checksum
* @commit: Commit data to check
* @error: Return location for a #GError, or %NULL
*
* Verify the ref and collection bindings.
*
* The ref binding is verified only if it exists. But if we have the
* collection ID specified in the remote configuration (@collection_id is
* non-%NULL) then the ref binding must exist, otherwise the verification will
* fail. Parts of the verification can be skipped by passing %NULL to the
* @ref_name parameter (in case we requested a checksum directly, without
* looking it up from a ref).
*
* The collection binding is verified only when we have collection ID
* specified in the remote configuration. If it is specified, then the
* binding must exist and must be equal to the remote repository
* collection ID.
*
* Returns: %TRUE if bindings are correct, %FALSE otherwise
* Since: 2017.14
*/
gboolean
_ostree_repo_verify_bindings (const char *collection_id,
const char *ref_name,
GVariant *commit,
GError **error)
{
g_autoptr(GVariant) metadata = g_variant_get_child_value (commit, 0);
g_autofree const char **refs = NULL;
if (!g_variant_lookup (metadata,
OSTREE_COMMIT_META_KEY_REF_BINDING,
"^a&s",
&refs))
{
/* Early return here - if the remote collection ID is NULL, then
* we certainly will not verify the collection binding in the
* commit.
*/
if (collection_id == NULL)
return TRUE;
return glnx_throw (error,
"Expected commit metadata to have ref "
"binding information, found none");
}
if (ref_name != NULL)
{
if (!g_strv_contains ((const char *const *) refs, ref_name))
{
g_autoptr(GString) refs_dump = g_string_new (NULL);
const char *refs_str;
if (refs != NULL && (*refs) != NULL)
{
for (const char **iter = refs; *iter != NULL; ++iter)
{
const char *ref = *iter;
if (refs_dump->len > 0)
g_string_append (refs_dump, ", ");
g_string_append_printf (refs_dump, "%s", ref);
}
refs_str = refs_dump->str;
}
else
{
refs_str = "no refs";
}
return glnx_throw (error, "Commit has no requested ref %s "
"in ref binding metadata (%s)",
ref_name, refs_str);
}
}
if (collection_id != NULL)
{
const char *collection_id_binding;
if (!g_variant_lookup (metadata,
OSTREE_COMMIT_META_KEY_COLLECTION_BINDING,
"&s",
&collection_id_binding))
return glnx_throw (error,
"Expected commit metadata to have collection ID "
"binding information, found none");
if (!g_str_equal (collection_id_binding, collection_id))
return glnx_throw (error,
"Commit has collection ID %s in collection binding "
"metadata, while the remote it came from has "
"collection ID %s",
collection_id_binding, collection_id);
}
return TRUE;
}
/* Reads the collection-id of a given remote from the repo
* configuration.
*/
@ -1824,11 +1535,51 @@ scan_commit_object (OtPullData *pull_data,
keyring_remote,
cancellable,
error);
if (!process_verify_result (pull_data, checksum, result, error))
if (!_process_gpg_verify_result (pull_data, checksum, result, error))
return FALSE;
}
#endif /* OSTREE_DISABLE_GPGME */
if (pull_data->signapi_commit_verifiers &&
!g_hash_table_contains (pull_data->signapi_verified_commits, checksum))
{
g_autoptr(GError) last_verification_error = NULL;
gboolean found_any_signature = FALSE;
gboolean found_valid_signature = FALSE;
g_autofree char *success_message = NULL;
for (guint i = 0; i < pull_data->signapi_commit_verifiers->len; i++)
{
OstreeSign *sign = pull_data->signapi_commit_verifiers->pdata[i];
found_any_signature = TRUE;
/* Set return to true if any sign fit */
if (ostree_sign_commit_verify (sign,
pull_data->repo,
checksum,
&success_message,
cancellable,
last_verification_error ? NULL : &last_verification_error))
{
found_valid_signature = TRUE;
break;
}
}
if (!found_any_signature)
return glnx_throw (error, "No signatures found for commit %s", checksum);
if (!found_valid_signature)
{
g_assert (last_verification_error);
g_propagate_error (error, g_steal_pointer (&last_verification_error));
return glnx_prefix_error (error, "Can't verify commit %s", checksum);
}
g_assert (success_message);
g_hash_table_insert (pull_data->signapi_verified_commits, g_strdup (checksum), g_steal_pointer (&success_message));
}
/* If we found a legacy transaction flag, assume we have to scan.
* We always do a scan of dirtree objects; see
* https://github.com/ostreedev/ostree/issues/543
@ -1848,6 +1599,7 @@ scan_commit_object (OtPullData *pull_data,
commit, error))
return glnx_prefix_error (error, "Commit %s", checksum);
guint64 new_ts = ostree_commit_get_timestamp (commit);
if (pull_data->timestamp_check)
{
/* We don't support timestamp checking while recursing right now */
@ -1866,11 +1618,22 @@ scan_commit_object (OtPullData *pull_data,
return glnx_prefix_error (error, "Reading %s for timestamp-check", ref->ref_name);
guint64 orig_ts = ostree_commit_get_timestamp (orig_commit);
guint64 new_ts = ostree_commit_get_timestamp (commit);
if (!_ostree_compare_timestamps (orig_rev, orig_ts, checksum, new_ts, error))
return FALSE;
}
}
if (pull_data->timestamp_check_from_rev)
{
g_autoptr(GVariant) commit = NULL;
if (!ostree_repo_load_commit (pull_data->repo, pull_data->timestamp_check_from_rev,
&commit, NULL, error))
return glnx_prefix_error (error, "Reading %s for timestamp-check-from-rev",
pull_data->timestamp_check_from_rev);
guint64 ts = ostree_commit_get_timestamp (commit);
if (!_ostree_compare_timestamps (pull_data->timestamp_check_from_rev, ts, checksum, new_ts, error))
return FALSE;
}
/* If we found a legacy transaction flag, assume all commits are partial */
gboolean is_partial = commitstate_is_partial (pull_data, commitstate);
@ -2413,8 +2176,8 @@ process_one_static_delta (OtPullData *pull_data,
g_autofree char *detached_path = _ostree_get_relative_static_delta_path (from_revision, to_revision, "commitmeta");
g_autoptr(GVariant) detached_data = g_variant_lookup_value (metadata, detached_path, G_VARIANT_TYPE("a{sv}"));
if (!ostree_verify_unwritten_commit (pull_data, to_revision, to_commit, detached_data,
ref, cancellable, error))
if (!_verify_unwritten_commit (pull_data, to_revision, to_commit, detached_data,
ref, cancellable, error))
return FALSE;
if (detached_data && !ostree_repo_write_commit_detached_metadata (pull_data->repo,
@ -3520,11 +3283,15 @@ initiate_request (OtPullData *pull_data,
* * override-remote-name (s): If local, add this remote to refspec
* * gpg-verify (b): GPG verify commits
* * gpg-verify-summary (b): GPG verify summary
* * disable-sign-verify (b): Disable signapi verification of commits
* * disable-sign-verify-summary (b): Disable signapi verification of the summary
* * depth (i): How far in the history to traverse; default is 0, -1 means infinite
* * per-object-fsync (b): Perform disk writes more slowly, avoiding a single large I/O sync
* * disable-static-deltas (b): Do not use static deltas
* * require-static-deltas (b): Require static deltas
* * override-commit-ids (as): Array of specific commit IDs to fetch for refs
* * timestamp-check (b): Verify commit timestamps are newer than current (when pulling via ref); Since: 2017.11
* * timestamp-check-from-rev (s): Verify that all fetched commit timestamps are newer than timestamp of given rev; Since: 2020.4
* * metadata-size-restriction (t): Restrict metadata objects to a maximum number of bytes; 0 to disable. Since: 2018.9
* * dry-run (b): Only print information on what will be downloaded (requires static deltas)
* * override-url (s): Fetch objects from this URL if remote specifies no metalink in options
@ -3574,11 +3341,14 @@ ostree_repo_pull_with_options (OstreeRepo *self,
g_autoptr(GVariantIter) collection_refs_iter = NULL;
g_autofree char **override_commit_ids = NULL;
g_autoptr(GSource) update_timeout = NULL;
gboolean opt_per_object_fsync = FALSE;
gboolean opt_gpg_verify_set = FALSE;
gboolean opt_gpg_verify_summary_set = FALSE;
gboolean opt_collection_refs_set = FALSE;
gboolean opt_n_network_retries_set = FALSE;
gboolean opt_ref_keyring_map_set = FALSE;
gboolean disable_sign_verify = FALSE;
gboolean disable_sign_verify_summary = FALSE;
const char *main_collection_id = NULL;
const char *url_override = NULL;
gboolean inherit_transaction = FALSE;
@ -3590,6 +3360,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
* value, otherwise NULL. Used for logging.
*/
const char *the_ref_to_fetch = NULL;
OstreeRepoTransactionStats tstats = { 0, };
/* Default */
pull_data->max_metadata_size = OSTREE_MAX_METADATA_SIZE;
@ -3610,17 +3381,21 @@ ostree_repo_pull_with_options (OstreeRepo *self,
g_variant_lookup (options, "gpg-verify", "b", &pull_data->gpg_verify);
opt_gpg_verify_summary_set =
g_variant_lookup (options, "gpg-verify-summary", "b", &pull_data->gpg_verify_summary);
g_variant_lookup (options, "disable-sign-verify", "b", &disable_sign_verify);
g_variant_lookup (options, "disable-sign-verify-summary", "b", &disable_sign_verify_summary);
(void) g_variant_lookup (options, "depth", "i", &pull_data->maxdepth);
(void) g_variant_lookup (options, "disable-static-deltas", "b", &pull_data->disable_static_deltas);
(void) g_variant_lookup (options, "require-static-deltas", "b", &pull_data->require_static_deltas);
(void) g_variant_lookup (options, "override-commit-ids", "^a&s", &override_commit_ids);
(void) g_variant_lookup (options, "dry-run", "b", &pull_data->dry_run);
(void) g_variant_lookup (options, "per-object-fsync", "b", &opt_per_object_fsync);
(void) g_variant_lookup (options, "override-url", "&s", &url_override);
(void) g_variant_lookup (options, "inherit-transaction", "b", &inherit_transaction);
(void) g_variant_lookup (options, "http-headers", "@a(ss)", &pull_data->extra_headers);
(void) g_variant_lookup (options, "update-frequency", "u", &update_frequency);
(void) g_variant_lookup (options, "localcache-repos", "^a&s", &opt_localcache_repos);
(void) g_variant_lookup (options, "timestamp-check", "b", &pull_data->timestamp_check);
(void) g_variant_lookup (options, "timestamp-check-from-rev", "s", &pull_data->timestamp_check_from_rev);
(void) g_variant_lookup (options, "max-metadata-size", "t", &pull_data->max_metadata_size);
(void) g_variant_lookup (options, "append-user-agent", "s", &pull_data->append_user_agent);
opt_n_network_retries_set =
@ -3634,10 +3409,10 @@ ostree_repo_pull_with_options (OstreeRepo *self,
#ifdef OSTREE_DISABLE_GPGME
/* Explicitly fail here if gpg verification is requested and we have no GPG support */
if (opt_gpg_verify_set || opt_gpg_verify_summary_set)
if (pull_data->gpg_verify || pull_data->gpg_verify_summary)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"'%s': GPG feature is disabled in a build time",
"'%s': GPG feature is disabled at build time",
__FUNCTION__);
goto out;
}
@ -3682,6 +3457,10 @@ ostree_repo_pull_with_options (OstreeRepo *self,
pull_data->main_context = g_main_context_ref_thread_default ();
pull_data->flags = flags;
/* TODO: Avoid mutating the repo object */
if (opt_per_object_fsync)
self->per_object_fsync = TRUE;
if (!opt_n_network_retries_set)
pull_data->n_network_retries = DEFAULT_N_NETWORK_RETRIES;
@ -3702,6 +3481,8 @@ ostree_repo_pull_with_options (OstreeRepo *self,
(GDestroyNotify)g_free);
pull_data->verified_commits = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free, NULL);
pull_data->signapi_verified_commits = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free, NULL);
pull_data->ref_keyring_map = g_hash_table_new_full (ostree_collection_ref_hash, ostree_collection_ref_equal,
(GDestroyNotify)ostree_collection_ref_free, (GDestroyNotify)g_free);
pull_data->scanned_metadata = g_hash_table_new_full (ostree_hash_object_name, g_variant_equal,
@ -3759,7 +3540,9 @@ ostree_repo_pull_with_options (OstreeRepo *self,
/* For compatibility with pull-local, don't gpg verify local
* pulls by default.
*/
if ((pull_data->gpg_verify || pull_data->gpg_verify_summary) &&
if ((pull_data->gpg_verify ||
pull_data->gpg_verify_summary
) &&
pull_data->remote_name == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@ -3774,7 +3557,6 @@ ostree_repo_pull_with_options (OstreeRepo *self,
g_free (pull_data->remote_name);
pull_data->remote_name = g_strdup (remote_name_or_baseurl);
#ifndef OSTREE_DISABLE_GPGME
/* Fetch GPG verification settings from remote if it wasn't already
* explicitly set in the options. */
if (!opt_gpg_verify_set)
@ -3786,7 +3568,6 @@ ostree_repo_pull_with_options (OstreeRepo *self,
if (!ostree_repo_remote_get_gpg_verify_summary (self, pull_data->remote_name,
&pull_data->gpg_verify_summary, error))
goto out;
#endif /* OSTREE_DISABLE_GPGME */
/* NOTE: If changing this, see the matching implementation in
* ostree-sysroot-upgrader.c
@ -3805,6 +3586,15 @@ ostree_repo_pull_with_options (OstreeRepo *self,
}
}
if (pull_data->remote_name && !(disable_sign_verify && disable_sign_verify_summary))
{
if (!_signapi_init_for_remote (pull_data->repo, pull_data->remote_name,
&pull_data->signapi_commit_verifiers,
&pull_data->signapi_summary_verifiers,
error))
return FALSE;
}
pull_data->phase = OSTREE_PULL_PHASE_FETCHING_REFS;
if (!reinitialize_fetcher (pull_data, remote_name_or_baseurl, error))
@ -4168,6 +3958,65 @@ ostree_repo_pull_with_options (OstreeRepo *self,
}
#endif /* OSTREE_DISABLE_GPGME */
if (pull_data->signapi_summary_verifiers)
{
if (!bytes_sig && pull_data->signapi_summary_verifiers)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Signatures verification enabled, but no summary.sig found (use sign-verify-summary=false in remote config to disable)");
goto out;
}
if (bytes_summary && bytes_sig)
{
g_autoptr(GVariant) signatures = NULL;
g_autoptr(GError) temp_error = NULL;
signatures = g_variant_new_from_bytes (OSTREE_SUMMARY_SIG_GVARIANT_FORMAT,
bytes_sig, FALSE);
g_assert (pull_data->signapi_summary_verifiers);
if (!_sign_verify_for_remote (pull_data->signapi_summary_verifiers, bytes_summary, signatures, NULL, &temp_error))
{
if (summary_from_cache)
{
/* The cached summary doesn't match, fetch a new one and verify again */
if ((self->test_error_flags & OSTREE_REPO_TEST_ERROR_INVALID_CACHE) > 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Remote %s cached summary invalid and "
"OSTREE_REPO_TEST_ERROR_INVALID_CACHE specified",
pull_data->remote_name);
goto out;
}
else
g_debug ("Remote %s cached summary invalid, pulling new version",
pull_data->remote_name);
summary_from_cache = FALSE;
g_clear_pointer (&bytes_summary, (GDestroyNotify)g_bytes_unref);
if (!_ostree_fetcher_mirrored_request_to_membuf (pull_data->fetcher,
pull_data->meta_mirrorlist,
"summary",
OSTREE_FETCHER_REQUEST_OPTIONAL_CONTENT,
pull_data->n_network_retries,
&bytes_summary,
OSTREE_MAX_METADATA_SIZE,
cancellable, error))
goto out;
if (!_sign_verify_for_remote (pull_data->signapi_summary_verifiers, bytes_summary, signatures, NULL, error))
goto out;
}
else
{
g_propagate_error (error, g_steal_pointer (&temp_error));
goto out;
}
}
}
}
if (bytes_summary)
{
pull_data->summary_data = g_bytes_ref (bytes_summary);
@ -4427,6 +4276,18 @@ ostree_repo_pull_with_options (OstreeRepo *self,
g_steal_pointer (&checksum));
}
/* Resolve refs to a checksum if necessary */
if (pull_data->timestamp_check_from_rev &&
!ostree_validate_checksum_string (pull_data->timestamp_check_from_rev, NULL))
{
g_autofree char *from_rev = NULL;
if (!ostree_repo_resolve_rev (pull_data->repo, pull_data->timestamp_check_from_rev, FALSE,
&from_rev, error))
goto out;
g_free (pull_data->timestamp_check_from_rev);
pull_data->timestamp_check_from_rev = g_steal_pointer (&from_rev);
}
g_hash_table_unref (requested_refs_to_fetch);
requested_refs_to_fetch = g_steal_pointer (&updated_requested_refs_to_fetch);
if (g_hash_table_size (requested_refs_to_fetch) == 1)
@ -4567,7 +4428,8 @@ ostree_repo_pull_with_options (OstreeRepo *self,
}
}
if (pull_data->is_mirror && pull_data->summary_data && !refs_to_fetch && !configured_branches)
if (pull_data->is_mirror && pull_data->summary_data &&
!refs_to_fetch && !opt_collection_refs_set && !configured_branches)
{
GLnxFileReplaceFlags replaceflag =
pull_data->repo->disable_fsync ? GLNX_FILE_REPLACE_NODATASYNC : 0;
@ -4590,7 +4452,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
}
if (!inherit_transaction &&
!ostree_repo_commit_transaction (pull_data->repo, NULL, cancellable, error))
!ostree_repo_commit_transaction (pull_data->repo, &tstats, cancellable, error))
goto out;
end_time = g_get_monotonic_time ();
@ -4632,6 +4494,11 @@ ostree_repo_pull_with_options (OstreeRepo *self,
shift == 1 ? "B" : "KiB",
(guint) ((end_time - pull_data->start_time) / G_USEC_PER_SEC));
}
if (!inherit_transaction)
{
g_autofree char *bytes_written = g_format_size (tstats.content_bytes_written);
g_string_append_printf (buf, "; %s content written", bytes_written);
}
ostree_async_progress_set_status (pull_data->progress, buf->str);
}
@ -4647,22 +4514,26 @@ ostree_repo_pull_with_options (OstreeRepo *self,
g_string_append_printf (msg, "libostree pull from '%s' for %u refs complete",
pull_data->remote_name, g_hash_table_size (requested_refs_to_fetch));
const char *verify_state;
const char *gpg_verify_state;
#ifndef OSTREE_DISABLE_GPGME
if (pull_data->gpg_verify_summary)
{
if (pull_data->gpg_verify)
verify_state = "summary+commit";
gpg_verify_state = "summary+commit";
else
verify_state = "summary-only";
gpg_verify_state = "summary-only";
}
else
verify_state = (pull_data->gpg_verify ? "commit" : "disabled");
g_string_append_printf (msg, "\nsecurity: GPG: %s ", verify_state);
gpg_verify_state = (pull_data->gpg_verify ? "commit" : "disabled");
#else
verify_state = "disabled";
g_string_append_printf (msg, "\nsecurity: %s ", verify_state);
gpg_verify_state = "disabled";
#endif /* OSTREE_DISABLE_GPGME */
g_string_append_printf (msg, "\nsecurity: GPG: %s ", gpg_verify_state);
const char *sign_verify_state;
sign_verify_state = (pull_data->signapi_commit_verifiers ? "commit" : "disabled");
g_string_append_printf (msg, "\nsecurity: SIGN: %s ", sign_verify_state);
OstreeFetcherURI *first_uri = pull_data->meta_mirrorlist->pdata[0];
g_autofree char *first_scheme = _ostree_fetcher_uri_get_scheme (first_uri);
@ -4694,11 +4565,16 @@ ostree_repo_pull_with_options (OstreeRepo *self,
const guint n_seconds = (guint) ((end_time - pull_data->start_time) / G_USEC_PER_SEC);
g_autofree char *formatted_xferred = g_format_size (bytes_transferred);
g_string_append_printf (msg, "\ntransfer: secs: %u size: %s", n_seconds, formatted_xferred);
if (pull_data->signapi_commit_verifiers)
{
g_assert_cmpuint (g_hash_table_size (pull_data->signapi_verified_commits), >, 0);
}
ot_journal_send ("MESSAGE=%s", msg->str,
"MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_MESSAGE_FETCH_COMPLETE_ID),
"OSTREE_REMOTE=%s", pull_data->remote_name,
"OSTREE_GPG=%s", verify_state,
"OSTREE_SIGN=%s", sign_verify_state,
"OSTREE_GPG=%s", gpg_verify_state,
"OSTREE_SECONDS=%u", n_seconds,
"OSTREE_XFER_SIZE=%s", formatted_xferred,
NULL);
@ -4719,6 +4595,13 @@ ostree_repo_pull_with_options (OstreeRepo *self,
if (!ostree_repo_mark_commit_partial (pull_data->repo, commit, FALSE, error))
goto out;
}
/* and finally any parent commits we might also have pulled because of depth>0 */
GLNX_HASH_TABLE_FOREACH (pull_data->commit_to_depth, const char*, commit)
{
if (!ostree_repo_mark_commit_partial (pull_data->repo, commit, FALSE, error))
goto out;
}
}
ret = TRUE;
@ -4746,6 +4629,8 @@ ostree_repo_pull_with_options (OstreeRepo *self,
g_free (pull_data->remote_refspec_name);
g_free (pull_data->remote_name);
g_free (pull_data->append_user_agent);
g_clear_pointer (&pull_data->signapi_commit_verifiers, (GDestroyNotify) g_ptr_array_unref);
g_clear_pointer (&pull_data->signapi_summary_verifiers, (GDestroyNotify) g_ptr_array_unref);
g_clear_pointer (&pull_data->meta_mirrorlist, (GDestroyNotify) g_ptr_array_unref);
g_clear_pointer (&pull_data->content_mirrorlist, (GDestroyNotify) g_ptr_array_unref);
g_clear_pointer (&pull_data->summary_data, (GDestroyNotify) g_bytes_unref);
@ -4758,7 +4643,9 @@ ostree_repo_pull_with_options (OstreeRepo *self,
g_clear_pointer (&pull_data->fetched_detached_metadata, (GDestroyNotify) g_hash_table_unref);
g_clear_pointer (&pull_data->summary_deltas_checksums, (GDestroyNotify) g_hash_table_unref);
g_clear_pointer (&pull_data->ref_original_commits, (GDestroyNotify) g_hash_table_unref);
g_free (pull_data->timestamp_check_from_rev);
g_clear_pointer (&pull_data->verified_commits, (GDestroyNotify) g_hash_table_unref);
g_clear_pointer (&pull_data->signapi_verified_commits, (GDestroyNotify) g_hash_table_unref);
g_clear_pointer (&pull_data->ref_keyring_map, (GDestroyNotify) g_hash_table_unref);
g_clear_pointer (&pull_data->requested_content, (GDestroyNotify) g_hash_table_unref);
g_clear_pointer (&pull_data->requested_fallback_content, (GDestroyNotify) g_hash_table_unref);
@ -6016,6 +5903,8 @@ ostree_repo_pull_from_remotes_async (OstreeRepo *self,
g_variant_dict_insert (&local_options_dict, "gpg-verify", "b", FALSE);
#endif /* OSTREE_DISABLE_GPGME */
g_variant_dict_insert (&local_options_dict, "gpg-verify-summary", "b", FALSE);
g_variant_dict_insert (&local_options_dict, "sign-verify", "b", FALSE);
g_variant_dict_insert (&local_options_dict, "sign-verify-summary", "b", FALSE);
g_variant_dict_insert (&local_options_dict, "inherit-transaction", "b", TRUE);
if (result->remote->refspec_name != NULL)
g_variant_dict_insert (&local_options_dict, "override-remote-name", "s", result->remote->refspec_name);
@ -6162,9 +6051,8 @@ ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self,
g_autofree char *metalink_url_string = NULL;
g_autoptr(GBytes) summary = NULL;
g_autoptr(GBytes) signatures = NULL;
#ifndef OSTREE_DISABLE_GPGME
gboolean gpg_verify_summary;
#endif
g_autoptr(GPtrArray) signapi_summary_verifiers = NULL;
gboolean ret = FALSE;
gboolean summary_is_from_cache;
@ -6186,37 +6074,73 @@ ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self,
error))
goto out;
#ifndef OSTREE_DISABLE_GPGME
if (!ostree_repo_remote_get_gpg_verify_summary (self, name, &gpg_verify_summary, error))
goto out;
if (gpg_verify_summary && summary == NULL)
if (gpg_verify_summary)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"GPG verification enabled, but no summary found (check that the configured URL in remote config is correct)");
goto out;
if (summary == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"GPG verification enabled, but no summary found (check that the configured URL in remote config is correct)");
goto out;
}
if (signatures == NULL)
{
g_set_error (error, OSTREE_GPG_ERROR, OSTREE_GPG_ERROR_NO_SIGNATURE,
"GPG verification enabled, but no summary signatures found (use gpg-verify-summary=false in remote config to disable)");
goto out;
}
/* Verify any summary signatures. */
if (summary != NULL && signatures != NULL)
{
g_autoptr(OstreeGpgVerifyResult) result = NULL;
result = ostree_repo_verify_summary (self,
name,
summary,
signatures,
cancellable,
error);
if (!ostree_gpg_verify_result_require_valid_signature (result, error))
goto out;
}
}
if (gpg_verify_summary && signatures == NULL)
{
g_set_error (error, OSTREE_GPG_ERROR, OSTREE_GPG_ERROR_NO_SIGNATURE,
"GPG verification enabled, but no summary signatures found (use gpg-verify-summary=false in remote config to disable)");
goto out;
}
if (!_signapi_init_for_remote (self, name, NULL,
&signapi_summary_verifiers,
error))
goto out;
/* Verify any summary signatures. */
if (gpg_verify_summary && summary != NULL && signatures != NULL)
if (signapi_summary_verifiers)
{
g_autoptr(OstreeGpgVerifyResult) result = NULL;
if (summary == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"Signature verification enabled, but no summary found (check that the configured URL in remote config is correct)");
goto out;
}
result = ostree_repo_verify_summary (self,
name,
summary,
signatures,
cancellable,
error);
if (!ostree_gpg_verify_result_require_valid_signature (result, error))
goto out;
if (signatures == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"Signature verification enabled, but no summary signatures found (use sign-verify-summary=false in remote config to disable)");
goto out;
}
/* Verify any summary signatures. */
if (summary != NULL && signatures != NULL)
{
g_autoptr(GVariant) sig_variant = NULL;
sig_variant = g_variant_new_from_bytes (OSTREE_SUMMARY_SIG_GVARIANT_FORMAT,
signatures, FALSE);
if (!_sign_verify_for_remote (signapi_summary_verifiers, summary, sig_variant, NULL, error))
goto out;
}
}
if (!summary_is_from_cache && summary && signatures)
@ -6240,10 +6164,6 @@ ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self,
}
}
#else
g_message ("%s: GPG feature is disabled in a build time", __FUNCTION__);
#endif /* OSTREE_DISABLE_GPGME */
if (out_summary != NULL)
*out_summary = g_steal_pointer (&summary);

View File

@ -1346,7 +1346,6 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
OstreeStaticDeltaBuilder builder = { 0, };
guint i;
guint min_fallback_size;
@ -1365,8 +1364,8 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
g_autoptr(GVariant) detached = NULL;
gboolean inline_parts;
guint endianness = G_BYTE_ORDER;
builder.parts = g_ptr_array_new_with_free_func ((GDestroyNotify)ostree_static_delta_part_builder_unref);
builder.fallback_objects = g_ptr_array_new_with_free_func ((GDestroyNotify)g_variant_unref);
g_autoptr(GPtrArray) builder_parts = g_ptr_array_new_with_free_func ((GDestroyNotify)ostree_static_delta_part_builder_unref);
g_autoptr(GPtrArray) builder_fallback_objects = g_ptr_array_new_with_free_func ((GDestroyNotify)g_variant_unref);
g_auto(GLnxTmpfile) descriptor_tmpf = { 0, };
g_autoptr(OtVariantBuilder) descriptor_builder = NULL;
@ -1385,6 +1384,8 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
g_return_val_if_fail (endianness == G_BIG_ENDIAN || endianness == G_LITTLE_ENDIAN, FALSE);
builder.swap_endian = endianness != G_BYTE_ORDER;
builder.parts = builder_parts;
builder.fallback_objects = builder_fallback_objects;
{ gboolean use_bsdiff;
if (!g_variant_lookup (params, "bsdiff-enabled", "b", &use_bsdiff))
@ -1408,7 +1409,7 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
if (!ostree_repo_load_variant (self, OSTREE_OBJECT_TYPE_COMMIT, to,
&to_commit, error))
goto out;
return FALSE;
builder.delta_opts = delta_opts;
@ -1419,7 +1420,7 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
descriptor_name = g_strdup (glnx_basename (opt_filename));
if (!glnx_opendirat (AT_FDCWD, dn, TRUE, &descriptor_dfd, error))
goto out;
return FALSE;
}
else
{
@ -1428,9 +1429,9 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
const char *dn = dirname (dnbuf);
if (!glnx_shutil_mkdir_p_at (self->repo_dir_fd, dn, DEFAULT_DIRECTORY_MODE, cancellable, error))
goto out;
return FALSE;
if (!glnx_opendirat (self->repo_dir_fd, dn, TRUE, &descriptor_dfd, error))
goto out;
return FALSE;
descriptor_name = g_strdup (basename (descriptor_relpath));
}
@ -1439,17 +1440,17 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
/* Ignore optimization flags */
if (!generate_delta_lowlatency (self, from, to, delta_opts, &builder,
cancellable, error))
goto out;
return FALSE;
if (!glnx_open_tmpfile_linkable_at (descriptor_dfd, ".", O_WRONLY | O_CLOEXEC,
&descriptor_tmpf, error))
goto out;
return FALSE;
descriptor_builder = ot_variant_builder_new (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT), descriptor_tmpf.fd);
/* Open the metadata dict */
if (!ot_variant_builder_open (descriptor_builder, G_VARIANT_TYPE ("a{sv}"), error))
goto out;
return FALSE;
/* NOTE: Add user-supplied metadata first. This is used by at least
* flatpak as a way to provide MIME content sniffing, since the
@ -1464,7 +1465,7 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
while ((item = g_variant_iter_next_value (&iter)))
{
if (!ot_variant_builder_add_value (descriptor_builder, item, error))
goto out;
return FALSE;
g_variant_unref (item);
}
}
@ -1483,7 +1484,7 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
g_assert_not_reached ();
}
if (!ot_variant_builder_add (descriptor_builder, error, "{sv}", "ostree.endianness", g_variant_new_byte (endianness_char)))
goto out;
return FALSE;
}
part_headers = g_variant_builder_new (G_VARIANT_TYPE ("a" OSTREE_STATIC_DELTA_META_ENTRY_FORMAT));
@ -1504,21 +1505,18 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
!ot_variant_builder_add_from_fd (descriptor_builder, G_VARIANT_TYPE ("(yay)"), part_builder->part_tmpf.fd, part_builder->compressed_size, error) ||
!ot_variant_builder_close (descriptor_builder, error) ||
!ot_variant_builder_close (descriptor_builder, error))
goto out;
return FALSE;
}
else
{
g_autofree char *partstr = g_strdup_printf ("%u", i);
if (fchmod (part_builder->part_tmpf.fd, 0644) < 0)
{
glnx_set_error_from_errno (error);
goto out;
}
return glnx_throw_errno_prefix (error, "fchmod");
if (!glnx_link_tmpfile_at (&part_builder->part_tmpf, GLNX_LINK_TMPFILE_REPLACE,
descriptor_dfd, partstr, error))
goto out;
return FALSE;
}
g_variant_builder_add_value (part_headers, part_builder->header);
@ -1529,21 +1527,21 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
if (!get_fallback_headers (self, &builder, &fallback_headers,
cancellable, error))
goto out;
return FALSE;
if (!ostree_repo_read_commit_detached_metadata (self, to, &detached, cancellable, error))
goto out;
return FALSE;
if (detached)
{
g_autofree char *detached_key = _ostree_get_relative_static_delta_path (from, to, "commitmeta");
if (!ot_variant_builder_add (descriptor_builder, error, "{sv}", detached_key, detached))
goto out;
return FALSE;
}
/* Close metadata dict */
if (!ot_variant_builder_close (descriptor_builder, error))
goto out;
return FALSE;
/* Generate OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT */
{
@ -1568,10 +1566,10 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
g_variant_builder_end (part_headers), error) ||
!ot_variant_builder_add_value (descriptor_builder,
fallback_headers, error))
goto out;
return FALSE;
if (!ot_variant_builder_end (descriptor_builder, error))
goto out;
return FALSE;
g_date_time_unref (now);
}
@ -1589,18 +1587,11 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
}
if (fchmod (descriptor_tmpf.fd, 0644) < 0)
{
glnx_set_error_from_errno (error);
goto out;
}
return glnx_throw_errno_prefix (error, "fchmod");
if (!glnx_link_tmpfile_at (&descriptor_tmpf, GLNX_LINK_TMPFILE_REPLACE,
descriptor_dfd, descriptor_name, error))
goto out;
return FALSE;
ret = TRUE;
out:
g_clear_pointer (&builder.parts, g_ptr_array_unref);
g_clear_pointer (&builder.fallback_objects, g_ptr_array_unref);
return ret;
return TRUE;
}

View File

@ -2028,17 +2028,8 @@ ostree_repo_remote_get_gpg_verify (OstreeRepo *self,
return TRUE;
}
#ifndef OSTREE_DISABLE_GPGME
return ostree_repo_get_remote_boolean_option (self, name, "gpg-verify",
TRUE, out_gpg_verify, error);
#else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"'%s': GPG feature is disabled in a build time",
__FUNCTION__);
if (out_gpg_verify != NULL)
*out_gpg_verify = FALSE;
return FALSE;
#endif /* OSTREE_DISABLE_GPGME */
}
/**
@ -2060,17 +2051,8 @@ ostree_repo_remote_get_gpg_verify_summary (OstreeRepo *self,
gboolean *out_gpg_verify_summary,
GError **error)
{
#ifndef OSTREE_DISABLE_GPGME
return ostree_repo_get_remote_boolean_option (self, name, "gpg-verify-summary",
FALSE, out_gpg_verify_summary, error);
#else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"'%s': GPG feature is disabled in a build time",
__FUNCTION__);
if (out_gpg_verify_summary != NULL)
*out_gpg_verify_summary = FALSE;
return FALSE;
#endif /* OSTREE_DISABLE_GPGME */
}
/**
@ -2344,10 +2326,7 @@ out:
return ret;
#else /* OSTREE_DISABLE_GPGME */
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"'%s': GPG feature is disabled in a build time",
__FUNCTION__);
return FALSE;
return glnx_throw (error, "GPG feature is disabled in a build time");
#endif /* OSTREE_DISABLE_GPGME */
}
@ -2943,6 +2922,10 @@ reload_core_config (OstreeRepo *self,
ostree_repo_set_disable_fsync (self, TRUE);
}
if (!ot_keyfile_get_boolean_with_default (self->config, "core", "per-object-fsync",
FALSE, &self->per_object_fsync, error))
return FALSE;
/* See https://github.com/ostreedev/ostree/issues/758 */
if (!ot_keyfile_get_boolean_with_default (self->config, "core", "disable-xattrs",
FALSE, &self->disable_xattrs, error))
@ -3257,6 +3240,8 @@ ostree_repo_open (OstreeRepo *self,
GCancellable *cancellable,
GError **error)
{
GLNX_AUTO_PREFIX_ERROR ("opening repo", error);
struct stat stbuf;
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
@ -3291,10 +3276,7 @@ ostree_repo_open (OstreeRepo *self,
g_assert (self->repodir);
if (!glnx_opendirat (AT_FDCWD, gs_file_get_path_cached (self->repodir), TRUE,
&self->repo_dir_fd, error))
{
g_prefix_error (error, "%s: ", gs_file_get_path_cached (self->repodir));
return FALSE;
}
return FALSE;
}
if (!glnx_fstat (self->repo_dir_fd, &stbuf, error))
@ -4992,10 +4974,7 @@ ostree_repo_append_gpg_signature (OstreeRepo *self,
return TRUE;
#else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"'%s': GPG feature is disabled in a build time",
__FUNCTION__);
return FALSE;
return glnx_throw (error, "GPG feature is disabled in a build time");
#endif /* OSTREE_DISABLE_GPGME */
}
@ -5147,7 +5126,7 @@ ostree_repo_sign_commit (OstreeRepo *self,
return TRUE;
#else
/* FIXME: Return false until refactoring */
return FALSE;
return glnx_throw (error, "GPG feature is disabled in a build time");
#endif /* OSTREE_DISABLE_GPGME */
}
@ -5239,10 +5218,7 @@ ostree_repo_add_gpg_signature_summary (OstreeRepo *self,
return TRUE;
#else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"'%s': GPG feature is disabled in a build time",
__FUNCTION__);
return FALSE;
return glnx_throw (error, "GPG feature is disabled in a build time");
#endif /* OSTREE_DISABLE_GPGME */
}
@ -5516,10 +5492,7 @@ ostree_repo_verify_commit (OstreeRepo *self,
return TRUE;
#else
/* FIXME: Return false until refactoring */
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"'%s': GPG feature is disabled in a build time",
__FUNCTION__);
return FALSE;
return glnx_throw (error, "GPG feature is disabled in a build time");
#endif /* OSTREE_DISABLE_GPGME */
}
@ -5554,9 +5527,7 @@ ostree_repo_verify_commit_ext (OstreeRepo *self,
cancellable,
error);
#else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"'%s': GPG feature is disabled in a build time",
__FUNCTION__);
glnx_throw (error, "GPG feature is disabled in a build time");
return NULL;
#endif /* OSTREE_DISABLE_GPGME */
}
@ -5593,9 +5564,7 @@ ostree_repo_verify_commit_for_remote (OstreeRepo *self,
cancellable,
error);
#else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"'%s': GPG feature is disabled in a build time",
__FUNCTION__);
glnx_throw (error, "GPG feature is disabled in a build time");
return NULL;
#endif /* OSTREE_DISABLE_GPGME */
}
@ -5645,9 +5614,7 @@ ostree_repo_gpg_verify_data (OstreeRepo *self,
cancellable,
error);
#else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"'%s': GPG feature is disabled in a build time",
__FUNCTION__);
glnx_throw (error, "GPG feature is disabled in a build time");
return NULL;
#endif /* OSTREE_DISABLE_GPGME */
}
@ -5693,9 +5660,7 @@ ostree_repo_verify_summary (OstreeRepo *self,
cancellable,
error);
#else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"'%s': GPG feature is disabled in a build time",
__FUNCTION__);
glnx_throw (error, "GPG feature is disabled in a build time");
return NULL;
#endif /* OSTREE_DISABLE_GPGME */
}
@ -5998,7 +5963,7 @@ _ostree_repo_maybe_regenerate_summary (OstreeRepo *self,
}
gboolean
_ostree_repo_is_locked_tmpdir (const char *filename)
_ostree_repo_has_staging_prefix (const char *filename)
{
return g_str_has_prefix (filename, OSTREE_REPO_TMPDIR_STAGING);
}
@ -6019,7 +5984,9 @@ _ostree_repo_try_lock_tmpdir (int tmpdir_dfd,
if (!glnx_make_lock_file (tmpdir_dfd, lock_name, LOCK_EX | LOCK_NB,
file_lock_out, &local_error))
{
if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
/* we need to handle EACCES too in the case of POSIX locks; see F_SETLK in fcntl(2) */
if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)
|| g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
{
did_lock = FALSE;
}
@ -6058,7 +6025,7 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (_ostree_repo_is_locked_tmpdir (tmpdir_prefix), FALSE);
g_return_val_if_fail (_ostree_repo_has_staging_prefix (tmpdir_prefix), FALSE);
/* Look for existing tmpdir (with same prefix) to reuse */
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
@ -6280,3 +6247,107 @@ ostree_repo_get_bootloader (OstreeRepo *self)
return self->bootloader;
}
/**
* _ostree_repo_verify_bindings:
* @collection_id: (nullable): Locally specified collection ID for the remote
* the @commit was retrieved from, or %NULL if none is configured
* @ref_name: (nullable): Ref name the commit was retrieved using, or %NULL if
* the commit was retrieved by checksum
* @commit: Commit data to check
* @error: Return location for a #GError, or %NULL
*
* Verify the ref and collection bindings.
*
* The ref binding is verified only if it exists. But if we have the
* collection ID specified in the remote configuration (@collection_id is
* non-%NULL) then the ref binding must exist, otherwise the verification will
* fail. Parts of the verification can be skipped by passing %NULL to the
* @ref_name parameter (in case we requested a checksum directly, without
* looking it up from a ref).
*
* The collection binding is verified only when we have collection ID
* specified in the remote configuration. If it is specified, then the
* binding must exist and must be equal to the remote repository
* collection ID.
*
* Returns: %TRUE if bindings are correct, %FALSE otherwise
* Since: 2017.14
*/
gboolean
_ostree_repo_verify_bindings (const char *collection_id,
const char *ref_name,
GVariant *commit,
GError **error)
{
g_autoptr(GVariant) metadata = g_variant_get_child_value (commit, 0);
g_autofree const char **refs = NULL;
if (!g_variant_lookup (metadata,
OSTREE_COMMIT_META_KEY_REF_BINDING,
"^a&s",
&refs))
{
/* Early return here - if the remote collection ID is NULL, then
* we certainly will not verify the collection binding in the
* commit.
*/
if (collection_id == NULL)
return TRUE;
return glnx_throw (error,
"Expected commit metadata to have ref "
"binding information, found none");
}
if (ref_name != NULL)
{
if (!g_strv_contains ((const char *const *) refs, ref_name))
{
g_autoptr(GString) refs_dump = g_string_new (NULL);
const char *refs_str;
if (refs != NULL && (*refs) != NULL)
{
for (const char **iter = refs; *iter != NULL; ++iter)
{
const char *ref = *iter;
if (refs_dump->len > 0)
g_string_append (refs_dump, ", ");
g_string_append_printf (refs_dump, "%s", ref);
}
refs_str = refs_dump->str;
}
else
{
refs_str = "no refs";
}
return glnx_throw (error, "Commit has no requested ref %s "
"in ref binding metadata (%s)",
ref_name, refs_str);
}
}
if (collection_id != NULL)
{
const char *collection_id_binding;
if (!g_variant_lookup (metadata,
OSTREE_COMMIT_META_KEY_COLLECTION_BINDING,
"&s",
&collection_id_binding))
return glnx_throw (error,
"Expected commit metadata to have collection ID "
"binding information, found none");
if (!g_str_equal (collection_id_binding, collection_id))
return glnx_throw (error,
"Commit has collection ID %s in collection binding "
"metadata, while the remote it came from has "
"collection ID %s",
collection_id_binding, collection_id);
}
return TRUE;
}

View File

@ -691,6 +691,13 @@ _OSTREE_PUBLIC
void ostree_repo_commit_modifier_set_sepolicy (OstreeRepoCommitModifier *modifier,
OstreeSePolicy *sepolicy);
_OSTREE_PUBLIC
gboolean ostree_repo_commit_modifier_set_sepolicy_from_commit (OstreeRepoCommitModifier *modifier,
OstreeRepo *repo,
const char *rev,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC
void ostree_repo_commit_modifier_set_devino_cache (OstreeRepoCommitModifier *modifier,
OstreeRepoDevInoCache *cache);
@ -1167,9 +1174,9 @@ void ostree_repo_commit_traverse_iter_cleanup (void *p);
* @OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY: Do not traverse individual commit objects, only follow refs
*/
typedef enum {
OSTREE_REPO_PRUNE_FLAGS_NONE,
OSTREE_REPO_PRUNE_FLAGS_NO_PRUNE,
OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY
OSTREE_REPO_PRUNE_FLAGS_NONE = 0,
OSTREE_REPO_PRUNE_FLAGS_NO_PRUNE = (1 << 0),
OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY = (1 << 1),
} OstreeRepoPruneFlags;
_OSTREE_PUBLIC

View File

@ -0,0 +1,196 @@
/* vim:set et sw=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e2s: */
/*
* Copyright © 2019 Collabora Ltd.
*
* SPDX-License-Identifier: LGPL-2.0+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include <libglnx.h>
#include "ostree-sign-dummy.h"
#include <string.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "OSTreeSign"
#define OSTREE_SIGN_DUMMY_NAME "dummy"
#define OSTREE_SIGN_METADATA_DUMMY_KEY "ostree.sign.dummy"
#define OSTREE_SIGN_METADATA_DUMMY_TYPE "aay"
struct _OstreeSignDummy
{
GObject parent;
gchar *sk_ascii;
gchar *pk_ascii;
};
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeSignDummy, g_object_unref)
#endif
static void
ostree_sign_dummy_iface_init (OstreeSignInterface *self);
G_DEFINE_TYPE_WITH_CODE (OstreeSignDummy, _ostree_sign_dummy, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (OSTREE_TYPE_SIGN, ostree_sign_dummy_iface_init));
static gboolean
check_dummy_sign_enabled (GError **error)
{
if (g_strcmp0 (g_getenv ("OSTREE_DUMMY_SIGN_ENABLED"), "1") != 0)
return glnx_throw (error, "dummy signature type is only for ostree testing");
return TRUE;
}
static void
ostree_sign_dummy_iface_init (OstreeSignInterface *self)
{
self->get_name = ostree_sign_dummy_get_name;
self->data = ostree_sign_dummy_data;
self->data_verify = ostree_sign_dummy_data_verify;
self->metadata_key = ostree_sign_dummy_metadata_key;
self->metadata_format = ostree_sign_dummy_metadata_format;
self->set_sk = ostree_sign_dummy_set_sk;
self->set_pk = ostree_sign_dummy_set_pk;
/* Implementation for dummy engine just load the single public key */
self->add_pk = ostree_sign_dummy_set_pk;
}
static void
_ostree_sign_dummy_class_init (OstreeSignDummyClass *self)
{
}
static void
_ostree_sign_dummy_init (OstreeSignDummy *self)
{
self->sk_ascii = NULL;
self->pk_ascii = NULL;
}
gboolean ostree_sign_dummy_set_sk (OstreeSign *self, GVariant *key, GError **error)
{
if (!check_dummy_sign_enabled (error))
return FALSE;
OstreeSignDummy *sign = _ostree_sign_dummy_get_instance_private(OSTREE_SIGN_DUMMY(self));
g_free(sign->sk_ascii);
sign->sk_ascii = g_variant_dup_string (key, 0);
return TRUE;
}
gboolean ostree_sign_dummy_set_pk (OstreeSign *self, GVariant *key, GError **error)
{
OstreeSignDummy *sign = _ostree_sign_dummy_get_instance_private(OSTREE_SIGN_DUMMY(self));
g_free(sign->pk_ascii);
sign->pk_ascii = g_variant_dup_string (key, 0);
return TRUE;
}
gboolean ostree_sign_dummy_data (OstreeSign *self,
GBytes *data,
GBytes **signature,
GCancellable *cancellable,
GError **error)
{
if (!check_dummy_sign_enabled (error))
return FALSE;
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
OstreeSignDummy *sign = _ostree_sign_dummy_get_instance_private(OSTREE_SIGN_DUMMY(self));
*signature = g_bytes_new (sign->sk_ascii, strlen(sign->sk_ascii));
return TRUE;
}
const gchar * ostree_sign_dummy_get_name (OstreeSign *self)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
return OSTREE_SIGN_DUMMY_NAME;
}
const gchar * ostree_sign_dummy_metadata_key (OstreeSign *self)
{
return OSTREE_SIGN_METADATA_DUMMY_KEY;
}
const gchar * ostree_sign_dummy_metadata_format (OstreeSign *self)
{
return OSTREE_SIGN_METADATA_DUMMY_TYPE;
}
gboolean ostree_sign_dummy_data_verify (OstreeSign *self,
GBytes *data,
GVariant *signatures,
char **out_success_message,
GError **error)
{
if (!check_dummy_sign_enabled (error))
return FALSE;
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
g_return_val_if_fail (data != NULL, FALSE);
OstreeSignDummy *sign = _ostree_sign_dummy_get_instance_private(OSTREE_SIGN_DUMMY(self));
if (signatures == NULL)
return glnx_throw (error, "signature: dummy: commit have no signatures of my type");
if (!g_variant_is_of_type (signatures, (GVariantType *) OSTREE_SIGN_METADATA_DUMMY_TYPE))
return glnx_throw (error, "signature: dummy: wrong type passed for verification");
for (gsize i = 0; i < g_variant_n_children(signatures); i++)
{
g_autoptr (GVariant) child = g_variant_get_child_value (signatures, i);
g_autoptr (GBytes) signature = g_variant_get_data_as_bytes(child);
gsize sign_size = 0;
g_bytes_get_data (signature, &sign_size);
g_autofree gchar *sign_ascii = g_strndup(g_bytes_get_data (signature, NULL), sign_size);
g_debug("Read signature %d: %s", (gint)i, sign_ascii);
g_debug("Stored signature %d: %s", (gint)i, sign->pk_ascii);
if (!g_strcmp0(sign_ascii, sign->pk_ascii))
{
if (out_success_message)
*out_success_message = g_strdup ("dummy: Signature verified");
return TRUE;
}
else
return glnx_throw (error, "signature: dummy: incorrect signature %" G_GSIZE_FORMAT, i);
}
return glnx_throw (error, "signature: dummy: no signatures");
}

View File

@ -0,0 +1,77 @@
/* vim:set et sw=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e2s: */
/*
* Copyright © 2019 Collabora Ltd.
*
* SPDX-License-Identifier: LGPL-2.0+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors:
* - Denis Pynkin (d4s) <denis.pynkin@collabora.com>
*/
#pragma once
#include "ostree-sign.h"
G_BEGIN_DECLS
#define OSTREE_TYPE_SIGN_DUMMY (_ostree_sign_dummy_get_type ())
GType _ostree_sign_dummy_get_type (void);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
typedef struct _OstreeSignDummy OstreeSignDummy;
typedef struct { GObjectClass parent_class; } OstreeSignDummyClass;
static inline OstreeSignDummy *OSTREE_SIGN_DUMMY (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_CAST (ptr, _ostree_sign_dummy_get_type (), OstreeSignDummy); }
static inline gboolean OSTREE_IS_SIGN_DUMMY (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_TYPE (ptr, _ostree_sign_dummy_get_type ()); }
G_GNUC_END_IGNORE_DEPRECATIONS
/* Have to use glib-2.44 for this
_OSTREE_PUBLIC
G_DECLARE_FINAL_TYPE (OstreeSignDummy,
ostree_sign_dummy,
OSTREE,
SIGN_DUMMY,
GObject)
*/
const gchar * ostree_sign_dummy_get_name (OstreeSign *self);
gboolean ostree_sign_dummy_data (OstreeSign *self,
GBytes *data,
GBytes **signature,
GCancellable *cancellable,
GError **error);
gboolean ostree_sign_dummy_data_verify (OstreeSign *self,
GBytes *data,
GVariant *signatures,
char **success_message,
GError **error);
const gchar * ostree_sign_dummy_metadata_key (OstreeSign *self);
const gchar * ostree_sign_dummy_metadata_format (OstreeSign *self);
gboolean ostree_sign_dummy_set_sk (OstreeSign *self, GVariant *key, GError **error);
gboolean ostree_sign_dummy_set_pk (OstreeSign *self, GVariant *key, GError **error);
gboolean ostree_sign_dummy_add_pk (OstreeSign *self, GVariant *key, GError **error);
G_END_DECLS

View File

@ -0,0 +1,672 @@
/* vim:set et sw=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e2s: */
/*
* Copyright © 2019 Collabora Ltd.
*
* SPDX-License-Identifier: LGPL-2.0+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors:
* - Denis Pynkin (d4s) <denis.pynkin@collabora.com>
*/
#include "config.h"
#include <libglnx.h>
#include "ostree-sign-ed25519.h"
#ifdef HAVE_LIBSODIUM
#include <sodium.h>
#endif
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "OSTreeSign"
#define OSTREE_SIGN_ED25519_NAME "ed25519"
#define OSTREE_SIGN_METADATA_ED25519_KEY "ostree.sign.ed25519"
#define OSTREE_SIGN_METADATA_ED25519_TYPE "aay"
typedef enum
{
ED25519_OK,
ED25519_NOT_SUPPORTED,
ED25519_FAILED_INITIALIZATION
} ed25519_state;
struct _OstreeSignEd25519
{
GObject parent;
ed25519_state state;
guchar *secret_key;
GList *public_keys;
GList *revoked_keys;
};
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeSignEd25519, g_object_unref)
#endif
static void
ostree_sign_ed25519_iface_init (OstreeSignInterface *self);
G_DEFINE_TYPE_WITH_CODE (OstreeSignEd25519, _ostree_sign_ed25519, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (OSTREE_TYPE_SIGN, ostree_sign_ed25519_iface_init));
static void
ostree_sign_ed25519_iface_init (OstreeSignInterface *self)
{
self->data = ostree_sign_ed25519_data;
self->data_verify = ostree_sign_ed25519_data_verify;
self->get_name = ostree_sign_ed25519_get_name;
self->metadata_key = ostree_sign_ed25519_metadata_key;
self->metadata_format = ostree_sign_ed25519_metadata_format;
self->clear_keys = ostree_sign_ed25519_clear_keys;
self->set_sk = ostree_sign_ed25519_set_sk;
self->set_pk = ostree_sign_ed25519_set_pk;
self->add_pk = ostree_sign_ed25519_add_pk;
self->load_pk = ostree_sign_ed25519_load_pk;
}
static void
_ostree_sign_ed25519_class_init (OstreeSignEd25519Class *self)
{
}
static void
_ostree_sign_ed25519_init (OstreeSignEd25519 *self)
{
self->state = ED25519_OK;
self->secret_key = NULL;
self->public_keys = NULL;
self->revoked_keys = NULL;
#ifdef HAVE_LIBSODIUM
if (sodium_init() < 0)
self->state = ED25519_FAILED_INITIALIZATION;
#else
self->state = ED25519_NOT_SUPPORTED;
#endif /* HAVE_LIBSODIUM */
}
static gboolean
_ostree_sign_ed25519_is_initialized (OstreeSignEd25519 *self, GError **error)
{
switch (self->state)
{
case ED25519_OK:
break;
case ED25519_NOT_SUPPORTED:
return glnx_throw(error, "ed25519: engine is not supported");
case ED25519_FAILED_INITIALIZATION:
return glnx_throw(error, "ed25519: libsodium library isn't initialized properly");
}
return TRUE;
}
gboolean ostree_sign_ed25519_data (OstreeSign *self,
GBytes *data,
GBytes **signature,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
OstreeSignEd25519 *sign = _ostree_sign_ed25519_get_instance_private(OSTREE_SIGN_ED25519(self));
#ifdef HAVE_LIBSODIUM
guchar *sig = NULL;
#endif
if (!_ostree_sign_ed25519_is_initialized (sign, error))
return FALSE;
if (sign->secret_key == NULL)
return glnx_throw (error, "Not able to sign: secret key is not set");
#ifdef HAVE_LIBSODIUM
unsigned long long sig_size = 0;
sig = g_malloc0(crypto_sign_BYTES);
if (crypto_sign_detached (sig,
&sig_size,
g_bytes_get_data (data, NULL),
g_bytes_get_size (data),
sign->secret_key))
{
return glnx_throw (error, "Not able to sign: fail to sign the object");
}
*signature = g_bytes_new_take (sig, sig_size);
return TRUE;
#endif /* HAVE_LIBSODIUM */
return FALSE;
}
#ifdef HAVE_LIBSODIUM
static gint
_compare_ed25519_keys(gconstpointer a, gconstpointer b) {
return memcmp (a, b, crypto_sign_PUBLICKEYBYTES);
}
#endif
gboolean ostree_sign_ed25519_data_verify (OstreeSign *self,
GBytes *data,
GVariant *signatures,
char **out_success_message,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
g_return_val_if_fail (data != NULL, FALSE);
OstreeSignEd25519 *sign = _ostree_sign_ed25519_get_instance_private(OSTREE_SIGN_ED25519(self));
if (!_ostree_sign_ed25519_is_initialized (sign, error))
return FALSE;
if (signatures == NULL)
return glnx_throw (error, "ed25519: commit have no signatures of my type");
if (!g_variant_is_of_type (signatures, (GVariantType *) OSTREE_SIGN_METADATA_ED25519_TYPE))
return glnx_throw (error, "ed25519: wrong type passed for verification");
#ifdef HAVE_LIBSODIUM
/* If no keys pre-loaded then,
* try to load public keys from storage(s) */
if (sign->public_keys == NULL)
{
g_autoptr (GVariantBuilder) builder = NULL;
g_autoptr (GVariant) options = NULL;
builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
options = g_variant_builder_end (builder);
if (!ostree_sign_ed25519_load_pk (self, options, error))
return FALSE;
}
g_debug ("verify: data hash = 0x%x", g_bytes_hash(data));
g_autoptr(GString) invalid_signatures = NULL;
guint n_invalid_signatures = 0;
for (gsize i = 0; i < g_variant_n_children(signatures); i++)
{
g_autoptr (GVariant) child = g_variant_get_child_value (signatures, i);
g_autoptr (GBytes) signature = g_variant_get_data_as_bytes(child);
g_autofree char * hex = g_malloc0 (crypto_sign_PUBLICKEYBYTES*2 + 1);
g_debug("Read signature %d: %s", (gint)i, g_variant_print(child, TRUE));
for (GList *public_key = sign->public_keys;
public_key != NULL;
public_key = public_key->next)
{
/* TODO: use non-list for tons of revoked keys? */
if (g_list_find_custom (sign->revoked_keys, public_key->data, _compare_ed25519_keys) != NULL)
{
g_debug("Skip revoked key '%s'",
sodium_bin2hex (hex, crypto_sign_PUBLICKEYBYTES*2+1, public_key->data, crypto_sign_PUBLICKEYBYTES));
continue;
}
if (crypto_sign_verify_detached ((guchar *) g_variant_get_data (child),
g_bytes_get_data (data, NULL),
g_bytes_get_size (data),
public_key->data) != 0)
{
/* Incorrect signature! */
if (invalid_signatures == NULL)
invalid_signatures = g_string_new ("");
else
g_string_append (invalid_signatures, "; ");
n_invalid_signatures++;
g_string_append_printf (invalid_signatures, "key '%s'",
sodium_bin2hex (hex, crypto_sign_PUBLICKEYBYTES*2+1, public_key->data, crypto_sign_PUBLICKEYBYTES));
}
else
{
if (out_success_message)
{
*out_success_message =
g_strdup_printf ("ed25519: Signature verified successfully with key '%s'",
sodium_bin2hex (hex, crypto_sign_PUBLICKEYBYTES*2+1, public_key->data, crypto_sign_PUBLICKEYBYTES));
}
return TRUE;
}
}
}
if (invalid_signatures)
{
g_assert_cmpuint (n_invalid_signatures, >, 0);
/* The test suite has a key ring with 100 keys. This seems insane, let's
* cap a reasonable error message at 3.
*/
if (n_invalid_signatures > 3)
return glnx_throw (error, "ed25519: Signature couldn't be verified; tried %u keys", n_invalid_signatures);
return glnx_throw (error, "ed25519: Signature couldn't be verified with: %s", invalid_signatures->str);
}
return glnx_throw (error, "ed25519: no signatures found");
#endif /* HAVE_LIBSODIUM */
return FALSE;
}
const gchar * ostree_sign_ed25519_get_name (OstreeSign *self)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
return OSTREE_SIGN_ED25519_NAME;
}
const gchar * ostree_sign_ed25519_metadata_key (OstreeSign *self)
{
return OSTREE_SIGN_METADATA_ED25519_KEY;
}
const gchar * ostree_sign_ed25519_metadata_format (OstreeSign *self)
{
return OSTREE_SIGN_METADATA_ED25519_TYPE;
}
gboolean ostree_sign_ed25519_clear_keys (OstreeSign *self,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
OstreeSignEd25519 *sign = _ostree_sign_ed25519_get_instance_private(OSTREE_SIGN_ED25519(self));
if (!_ostree_sign_ed25519_is_initialized (sign, error))
return FALSE;
#ifdef HAVE_LIBSODIUM
/* Clear secret key */
if (sign->secret_key != NULL)
{
memset (sign->secret_key, 0, crypto_sign_SECRETKEYBYTES);
g_free (sign->secret_key);
sign->secret_key = NULL;
}
/* Clear already loaded trusted keys */
if (sign->public_keys != NULL)
{
g_list_free_full (sign->public_keys, g_free);
sign->public_keys = NULL;
}
/* Clear already loaded revoked keys */
if (sign->revoked_keys != NULL)
{
g_list_free_full (sign->revoked_keys, g_free);
sign->revoked_keys = NULL;
}
return TRUE;
#endif /* HAVE_LIBSODIUM */
return FALSE;
}
/* Support 2 representations:
* base64 ascii -- secret key is passed as string
* raw key -- key is passed as bytes array
* */
gboolean ostree_sign_ed25519_set_sk (OstreeSign *self,
GVariant *secret_key,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
if (!ostree_sign_ed25519_clear_keys (self, error))
return FALSE;
#ifdef HAVE_LIBSODIUM
OstreeSignEd25519 *sign = _ostree_sign_ed25519_get_instance_private(OSTREE_SIGN_ED25519(self));
gsize n_elements = 0;
if (g_variant_is_of_type (secret_key, G_VARIANT_TYPE_STRING))
{
const gchar *sk_ascii = g_variant_get_string (secret_key, NULL);
sign->secret_key = g_base64_decode (sk_ascii, &n_elements);
}
else if (g_variant_is_of_type (secret_key, G_VARIANT_TYPE_BYTESTRING))
{
sign->secret_key = (guchar *) g_variant_get_fixed_array (secret_key, &n_elements, sizeof(guchar));
}
else
{
return glnx_throw (error, "Unknown ed25519 secret key type");
}
if (n_elements != crypto_sign_SECRETKEYBYTES)
return glnx_throw (error, "Incorrect ed25519 secret key");
return TRUE;
#endif /* HAVE_LIBSODIUM */
return FALSE;
}
/* Support 2 representations:
* base64 ascii -- public key is passed as string
* raw key -- key is passed as bytes array
* */
gboolean ostree_sign_ed25519_set_pk (OstreeSign *self,
GVariant *public_key,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
if (!ostree_sign_ed25519_clear_keys (self, error))
return FALSE;
return ostree_sign_ed25519_add_pk (self, public_key, error);
}
/* Support 2 representations:
* base64 ascii -- public key is passed as string
* raw key -- key is passed as bytes array
* */
gboolean ostree_sign_ed25519_add_pk (OstreeSign *self,
GVariant *public_key,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
OstreeSignEd25519 *sign = _ostree_sign_ed25519_get_instance_private(OSTREE_SIGN_ED25519(self));
if (!_ostree_sign_ed25519_is_initialized (sign, error))
return FALSE;
#ifdef HAVE_LIBSODIUM
gpointer key = NULL;
gsize n_elements = 0;
if (g_variant_is_of_type (public_key, G_VARIANT_TYPE_STRING))
{
const gchar *pk_ascii = g_variant_get_string (public_key, NULL);
key = g_base64_decode (pk_ascii, &n_elements);
}
else if (g_variant_is_of_type (public_key, G_VARIANT_TYPE_BYTESTRING))
{
key = (gpointer) g_variant_get_fixed_array (public_key, &n_elements, sizeof(guchar));
}
else
{
return glnx_throw (error, "Unknown ed25519 public key type");
}
if (n_elements != crypto_sign_PUBLICKEYBYTES)
return glnx_throw (error, "Incorrect ed25519 public key");
g_autofree char *hex = g_malloc0 (crypto_sign_PUBLICKEYBYTES*2 + 1);
g_debug ("Read ed25519 public key = %s", sodium_bin2hex (hex, crypto_sign_PUBLICKEYBYTES*2+1, key, n_elements));
if (g_list_find_custom (sign->public_keys, key, _compare_ed25519_keys) == NULL)
{
gpointer newkey = g_memdup (key, n_elements);
sign->public_keys = g_list_prepend (sign->public_keys, newkey);
}
#endif /* HAVE_LIBSODIUM */
return TRUE;
}
#ifdef HAVE_LIBSODIUM
/* Add revoked public key */
static gboolean
_ed25519_add_revoked (OstreeSign *self,
GVariant *revoked_key,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
if (!g_variant_is_of_type (revoked_key, G_VARIANT_TYPE_STRING))
return glnx_throw (error, "Unknown ed25519 revoked key type");
OstreeSignEd25519 *sign = _ostree_sign_ed25519_get_instance_private(OSTREE_SIGN_ED25519(self));
const gchar *rk_ascii = g_variant_get_string (revoked_key, NULL);
gsize n_elements = 0;
gpointer key = g_base64_decode (rk_ascii, &n_elements);
if (n_elements != crypto_sign_PUBLICKEYBYTES)
{
return glnx_throw (error, "Incorrect ed25519 revoked key");
}
g_autofree char * hex = g_malloc0 (crypto_sign_PUBLICKEYBYTES*2 + 1);
g_debug ("Read ed25519 revoked key = %s", sodium_bin2hex (hex, crypto_sign_PUBLICKEYBYTES*2+1, key, n_elements));
if (g_list_find_custom (sign->revoked_keys, key, _compare_ed25519_keys) == NULL)
{
gpointer newkey = g_memdup (key, n_elements);
sign->revoked_keys = g_list_prepend (sign->revoked_keys, newkey);
}
return TRUE;
}
#endif /* HAVE_LIBSODIUM */
static gboolean
_load_pk_from_stream (OstreeSign *self,
GDataInputStream *key_data_in,
gboolean trusted,
GError **error)
{
g_return_val_if_fail (key_data_in, FALSE);
#ifdef HAVE_LIBSODIUM
gboolean ret = FALSE;
/* Use simple file format with just a list of base64 public keys per line */
while (TRUE)
{
gsize len = 0;
g_autofree char *line = g_data_input_stream_read_line (key_data_in, &len, NULL, error);
g_autoptr (GVariant) pk = NULL;
gboolean added = FALSE;
if (*error != NULL)
return FALSE;
if (line == NULL)
return ret;
/* Read the key itself */
/* base64 encoded key */
pk = g_variant_new_string (line);
if (trusted)
added = ostree_sign_ed25519_add_pk (self, pk, error);
else
added = _ed25519_add_revoked (self, pk, error);
g_debug ("%s %s key: %s",
added ? "Added" : "Invalid",
trusted ? "public" : "revoked",
line);
/* Mark what we load at least one key */
if (added)
ret = TRUE;
}
#endif /* HAVE_LIBSODIUM */
return FALSE;
}
static gboolean
_load_pk_from_file (OstreeSign *self,
const gchar *filename,
gboolean trusted,
GError **error)
{
g_debug ("Processing file '%s'", filename);
g_autoptr (GFile) keyfile = NULL;
g_autoptr (GFileInputStream) key_stream_in = NULL;
g_autoptr (GDataInputStream) key_data_in = NULL;
if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR))
{
g_debug ("Can't open file '%s' with public keys", filename);
return glnx_throw (error, "File object '%s' is not a regular file", filename);
}
keyfile = g_file_new_for_path (filename);
key_stream_in = g_file_read (keyfile, NULL, error);
if (key_stream_in == NULL)
return FALSE;
key_data_in = g_data_input_stream_new (G_INPUT_STREAM(key_stream_in));
g_assert (key_data_in != NULL);
if (!_load_pk_from_stream (self, key_data_in, trusted, error))
{
if (error == NULL || *error == NULL)
return glnx_throw (error,
"signature: ed25519: no valid keys in file '%s'",
filename);
else
return FALSE;
}
return TRUE;
}
static gboolean
_ed25519_load_pk (OstreeSign *self,
GVariant *options,
gboolean trusted,
GError **error)
{
gboolean ret = FALSE;
const gchar *custom_dir = NULL;
g_autoptr (GPtrArray) base_dirs = g_ptr_array_new_with_free_func (g_free);
g_autoptr (GPtrArray) ed25519_files = g_ptr_array_new_with_free_func (g_free);
if (g_variant_lookup (options, "basedir", "&s", &custom_dir))
{
/* Add custom directory */
g_ptr_array_add (base_dirs, g_strdup (custom_dir));
}
else
{
/* Default paths where to find files with public keys */
g_ptr_array_add (base_dirs, g_strdup ("/etc/ostree"));
g_ptr_array_add (base_dirs, g_strdup (DATADIR "/ostree"));
}
/* Scan all well-known directories and construct the list with file names to scan keys */
for (gint i=0; i < base_dirs->len; i++)
{
gchar *base_name = NULL;
g_autofree gchar *base_dir = NULL;
g_autoptr (GDir) dir = NULL;
base_name = g_build_filename ((gchar *)g_ptr_array_index (base_dirs, i),
trusted ? "trusted.ed25519" : "revoked.ed25519",
NULL);
g_debug ("Check ed25519 keys from file: %s", base_name);
g_ptr_array_add (ed25519_files, base_name);
base_dir = g_strconcat (base_name, ".d", NULL);
dir = g_dir_open (base_dir, 0, error);
if (dir == NULL)
{
g_clear_error (error);
continue;
}
const gchar *entry = NULL;
while ((entry = g_dir_read_name (dir)) != NULL)
{
gchar *filename = g_build_filename (base_dir, entry, NULL);
g_debug ("Check ed25519 keys from file: %s", filename);
g_ptr_array_add (ed25519_files, filename);
}
}
/* Scan all well-known files */
for (gint i=0; i < ed25519_files->len; i++)
{
if (!_load_pk_from_file (self, (gchar *)g_ptr_array_index (ed25519_files, i), trusted, error))
{
g_debug ("Problem with loading ed25519 %s keys from `%s`",
trusted ? "public" : "revoked",
(gchar *)g_ptr_array_index (ed25519_files, i));
g_clear_error(error);
}
else
ret = TRUE;
}
if (!ret && (error == NULL || *error == NULL))
return glnx_throw (error, "signature: ed25519: no keys loaded");
return ret;
}
/*
* options argument should be a{sv}:
* - filename -- single file to use to load keys from;
* - basedir -- directory containing subdirectories
* 'trusted.ed25519.d' and 'revoked.ed25519.d' with appropriate
* public keys. Used for testing and re-definition of system-wide
* directories if defaults are not suitable for any reason.
*/
gboolean
ostree_sign_ed25519_load_pk (OstreeSign *self,
GVariant *options,
GError **error)
{
const gchar *filename = NULL;
OstreeSignEd25519 *sign = _ostree_sign_ed25519_get_instance_private(OSTREE_SIGN_ED25519(self));
if (!_ostree_sign_ed25519_is_initialized (sign, error))
return FALSE;
/* Read keys only from single file provided */
if (g_variant_lookup (options, "filename", "&s", &filename))
return _load_pk_from_file (self, filename, TRUE, error);
/* Load public keys from well-known directories and files */
if (!_ed25519_load_pk (self, options, TRUE, error))
return FALSE;
/* Load untrusted keys from well-known directories and files
* Ignore the failure from this function -- it is expected to have
* empty list of revoked keys.
* */
if (!_ed25519_load_pk (self, options, FALSE, error))
g_clear_error(error);
return TRUE;
}

View File

@ -0,0 +1,91 @@
/* vim:set et sw=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e2s: */
/*
* Copyright © 2019 Collabora Ltd.
*
* SPDX-License-Identifier: LGPL-2.0+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors:
* - Denis Pynkin (d4s) <denis.pynkin@collabora.com>
*/
#pragma once
#include "ostree-sign.h"
G_BEGIN_DECLS
#define OSTREE_TYPE_SIGN_ED25519 (_ostree_sign_ed25519_get_type ())
GType _ostree_sign_ed25519_get_type (void);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
typedef struct _OstreeSignEd25519 OstreeSignEd25519;
typedef struct { GObjectClass parent_class; } OstreeSignEd25519Class;
static inline OstreeSignEd25519 *OSTREE_SIGN_ED25519 (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_CAST (ptr, _ostree_sign_ed25519_get_type (), OstreeSignEd25519); }
static inline gboolean OSTREE_IS_SIGN_ED25519 (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_TYPE (ptr, _ostree_sign_ed25519_get_type ()); }
G_GNUC_END_IGNORE_DEPRECATIONS
/* Have to use glib-2.44 for this
_OSTREE_PUBLIC
G_DECLARE_FINAL_TYPE (OstreeSignEd25519,
ostree_sign_ed25519,
OSTREE,
SIGN_ED25519,
GObject)
*/
gboolean ostree_sign_ed25519_data (OstreeSign *self,
GBytes *data,
GBytes **signature,
GCancellable *cancellable,
GError **error);
gboolean ostree_sign_ed25519_data_verify (OstreeSign *self,
GBytes *data,
GVariant *signatures,
char **out_success_message,
GError **error);
const gchar * ostree_sign_ed25519_get_name (OstreeSign *self);
const gchar * ostree_sign_ed25519_metadata_key (OstreeSign *self);
const gchar * ostree_sign_ed25519_metadata_format (OstreeSign *self);
gboolean ostree_sign_ed25519_clear_keys (OstreeSign *self,
GError **error);
gboolean ostree_sign_ed25519_set_sk (OstreeSign *self,
GVariant *secret_key,
GError **error);
gboolean ostree_sign_ed25519_set_pk (OstreeSign *self,
GVariant *public_key,
GError **error);
gboolean ostree_sign_ed25519_add_pk (OstreeSign *self,
GVariant *public_key,
GError **error);
gboolean ostree_sign_ed25519_load_pk (OstreeSign *self,
GVariant *options,
GError **error);
G_END_DECLS

668
src/libostree/ostree-sign.c Normal file
View File

@ -0,0 +1,668 @@
/* vim:set et sw=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e2s: */
/*
* Copyright © 2019 Collabora Ltd.
*
* SPDX-License-Identifier: LGPL-2.0+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
/**
* SECTION:ostree-sign
* @title: Signature management
* @short_description: Sign and verify commits
*
* An #OstreeSign interface allows to select and use any available engine
* for signing or verifying the commit object or summary file.
*/
#include "config.h"
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include "libglnx.h"
#include "otutil.h"
#include "ostree-autocleanups.h"
#include "ostree-core.h"
#include "ostree-sign.h"
#include "ostree-sign-dummy.h"
#ifdef HAVE_LIBSODIUM
#include "ostree-sign-ed25519.h"
#endif
#include "ostree-autocleanups.h"
#include "ostree-repo-private.h"
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "OSTreeSign"
typedef struct
{
gchar *name;
GType type;
} _sign_type;
_sign_type sign_types[] =
{
#if defined(HAVE_LIBSODIUM)
{OSTREE_SIGN_NAME_ED25519, 0},
#endif
{"dummy", 0}
};
enum
{
#if defined(HAVE_LIBSODIUM)
SIGN_ED25519,
#endif
SIGN_DUMMY
};
G_DEFINE_INTERFACE (OstreeSign, ostree_sign, G_TYPE_OBJECT)
static void
ostree_sign_default_init (OstreeSignInterface *iface)
{
g_debug ("OstreeSign initialization");
}
/**
* ostree_sign_metadata_key:
* @self: an #OstreeSign object
*
* Return the pointer to the name of the key used in (detached) metadata for
* current signing engine.
*
* Returns: (transfer none): pointer to the metadata key name,
* @NULL in case of error (unlikely).
*
* Since: 2020.2
*/
const gchar *
ostree_sign_metadata_key (OstreeSign *self)
{
g_return_val_if_fail (OSTREE_SIGN_GET_IFACE (self)->metadata_key != NULL, NULL);
return OSTREE_SIGN_GET_IFACE (self)->metadata_key (self);
}
/**
* ostree_sign_metadata_format:
* @self: an #OstreeSign object
*
* Return the pointer to the string with format used in (detached) metadata for
* current signing engine.
*
* Returns: (transfer none): pointer to the metadata format,
* @NULL in case of error (unlikely).
*
* Since: 2020.2
*/
const gchar *
ostree_sign_metadata_format (OstreeSign *self)
{
g_return_val_if_fail (OSTREE_SIGN_GET_IFACE (self)->metadata_format != NULL, NULL);
return OSTREE_SIGN_GET_IFACE (self)->metadata_format (self);
}
/**
* ostree_sign_clear_keys:
* @self: an #OstreeSign object
* @error: a #GError
*
* Clear all previously preloaded secret and public keys.
*
* Returns: @TRUE in case if no errors, @FALSE in case of error
*
* Since: 2020.2
*/
gboolean
ostree_sign_clear_keys (OstreeSign *self,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
if (OSTREE_SIGN_GET_IFACE (self)->clear_keys == NULL)
return glnx_throw (error, "not implemented");
return OSTREE_SIGN_GET_IFACE (self)->clear_keys (self, error);
}
/**
* ostree_sign_set_sk:
* @self: an #OstreeSign object
* @secret_key: secret key to be added
* @error: a #GError
*
* Set the secret key to be used for signing data, commits and summary.
*
* The @secret_key argument depends of the particular engine implementation.
*
* Returns: @TRUE in case if the key could be set successfully,
* @FALSE in case of error (@error will contain the reason).
*
* Since: 2020.2
*/
gboolean
ostree_sign_set_sk (OstreeSign *self,
GVariant *secret_key,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
if (OSTREE_SIGN_GET_IFACE (self)->set_sk == NULL)
return glnx_throw (error, "not implemented");
return OSTREE_SIGN_GET_IFACE (self)->set_sk (self, secret_key, error);
}
/**
* ostree_sign_set_pk:
* @self: an #OstreeSign object
* @public_key: single public key to be added
* @error: a #GError
*
* Set the public key for verification. It is expected what all
* previously pre-loaded public keys will be dropped.
*
* The @public_key argument depends of the particular engine implementation.
*
* Returns: @TRUE in case if the key could be set successfully,
* @FALSE in case of error (@error will contain the reason).
*
* Since: 2020.2
*/
gboolean
ostree_sign_set_pk (OstreeSign *self,
GVariant *public_key,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
if (OSTREE_SIGN_GET_IFACE (self)->set_pk == NULL)
return glnx_throw (error, "not implemented");
return OSTREE_SIGN_GET_IFACE (self)->set_pk (self, public_key, error);
}
/**
* ostree_sign_add_pk:
* @self: an #OstreeSign object
* @public_key: single public key to be added
* @error: a #GError
*
* Add the public key for verification. Could be called multiple times for
* adding all needed keys to be used for verification.
*
* The @public_key argument depends of the particular engine implementation.
*
* Returns: @TRUE in case if the key could be added successfully,
* @FALSE in case of error (@error will contain the reason).
*
* Since: 2020.2
*/
gboolean
ostree_sign_add_pk (OstreeSign *self,
GVariant *public_key,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
if (OSTREE_SIGN_GET_IFACE (self)->add_pk == NULL)
return glnx_throw (error, "not implemented");
return OSTREE_SIGN_GET_IFACE (self)->add_pk (self, public_key, error);
}
/**
* ostree_sign_load_pk:
* @self: an #OstreeSign object
* @options: any options
* @error: a #GError
*
* Load public keys for verification from anywhere.
* It is expected that all keys would be added to already pre-loaded keys.
*
* The @options argument depends of the particular engine implementation.
*
* For example, @ed25515 engine could use following string-formatted options:
* - @filename -- single file to use to load keys from
* - @basedir -- directory containing subdirectories
* 'trusted.ed25519.d' and 'revoked.ed25519.d' with appropriate
* public keys. Used for testing and re-definition of system-wide
* directories if defaults are not suitable for any reason.
*
* Returns: @TRUE in case if at least one key could be load successfully,
* @FALSE in case of error (@error will contain the reason).
*
* Since: 2020.2
*/
/*
* No need to have similar function for secret keys load -- it is expected
* what the signing software will load the secret key in it's own way.
*/
gboolean
ostree_sign_load_pk (OstreeSign *self,
GVariant *options,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
if (OSTREE_SIGN_GET_IFACE (self)->load_pk == NULL)
return glnx_throw (error, "not implemented");
return OSTREE_SIGN_GET_IFACE (self)->load_pk (self, options, error);
}
/**
* ostree_sign_data:
* @self: an #OstreeSign object
* @data: the raw data to be signed with pre-loaded secret key
* @signature: in case of success will contain signature
* @cancellable: A #GCancellable
* @error: a #GError
*
* Sign the given @data with pre-loaded secret key.
*
* Depending of the signing engine used you will need to load
* the secret key with #ostree_sign_set_sk.
*
* Returns: @TRUE if @data has been signed successfully,
* @FALSE in case of error (@error will contain the reason).
*
* Since: 2020.2
*/
gboolean
ostree_sign_data (OstreeSign *self,
GBytes *data,
GBytes **signature,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
if (OSTREE_SIGN_GET_IFACE (self)->data == NULL)
return glnx_throw (error, "not implemented");
return OSTREE_SIGN_GET_IFACE (self)->data (self, data, signature, cancellable, error);
}
/**
* ostree_sign_data_verify:
* @self: an #OstreeSign object
* @data: the raw data to check
* @signatures: the signatures to be checked
* @error: a #GError
*
* Verify given data against signatures with pre-loaded public keys.
*
* Depending of the signing engine used you will need to load
* the public key(s) with #ostree_sign_set_pk, #ostree_sign_add_pk
* or #ostree_sign_load_pk.
*
* Returns: @TRUE if @data has been signed at least with any single valid key,
* @FALSE in case of error or no valid keys are available (@error will contain the reason).
*
* Since: 2020.2
*/
gboolean
ostree_sign_data_verify (OstreeSign *self,
GBytes *data,
GVariant *signatures,
char **out_success_message,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
if (OSTREE_SIGN_GET_IFACE (self)->data_verify == NULL)
return glnx_throw (error, "not implemented");
return OSTREE_SIGN_GET_IFACE (self)->data_verify(self, data, signatures, out_success_message, error);
}
/*
* Adopted version of _ostree_detached_metadata_append_gpg_sig ()
*/
static GVariant *
_sign_detached_metadata_append (OstreeSign *self,
GVariant *existing_metadata,
GBytes *signature_bytes)
{
g_return_val_if_fail (signature_bytes != NULL, FALSE);
GVariantDict metadata_dict;
g_autoptr(GVariant) signature_data = NULL;
g_autoptr(GVariantBuilder) signature_builder = NULL;
g_variant_dict_init (&metadata_dict, existing_metadata);
const gchar *signature_key = ostree_sign_metadata_key(self);
GVariantType *signature_format = (GVariantType *) ostree_sign_metadata_format(self);
signature_data = g_variant_dict_lookup_value (&metadata_dict,
signature_key,
(GVariantType*)signature_format);
/* signature_data may be NULL */
signature_builder = ot_util_variant_builder_from_variant (signature_data, signature_format);
g_variant_builder_add (signature_builder, "@ay", ot_gvariant_new_ay_bytes (signature_bytes));
g_variant_dict_insert_value (&metadata_dict,
signature_key,
g_variant_builder_end (signature_builder));
return g_variant_dict_end (&metadata_dict);
}
/**
* ostree_sign_commit_verify:
* @self: an #OstreeSign object
* @repo: an #OsreeRepo object
* @commit_checksum: SHA256 of given commit to verify
* @cancellable: A #GCancellable
* @error: a #GError
*
* Verify if commit is signed with known key.
*
* Depending of the signing engine used you will need to load
* the public key(s) for verification with #ostree_sign_set_pk,
* #ostree_sign_add_pk and/or #ostree_sign_load_pk.
*
* Returns: @TRUE if commit has been verified successfully,
* @FALSE in case of error or no valid keys are available (@error will contain the reason).
*
* Since: 2020.2
*/
gboolean
ostree_sign_commit_verify (OstreeSign *self,
OstreeRepo *repo,
const gchar *commit_checksum,
char **out_success_message,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
g_autoptr(GVariant) commit_variant = NULL;
/* Load the commit */
if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT,
commit_checksum, &commit_variant,
error))
return glnx_prefix_error (error, "Failed to read commit");
/* Load the metadata */
g_autoptr(GVariant) metadata = NULL;
if (!ostree_repo_read_commit_detached_metadata (repo,
commit_checksum,
&metadata,
cancellable,
error))
return glnx_prefix_error (error, "Failed to read detached metadata");
g_autoptr(GBytes) signed_data = g_variant_get_data_as_bytes (commit_variant);
g_autoptr(GVariant) signatures = NULL;
const gchar *signature_key = ostree_sign_metadata_key(self);
GVariantType *signature_format = (GVariantType *) ostree_sign_metadata_format(self);
if (metadata)
signatures = g_variant_lookup_value (metadata,
signature_key,
signature_format);
return ostree_sign_data_verify (self,
signed_data,
signatures,
out_success_message,
error);
}
/**
* ostree_sign_get_name:
* @self: an #OstreeSign object
*
* Return the pointer to the name of currently used/selected signing engine.
*
* Returns: (transfer none): pointer to the name
* @NULL in case of error (unlikely).
*
* Since: 2020.2
*/
const gchar *
ostree_sign_get_name (OstreeSign *self)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), NULL);
g_return_val_if_fail (OSTREE_SIGN_GET_IFACE (self)->get_name != NULL, NULL);
return OSTREE_SIGN_GET_IFACE (self)->get_name (self);
}
/**
* ostree_sign_commit:
* @self: an #OstreeSign object
* @repo: an #OsreeRepo object
* @commit_checksum: SHA256 of given commit to sign
* @cancellable: A #GCancellable
* @error: a #GError
*
* Add a signature to a commit.
*
* Depending of the signing engine used you will need to load
* the secret key with #ostree_sign_set_sk.
*
* Returns: @TRUE if commit has been signed successfully,
* @FALSE in case of error (@error will contain the reason).
*
* Since: 2020.2
*/
gboolean
ostree_sign_commit (OstreeSign *self,
OstreeRepo *repo,
const gchar *commit_checksum,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GBytes) commit_data = NULL;
g_autoptr(GBytes) signature = NULL;
g_autoptr(GVariant) commit_variant = NULL;
g_autoptr(GVariant) old_metadata = NULL;
g_autoptr(GVariant) new_metadata = NULL;
if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT,
commit_checksum, &commit_variant, error))
return glnx_prefix_error (error, "Failed to read commit");
if (!ostree_repo_read_commit_detached_metadata (repo,
commit_checksum,
&old_metadata,
cancellable,
error))
return glnx_prefix_error (error, "Failed to read detached metadata");
commit_data = g_variant_get_data_as_bytes (commit_variant);
if (!ostree_sign_data (self, commit_data, &signature,
cancellable, error))
return glnx_prefix_error (error, "Not able to sign the cobject");
new_metadata =
_sign_detached_metadata_append (self, old_metadata, signature);
if (!ostree_repo_write_commit_detached_metadata (repo,
commit_checksum,
new_metadata,
cancellable,
error))
return FALSE;
return TRUE;
}
/**
* ostree_sign_get_all:
*
* Return an array with newly allocated instances of all available
* signing engines; they will not be initialized.
*
* Returns: (transfer full) (element-type OstreeSign): an array of signing engines
*
* Since: 2020.2
*/
GPtrArray *
ostree_sign_get_all (void)
{
g_autoptr(GPtrArray) engines = g_ptr_array_new_with_free_func (g_object_unref);
for (guint i = 0; i < G_N_ELEMENTS(sign_types); i++)
{
OstreeSign *engine = ostree_sign_get_by_name (sign_types[i].name, NULL);
g_assert (engine);
g_ptr_array_add (engines, engine);
}
return g_steal_pointer (&engines);
}
/**
* ostree_sign_get_by_name:
* @name: the name of desired signature engine
* @error: return location for a #GError
*
* Create a new instance of a signing engine.
*
* Returns: (transfer full): New signing engine, or %NULL if the engine is not known
*
* Since: 2020.2
*/
OstreeSign *
ostree_sign_get_by_name (const gchar *name, GError **error)
{
OstreeSign *sign = NULL;
/* Get types if not initialized yet */
#if defined(HAVE_LIBSODIUM)
if (sign_types[SIGN_ED25519].type == 0)
sign_types[SIGN_ED25519].type = OSTREE_TYPE_SIGN_ED25519;
#endif
if (sign_types[SIGN_DUMMY].type == 0)
sign_types[SIGN_DUMMY].type = OSTREE_TYPE_SIGN_DUMMY;
for (gint i=0; i < G_N_ELEMENTS(sign_types); i++)
{
if (g_strcmp0 (name, sign_types[i].name) == 0)
{
g_debug ("Using '%s' signing engine", sign_types[i].name);
sign = g_object_new (sign_types[i].type, NULL);
break;
}
}
if (sign == NULL)
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Requested signature type is not implemented");
return sign;
}
/**
* ostree_sign_summary:
* @self: Self
* @repo: ostree repository
* @keys: keys -- GVariant containing keys as GVarints specific to signature type.
* @cancellable: A #GCancellable
* @error: a #GError
*
* Add a signature to a summary file.
* Based on ostree_repo_add_gpg_signature_summary implementation.
*
* Returns: @TRUE if summary file has been signed with all provided keys
*/
gboolean
ostree_sign_summary (OstreeSign *self,
OstreeRepo *repo,
GVariant *keys,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
g_return_val_if_fail (OSTREE_IS_REPO (repo), FALSE);
g_autoptr(GVariant) normalized = NULL;
g_autoptr(GBytes) summary_data = NULL;
g_autoptr(GVariant) metadata = NULL;
glnx_autofd int fd = -1;
if (!glnx_openat_rdonly (repo->repo_dir_fd, "summary", TRUE, &fd, error))
return FALSE;
summary_data = ot_fd_readall_or_mmap (fd, 0, error);
if (!summary_data)
return FALSE;
/* Note that fd is reused below */
glnx_close_fd (&fd);
if (!ot_openat_ignore_enoent (repo->repo_dir_fd, "summary.sig", &fd, error))
return FALSE;
if (fd >= 0)
{
if (!ot_variant_read_fd (fd, 0, OSTREE_SUMMARY_SIG_GVARIANT_FORMAT,
FALSE, &metadata, error))
return FALSE;
}
if (g_variant_n_children(keys) == 0)
return glnx_throw (error, "No keys passed for signing summary");
GVariantIter *iter;
GVariant *key;
g_variant_get (keys, "av", &iter);
while (g_variant_iter_loop (iter, "v", &key))
{
g_autoptr (GBytes) signature = NULL;
if (!ostree_sign_set_sk (self, key, error))
return FALSE;
if (!ostree_sign_data (self,
summary_data,
&signature,
cancellable,
error))
return FALSE;
g_autoptr(GVariant) old_metadata = g_steal_pointer (&metadata);
metadata =
_sign_detached_metadata_append (self, old_metadata, signature);
}
g_variant_iter_free (iter);
normalized = g_variant_get_normal_form (metadata);
if (!_ostree_repo_file_replace_contents (repo,
repo->repo_dir_fd,
"summary.sig",
g_variant_get_data (normalized),
g_variant_get_size (normalized),
cancellable, error))
return FALSE;
return TRUE;
}

171
src/libostree/ostree-sign.h Normal file
View File

@ -0,0 +1,171 @@
/* vim:set et sw=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e2s: */
/*
* Copyright © 2019 Collabora Ltd.
*
* SPDX-License-Identifier: LGPL-2.0+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors:
* - Denis Pynkin (d4s) <denis.pynkin@collabora.com>
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include "ostree-ref.h"
#include "ostree-remote.h"
#include "ostree-types.h"
G_BEGIN_DECLS
#define OSTREE_TYPE_SIGN (ostree_sign_get_type ())
_OSTREE_PUBLIC
GType ostree_sign_get_type (void);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
typedef struct _OstreeSign OstreeSign;
typedef struct _OstreeSignInterface OstreeSignInterface;
static inline OstreeSign *OSTREE_SIGN (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_CAST (ptr, ostree_sign_get_type (), OstreeSign); }
static inline gboolean OSTREE_IS_SIGN (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_TYPE (ptr, ostree_sign_get_type ()); }
static inline OstreeSignInterface *OSTREE_SIGN_GET_IFACE (gpointer ptr) { return G_TYPE_INSTANCE_GET_INTERFACE (ptr, ostree_sign_get_type (), OstreeSignInterface); }
G_GNUC_END_IGNORE_DEPRECATIONS
/**
* OSTREE_SIGN_NAME_ED25519:
* The name of the default ed25519 signing type.
*/
#define OSTREE_SIGN_NAME_ED25519 "ed25519"
/* Have to use glib-2.44 for this
_OSTREE_PUBLIC
G_DECLARE_INTERFACE (OstreeSign, ostree_sign, OSTREE, SIGN, GObject)
*/
struct _OstreeSignInterface
{
GTypeInterface g_iface;
const gchar *(* get_name) (OstreeSign *self);
gboolean (* data) (OstreeSign *self,
GBytes *data,
GBytes **signature,
GCancellable *cancellable,
GError **error);
gboolean (* data_verify) (OstreeSign *self,
GBytes *data,
GVariant *signatures,
char **out_success_message,
GError **error);
const gchar *(* metadata_key) (OstreeSign *self);
const gchar *(* metadata_format) (OstreeSign *self);
gboolean (* clear_keys) (OstreeSign *self,
GError **error);
gboolean (* set_sk) (OstreeSign *self,
GVariant *secret_key,
GError **error);
gboolean (* set_pk) (OstreeSign *self,
GVariant *public_key,
GError **error);
gboolean (* add_pk) (OstreeSign *self,
GVariant *public_key,
GError **error);
gboolean (* load_pk) (OstreeSign *self,
GVariant *options,
GError **error);
};
_OSTREE_PUBLIC
const gchar * ostree_sign_get_name (OstreeSign *self);
_OSTREE_PUBLIC
gboolean ostree_sign_data (OstreeSign *self,
GBytes *data,
GBytes **signature,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_sign_data_verify (OstreeSign *self,
GBytes *data,
GVariant *signatures,
char **out_success_message,
GError **error);
_OSTREE_PUBLIC
const gchar * ostree_sign_metadata_key (OstreeSign *self);
_OSTREE_PUBLIC
const gchar * ostree_sign_metadata_format (OstreeSign *self);
_OSTREE_PUBLIC
gboolean ostree_sign_commit (OstreeSign *self,
OstreeRepo *repo,
const gchar *commit_checksum,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_sign_commit_verify (OstreeSign *self,
OstreeRepo *repo,
const gchar *commit_checksum,
char **out_success_message,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_sign_clear_keys (OstreeSign *self,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_sign_set_sk (OstreeSign *self,
GVariant *secret_key,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_sign_set_pk (OstreeSign *self,
GVariant *public_key,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_sign_add_pk (OstreeSign *self,
GVariant *public_key,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_sign_load_pk (OstreeSign *self,
GVariant *options,
GError **error);
_OSTREE_PUBLIC
GPtrArray * ostree_sign_get_all(void);
_OSTREE_PUBLIC
OstreeSign * ostree_sign_get_by_name (const gchar *name, GError **error);
_OSTREE_PUBLIC
gboolean ostree_sign_summary (OstreeSign *self,
OstreeRepo *repo,
GVariant *keys,
GCancellable *cancellable,
GError **error);
G_END_DECLS

View File

@ -217,6 +217,79 @@ dirfd_copy_attributes_and_xattrs (int src_parent_dfd,
return TRUE;
}
static gint
str_sort_cb (gconstpointer name_ptr_a, gconstpointer name_ptr_b)
{
const gchar *name_a = *((const gchar **) name_ptr_a);
const gchar *name_b = *((const gchar **) name_ptr_b);
return g_strcmp0 (name_a, name_b);
}
static gboolean
checksum_dir_recurse (int dfd,
const char *path,
OtChecksum *checksum,
GCancellable *cancellable,
GError **error)
{
g_auto(GLnxDirFdIterator) dfditer = { 0, };
g_autoptr (GPtrArray) d_entries = g_ptr_array_new_with_free_func (g_free);
if (!glnx_dirfd_iterator_init_at (dfd, path, TRUE, &dfditer, error))
return FALSE;
while (TRUE)
{
struct dirent *dent;
if (!glnx_dirfd_iterator_next_dent (&dfditer, &dent, cancellable, error))
return FALSE;
if (dent == NULL)
break;
g_ptr_array_add (d_entries, g_strdup (dent->d_name));
}
/* File systems do not guarantee dir entry order, make sure this is
* reproducable
*/
g_ptr_array_sort(d_entries, str_sort_cb);
for (gint i=0; i < d_entries->len; i++)
{
const gchar *d_name = (gchar *)g_ptr_array_index (d_entries, i);
struct stat stbuf;
if (!glnx_fstatat (dfditer.fd, d_name, &stbuf,
AT_SYMLINK_NOFOLLOW, error))
return FALSE;
if (S_ISDIR (stbuf.st_mode))
{
if (!checksum_dir_recurse(dfditer.fd, d_name, checksum, cancellable, error))
return FALSE;
}
else
{
int fd;
if (!ot_openat_ignore_enoent (dfditer.fd, d_name, &fd, error))
return FALSE;
if (fd != -1)
{
g_autoptr(GInputStream) in = g_unix_input_stream_new (fd, FALSE);
if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error))
return FALSE;
}
}
}
return TRUE;
}
static gboolean
copy_dir_recurse (int src_parent_dfd,
int dest_parent_dfd,
@ -1065,6 +1138,9 @@ get_kernel_from_tree_usrlib_modules (int deployment_dfd,
g_clear_object (&in);
glnx_close_fd (&fd);
/* Check for /usr/lib/modules/$kver/devicetree first, if it does not
* exist check for /usr/lib/modules/$kver/dtb/ directory.
*/
if (!ot_openat_ignore_enoent (ret_layout->boot_dfd, "devicetree", &fd, error))
return FALSE;
if (fd != -1)
@ -1075,6 +1151,23 @@ get_kernel_from_tree_usrlib_modules (int deployment_dfd,
if (!ot_gio_splice_update_checksum (NULL, in, &checksum, cancellable, error))
return FALSE;
}
else
{
struct stat stbuf;
/* Check for dtb directory */
if (!glnx_fstatat_allow_noent (ret_layout->boot_dfd, "dtb", &stbuf, 0, error))
return FALSE;
if (errno == 0 && S_ISDIR (stbuf.st_mode))
{
/* devicetree_namever set to NULL indicates a complete directory */
ret_layout->devicetree_srcpath = g_strdup ("dtb");
ret_layout->devicetree_namever = NULL;
if (!checksum_dir_recurse(ret_layout->boot_dfd, "dtb", &checksum, cancellable, error))
return FALSE;
}
}
g_clear_object (&in);
glnx_close_fd (&fd);
@ -1730,15 +1823,24 @@ install_deployment_kernel (OstreeSysroot *sysroot,
if (kernel_layout->devicetree_srcpath)
{
g_assert (kernel_layout->devicetree_namever);
if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->devicetree_namever, &stbuf, 0, error))
return FALSE;
if (errno == ENOENT)
/* If devicetree_namever is set a single device tree is deployed */
if (kernel_layout->devicetree_namever)
{
if (!install_into_boot (repo, sepolicy, kernel_layout->boot_dfd, kernel_layout->devicetree_srcpath,
bootcsum_dfd, kernel_layout->devicetree_namever,
sysroot->debug_flags,
cancellable, error))
if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->devicetree_namever, &stbuf, 0, error))
return FALSE;
if (errno == ENOENT)
{
if (!install_into_boot (repo, sepolicy, kernel_layout->boot_dfd, kernel_layout->devicetree_srcpath,
bootcsum_dfd, kernel_layout->devicetree_namever,
sysroot->debug_flags,
cancellable, error))
return FALSE;
}
}
else
{
if (!copy_dir_recurse(kernel_layout->boot_dfd, bootcsum_dfd, kernel_layout->devicetree_srcpath,
sysroot->debug_flags, cancellable, error))
return FALSE;
}
}
@ -1850,6 +1952,15 @@ install_deployment_kernel (OstreeSysroot *sysroot,
g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->devicetree_namever, NULL);
ostree_bootconfig_parser_set (bootconfig, "devicetree", boot_relpath);
}
else if (kernel_layout->devicetree_srcpath)
{
/* If devicetree_srcpath is set but devicetree_namever is NULL, then we
* want to point to a whole directory of device trees.
* See: https://github.com/ostreedev/ostree/issues/1900
*/
g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->devicetree_srcpath, NULL);
ostree_bootconfig_parser_set (bootconfig, "fdtdir", boot_relpath);
}
/* Note this is parsed in ostree-impl-system-generator.c */
g_autofree char *ostree_kernel_arg = g_strdup_printf ("ostree=/ostree/boot.%d/%s/%s/%d",

View File

@ -530,8 +530,8 @@ ostree_sysroot_upgrader_pull_one_dir (OstreeSysrootUpgrader *self,
g_variant_new_variant (g_variant_new_int32 (flags)));
/* Add the timestamp check, unless disabled */
if ((upgrader_flags & OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER) == 0)
g_variant_builder_add (optbuilder, "{s@v}", "timestamp-check",
g_variant_new_variant (g_variant_new_boolean (TRUE)));
g_variant_builder_add (optbuilder, "{s@v}", "timestamp-check-from-rev",
g_variant_new_variant (g_variant_new_string (from_revision)));
g_variant_builder_add (optbuilder, "{s@v}", "refs",
g_variant_new_variant (g_variant_new_strv ((const char *const*) refs_to_fetch, -1)));

View File

@ -988,30 +988,12 @@ _ostree_sysroot_reload_staged (OstreeSysroot *self,
return TRUE;
}
/**
* ostree_sysroot_load_if_changed:
* @self: #OstreeSysroot
* @out_changed: (out caller-allocates):
* @cancellable: Cancellable
* @error: Error
*
* Since: 2016.4
*/
gboolean
ostree_sysroot_load_if_changed (OstreeSysroot *self,
gboolean *out_changed,
GCancellable *cancellable,
GError **error)
static gboolean
sysroot_load_from_bootloader_configs (OstreeSysroot *self,
GCancellable *cancellable,
GError **error)
{
if (!ostree_sysroot_initialize (self, error))
return FALSE;
/* Here we also lazily initialize the repository. We didn't do this
* previous to v2017.6, but we do now to support the error-free
* ostree_sysroot_repo() API.
*/
if (!ensure_repo (self, error))
return FALSE;
struct stat stbuf;
int bootversion = 0;
if (!read_current_bootversion (self, &bootversion, cancellable, error))
@ -1022,27 +1004,6 @@ ostree_sysroot_load_if_changed (OstreeSysroot *self,
cancellable, error))
return FALSE;
struct stat stbuf;
if (!glnx_fstatat (self->sysroot_fd, "ostree/deploy", &stbuf, 0, error))
return FALSE;
if (out_changed)
{
if (self->loaded_ts.tv_sec == stbuf.st_mtim.tv_sec &&
self->loaded_ts.tv_nsec == stbuf.st_mtim.tv_nsec)
{
*out_changed = FALSE;
/* Note early return */
return TRUE;
}
}
g_clear_pointer (&self->deployments, g_ptr_array_unref);
g_clear_object (&self->booted_deployment);
g_clear_object (&self->staged_deployment);
self->bootversion = -1;
self->subbootversion = -1;
g_autoptr(GPtrArray) boot_loader_configs = NULL;
if (!_ostree_sysroot_read_boot_loader_configs (self, bootversion, &boot_loader_configs,
cancellable, error))
@ -1120,8 +1081,60 @@ ostree_sysroot_load_if_changed (OstreeSysroot *self,
self->bootversion = bootversion;
self->subbootversion = subbootversion;
self->deployments = deployments;
deployments = NULL; /* Transfer ownership */
self->deployments = g_steal_pointer (&deployments);
return TRUE;
}
/**
* ostree_sysroot_load_if_changed:
* @self: #OstreeSysroot
* @out_changed: (out caller-allocates):
* @cancellable: Cancellable
* @error: Error
*
* Since: 2016.4
*/
gboolean
ostree_sysroot_load_if_changed (OstreeSysroot *self,
gboolean *out_changed,
GCancellable *cancellable,
GError **error)
{
GLNX_AUTO_PREFIX_ERROR ("loading sysroot", error);
if (!ostree_sysroot_initialize (self, error))
return FALSE;
/* Here we also lazily initialize the repository. We didn't do this
* previous to v2017.6, but we do now to support the error-free
* ostree_sysroot_repo() API.
*/
if (!ensure_repo (self, error))
return FALSE;
struct stat stbuf;
if (!glnx_fstatat (self->sysroot_fd, "ostree/deploy", &stbuf, 0, error))
return FALSE;
if (self->loaded_ts.tv_sec == stbuf.st_mtim.tv_sec &&
self->loaded_ts.tv_nsec == stbuf.st_mtim.tv_nsec)
{
if (out_changed)
*out_changed = FALSE;
/* Note early return */
return TRUE;
}
g_clear_pointer (&self->deployments, g_ptr_array_unref);
g_clear_object (&self->booted_deployment);
g_clear_object (&self->staged_deployment);
self->bootversion = -1;
self->subbootversion = -1;
if (!sysroot_load_from_bootloader_configs (self, cancellable, error))
return FALSE;
self->loaded_ts = stbuf.st_mtim;
if (out_changed)

View File

@ -101,9 +101,6 @@ GFile * ostree_sysroot_get_deployment_origin_path (GFile *deployment_path);
_OSTREE_PUBLIC
gboolean ostree_sysroot_lock (OstreeSysroot *self, GError **error);
_OSTREE_PUBLIC
gboolean ostree_sysroot_lock_with_mount_namespace (OstreeSysroot *self, GError **error);
_OSTREE_PUBLIC
gboolean ostree_sysroot_try_lock (OstreeSysroot *self,
gboolean *out_acquired,

View File

@ -43,7 +43,7 @@
*
* Since: 2017.4
*/
#define OSTREE_RELEASE_VERSION (3)
#define OSTREE_RELEASE_VERSION (4)
/**
* OSTREE_VERSION
@ -52,7 +52,7 @@
*
* Since: 2017.4
*/
#define OSTREE_VERSION (2020.3)
#define OSTREE_VERSION (2020.4)
/**
* OSTREE_VERSION_S:
@ -62,7 +62,7 @@
*
* Since: 2017.4
*/
#define OSTREE_VERSION_S "2020.3"
#define OSTREE_VERSION_S "2020.4"
#define OSTREE_ENCODE_VERSION(year,release) \
((year) << 16 | (release))

View File

@ -40,5 +40,6 @@
#include <ostree-repo-finder-mount.h>
#include <ostree-repo-finder-override.h>
#include <ostree-kernel-args.h>
#include <ostree-sign.h>
#include <ostree-autocleanups.h>
#include <ostree-version.h>

View File

@ -109,6 +109,9 @@ static OstreeCommand commands[] = {
{ "rev-parse", OSTREE_BUILTIN_FLAG_NONE,
ostree_builtin_rev_parse,
"Output the target of a rev" },
{ "sign", OSTREE_BUILTIN_FLAG_NONE,
ostree_builtin_sign,
"Sign a commit" },
{ "show", OSTREE_BUILTIN_FLAG_NONE,
ostree_builtin_show,
"Output a metadata object" },

View File

@ -37,6 +37,7 @@ static gboolean opt_retain_pending;
static gboolean opt_retain_rollback;
static gboolean opt_not_as_default;
static gboolean opt_no_prune;
static gboolean opt_no_merge;
static char **opt_kernel_argv;
static char **opt_kernel_argv_append;
static gboolean opt_kernel_proc_cmdline;
@ -48,6 +49,7 @@ static GOptionEntry options[] = {
{ "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Use a different operating system root than the current one", "OSNAME" },
{ "origin-file", 0, 0, G_OPTION_ARG_FILENAME, &opt_origin_path, "Specify origin file", "FILENAME" },
{ "no-prune", 0, 0, G_OPTION_ARG_NONE, &opt_no_prune, "Don't prune the repo when done", NULL},
{ "no-merge", 0, 0, G_OPTION_ARG_NONE, &opt_no_merge, "Do not apply configuration (/etc and kernel arguments) from booted deployment", NULL},
{ "retain", 0, 0, G_OPTION_ARG_NONE, &opt_retain, "Do not delete previous deployments", NULL },
{ "stage", 0, 0, G_OPTION_ARG_NONE, &opt_stage, "Complete deployment at OS shutdown", NULL },
{ "retain-pending", 0, 0, G_OPTION_ARG_NONE, &opt_retain_pending, "Do not delete pending deployments", NULL },
@ -113,7 +115,7 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeCommandInvocation *invocat
return FALSE;
g_autoptr(OstreeDeployment) merge_deployment =
ostree_sysroot_get_merge_deployment (sysroot, opt_osname);
opt_no_merge ? NULL : ostree_sysroot_get_merge_deployment (sysroot, opt_osname);
/* Here we perform cleanup of any leftover data from previous
* partial failures. This avoids having to call

View File

@ -52,39 +52,28 @@ ot_admin_builtin_pin (int argc, char **argv, OstreeCommandInvocation *invocation
return FALSE;
}
unsigned int nsuccess = 0;
for (unsigned int i = 1; i < argc; i++)
{
const char *deploy_index_str = argv[i];
const int deploy_index = atoi (deploy_index_str);
g_autoptr(GError) e = NULL;
g_autoptr(OstreeDeployment) target_deployment = ot_admin_get_indexed_deployment (sysroot, deploy_index, &e);
g_autoptr(OstreeDeployment) target_deployment = ot_admin_get_indexed_deployment (sysroot, deploy_index, error);
if (!target_deployment)
{
g_print ("Invalid deployment %s: %s\n", deploy_index_str, e->message);
continue;
}
return FALSE;
gboolean current_pin = ostree_deployment_is_pinned (target_deployment);
const gboolean desired_pin = !opt_unpin;
if (current_pin == desired_pin)
{
g_print ("Deployment %s is already %s\n", deploy_index_str, current_pin ? "pinned" : "unpinned");
nsuccess++;
}
else
{
g_autoptr(GError) e = NULL;
if (ostree_sysroot_deployment_set_pinned (sysroot, target_deployment, desired_pin, &e))
{
g_print ("Deployment %s is now %s\n", deploy_index_str, desired_pin ? "pinned" : "unpinned");
nsuccess++;
}
else
g_print ("Failed to %s deployment %s: %s\n", desired_pin ? "pin" : "unpin", deploy_index_str, e->message);
if (!ostree_sysroot_deployment_set_pinned (sysroot, target_deployment, desired_pin, error))
return FALSE;
g_print ("Deployment %s is now %s\n", deploy_index_str, desired_pin ? "pinned" : "unpinned");
}
}
return nsuccess > 0;
return TRUE;
}

View File

@ -87,7 +87,7 @@ static GOptionEntry options[] = {
{ "force-copy-zerosized", 'z', 0, G_OPTION_ARG_NONE, &opt_force_copy_zerosized, "Do not hardlink zero-sized files", NULL },
{ "force-copy", 'C', 0, G_OPTION_ARG_NONE, &opt_force_copy, "Never hardlink (but may reflink if available)", NULL },
{ "bareuseronly-dirs", 'M', 0, G_OPTION_ARG_NONE, &opt_bareuseronly_dirs, "Suppress mode bits outside of 0775 for directories (suid, world writable, etc.)", NULL },
{ "skip-list", 0, 0, G_OPTION_ARG_FILENAME, &opt_skiplist_file, "File containing list of files to skip", "PATH" },
{ "skip-list", 0, 0, G_OPTION_ARG_FILENAME, &opt_skiplist_file, "File containing list of files to skip", "FILE" },
{ "selinux-policy", 0, 0, G_OPTION_ARG_FILENAME, &opt_selinux_policy, "Set SELinux labels based on policy in root filesystem PATH (may be /); implies --force-copy", "PATH" },
{ "selinux-prefix", 0, 0, G_OPTION_ARG_STRING, &opt_selinux_prefix, "When setting SELinux labels, prefix all paths by PREFIX", "PREFIX" },
{ NULL }

View File

@ -31,6 +31,7 @@
#include "parse-datetime.h"
#include "ostree-repo-private.h"
#include "ostree-libarchive-private.h"
#include "ostree-sign.h"
static char *opt_subject;
static char *opt_body;
@ -53,17 +54,22 @@ static gboolean opt_tar_autocreate_parents;
static char *opt_tar_pathname_filter;
static gboolean opt_no_xattrs;
static char *opt_selinux_policy;
static gboolean opt_selinux_policy_from_base;
static gboolean opt_canonical_permissions;
static gboolean opt_ro_executables;
static gboolean opt_consume;
static gboolean opt_devino_canonical;
static char *opt_base;
static char **opt_trees;
static gint opt_owner_uid = -1;
static gint opt_owner_gid = -1;
static gboolean opt_table_output;
#ifndef OSTREE_DISABLE_GPGME
static char **opt_key_ids;
static char **opt_gpg_key_ids;
static char *opt_gpg_homedir;
#endif
static char **opt_key_ids;
static char *opt_sign_name;
static gboolean opt_generate_sizes;
static gboolean opt_disable_fsync;
static char *opt_timestamp;
@ -97,6 +103,7 @@ static GOptionEntry options[] = {
{ "orphan", 0, 0, G_OPTION_ARG_NONE, &opt_orphan, "Create a commit without writing a ref", NULL },
{ "no-bindings", 0, 0, G_OPTION_ARG_NONE, &opt_no_bindings, "Do not write any ref bindings", NULL },
{ "bind-ref", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_bind_refs, "Add a ref to ref binding commit metadata", "BRANCH" },
{ "base", 0, 0, G_OPTION_ARG_STRING, &opt_base, "Start from the given commit as a base (no modifiers apply)", "REF" },
{ "tree", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_trees, "Overlay the given argument as a tree", "dir=PATH or tar=TARFILE or ref=COMMIT" },
{ "add-metadata-string", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_metadata_strings, "Add a key/value pair to metadata", "KEY=VALUE" },
{ "add-metadata", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_metadata_variants, "Add a key/value pair to metadata, where the KEY is a string, an VALUE is g_variant_parse() formatted", "KEY=VALUE" },
@ -105,8 +112,10 @@ static GOptionEntry options[] = {
{ "owner-uid", 0, 0, G_OPTION_ARG_INT, &opt_owner_uid, "Set file ownership user id", "UID" },
{ "owner-gid", 0, 0, G_OPTION_ARG_INT, &opt_owner_gid, "Set file ownership group id", "GID" },
{ "canonical-permissions", 0, 0, G_OPTION_ARG_NONE, &opt_canonical_permissions, "Canonicalize permissions in the same way bare-user does for hardlinked files", NULL },
{ "mode-ro-executables", 0, 0, G_OPTION_ARG_NONE, &opt_ro_executables, "Ensure executable files are not writable", NULL },
{ "no-xattrs", 0, 0, G_OPTION_ARG_NONE, &opt_no_xattrs, "Do not import extended attributes", NULL },
{ "selinux-policy", 0, 0, G_OPTION_ARG_FILENAME, &opt_selinux_policy, "Set SELinux labels based on policy in root filesystem PATH (may be /)", "PATH" },
{ "selinux-policy-from-base", 'P', 0, G_OPTION_ARG_NONE, &opt_selinux_policy_from_base, "Set SELinux labels based on first --tree argument", NULL },
{ "link-checkout-speedup", 0, 0, G_OPTION_ARG_NONE, &opt_link_checkout_speedup, "Optimize for commits of trees composed of hardlinks into the repository", NULL },
{ "devino-canonical", 'I', 0, G_OPTION_ARG_NONE, &opt_devino_canonical, "Assume hardlinked objects are unmodified. Implies --link-checkout-speedup", NULL },
{ "tar-autocreate-parents", 0, 0, G_OPTION_ARG_NONE, &opt_tar_autocreate_parents, "When loading tar archives, automatically create parent directories as needed", NULL },
@ -117,9 +126,11 @@ static GOptionEntry options[] = {
{ "consume", 0, 0, G_OPTION_ARG_NONE, &opt_consume, "Consume (delete) content after commit (for local directories)", NULL },
{ "table-output", 0, 0, G_OPTION_ARG_NONE, &opt_table_output, "Output more information in a KEY: VALUE format", NULL },
#ifndef OSTREE_DISABLE_GPGME
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "GPG Key ID to sign the commit with", "KEY-ID"},
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_gpg_key_ids, "GPG Key ID to sign the commit with", "KEY-ID"},
{ "gpg-homedir", 0, 0, G_OPTION_ARG_FILENAME, &opt_gpg_homedir, "GPG Homedir to use when looking for keyrings", "HOMEDIR"},
#endif
{ "sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "Sign the commit with", "KEY_ID"},
{ "sign-type", 0, 0, G_OPTION_ARG_STRING, &opt_sign_name, "Signature type to use (defaults to 'ed25519')", "NAME"},
{ "generate-sizes", 0, 0, G_OPTION_ARG_NONE, &opt_generate_sizes, "Generate size information along with commit metadata", NULL },
{ "disable-fsync", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_disable_fsync, "Do not invoke fsync()", NULL },
{ "fsync", 0, 0, G_OPTION_ARG_CALLBACK, parse_fsync_cb, "Specify how to invoke fsync()", "POLICY" },
@ -185,13 +196,19 @@ commit_filter (OstreeRepo *self,
g_file_info_set_attribute_uint32 (file_info, "unix::uid", opt_owner_uid);
if (opt_owner_gid >= 0)
g_file_info_set_attribute_uint32 (file_info, "unix::gid", opt_owner_gid);
guint mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
if (S_ISREG (mode) && opt_ro_executables && (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
{
mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
g_file_info_set_attribute_uint32 (file_info, "unix::mode", mode);
}
if (mode_adds && g_hash_table_lookup_extended (mode_adds, path, NULL, &value))
{
guint current_mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
guint mode_add = GPOINTER_TO_UINT (value);
g_file_info_set_attribute_uint32 (file_info, "unix::mode",
current_mode | mode_add);
mode | mode_add);
g_hash_table_remove (mode_adds, path);
}
else if (mode_overrides && g_hash_table_lookup_extended (mode_overrides, path, NULL, &value))
@ -417,6 +434,7 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio
OstreeRepoTransactionStats stats;
struct CommitFilterData filter_data = { 0, };
g_autofree char *commit_body = NULL;
g_autoptr (OstreeSign) sign = NULL;
context = g_option_context_new ("[PATH]");
@ -550,6 +568,11 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio
flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES;
if (opt_disable_fsync)
ostree_repo_set_disable_fsync (repo, TRUE);
if (opt_selinux_policy && opt_selinux_policy_from_base)
{
glnx_throw (error, "Cannot specify both --selinux-policy and --selinux-policy-from-base");
goto out;
}
if (flags != 0
|| opt_owner_uid >= 0
@ -557,25 +580,14 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio
|| opt_statoverride_file != NULL
|| opt_skiplist_file != NULL
|| opt_no_xattrs
|| opt_selinux_policy)
|| opt_ro_executables
|| opt_selinux_policy
|| opt_selinux_policy_from_base)
{
filter_data.mode_adds = mode_adds;
filter_data.skip_list = skip_list;
modifier = ostree_repo_commit_modifier_new (flags, commit_filter,
&filter_data, NULL);
if (opt_selinux_policy)
{
glnx_autofd int rootfs_dfd = -1;
if (!glnx_opendirat (AT_FDCWD, opt_selinux_policy, TRUE, &rootfs_dfd, error))
{
g_prefix_error (error, "selinux-policy: ");
goto out;
}
policy = ostree_sepolicy_new_at (rootfs_dfd, cancellable, error);
if (!policy)
goto out;
ostree_repo_commit_modifier_set_sepolicy (modifier, policy);
}
}
if (opt_editor)
@ -599,129 +611,180 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio
if (opt_link_checkout_speedup && !ostree_repo_scan_hardlinks (repo, cancellable, error))
goto out;
mtree = ostree_mutable_tree_new ();
if (argc <= 1 && (opt_trees == NULL || opt_trees[0] == NULL))
if (opt_base)
{
if (!ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, ".", mtree, modifier,
cancellable, error))
g_autofree char *base_commit = NULL;
g_autoptr(GFile) root = NULL;
if (!ostree_repo_read_commit (repo, opt_base, &root, &base_commit, cancellable, error))
goto out;
}
else if (opt_trees != NULL)
{
const char *const*tree_iter;
const char *tree;
const char *eq;
OstreeRepoFile *rootf = (OstreeRepoFile*) root;
for (tree_iter = (const char *const*)opt_trees; *tree_iter; tree_iter++)
mtree = ostree_mutable_tree_new_from_checksum (repo,
ostree_repo_file_tree_get_contents_checksum (rootf),
ostree_repo_file_tree_get_metadata_checksum (rootf));
if (opt_selinux_policy_from_base)
{
tree = *tree_iter;
eq = strchr (tree, '=');
if (!eq)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Missing type in tree specification '%s'", tree);
goto out;
}
g_free (tree_type);
tree_type = g_strndup (tree, eq - tree);
tree = eq + 1;
g_clear_object (&object_to_commit);
if (strcmp (tree_type, "dir") == 0)
{
if (!ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, tree, mtree, modifier,
cancellable, error))
goto out;
}
else if (strcmp (tree_type, "tar") == 0)
{
if (!opt_tar_pathname_filter)
{
if (strcmp (tree, "-") == 0)
{
if (!ostree_repo_write_archive_to_mtree_from_fd (repo, STDIN_FILENO, mtree, modifier,
opt_tar_autocreate_parents,
cancellable, error))
goto out;
}
else
{
object_to_commit = g_file_new_for_path (tree);
if (!ostree_repo_write_archive_to_mtree (repo, object_to_commit, mtree, modifier,
opt_tar_autocreate_parents,
cancellable, error))
goto out;
}
}
else
{
#ifdef HAVE_LIBARCHIVE
const char *comma = strchr (opt_tar_pathname_filter, ',');
if (!comma)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Missing ',' in --tar-pathname-filter");
goto out;
}
const char *replacement = comma + 1;
g_autofree char *regexp_text = g_strndup (opt_tar_pathname_filter, comma - opt_tar_pathname_filter);
/* Use new API if we have a pathname filter */
OstreeRepoImportArchiveOptions opts = { 0, };
opts.autocreate_parents = opt_tar_autocreate_parents;
opts.translate_pathname = handle_translate_pathname;
g_autoptr(GRegex) regexp = g_regex_new (regexp_text, 0, 0, error);
TranslatePathnameData tpdata = { regexp, replacement };
if (!regexp)
{
g_prefix_error (error, "--tar-pathname-filter: ");
goto out;
}
opts.translate_pathname_user_data = &tpdata;
g_autoptr(OtAutoArchiveRead) archive;
if (strcmp (tree, "-") == 0)
archive = ot_open_archive_read_fd (STDIN_FILENO, error);
else
archive = ot_open_archive_read (tree, error);
if (!archive)
goto out;
if (!ostree_repo_import_archive_to_mtree (repo, &opts, archive, mtree,
modifier, cancellable, error))
goto out;
#else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"This version of ostree is not compiled with libarchive support");
goto out;
#endif
}
}
else if (strcmp (tree_type, "ref") == 0)
{
if (!ostree_repo_read_commit (repo, tree, &object_to_commit, NULL, cancellable, error))
goto out;
if (!ostree_repo_write_directory_to_mtree (repo, object_to_commit, mtree, modifier,
cancellable, error))
goto out;
}
else
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid tree type specification '%s'", tree_type);
goto out;
}
g_assert (modifier);
if (!ostree_repo_commit_modifier_set_sepolicy_from_commit (modifier, repo, base_commit, cancellable, error))
goto out;
/* Don't try to handle it twice */
opt_selinux_policy_from_base = FALSE;
}
}
else
{
g_assert (argc > 1);
if (!ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, argv[1], mtree, modifier,
cancellable, error))
goto out;
mtree = ostree_mutable_tree_new ();
}
/* Convert implicit . or explicit path via argv into
* --tree=dir= so that we only have one primary code path below.
*/
if (opt_trees == NULL || opt_trees[0] == NULL)
{
char *path;
if (argc <= 1)
path = ".";
else
path = argv[1];
opt_trees = g_new0 (char *, 2);
opt_trees[0] = g_strconcat ("dir=", path, NULL);
}
const char *const*tree_iter;
const char *tree;
const char *eq;
g_assert (opt_trees && *opt_trees);
for (tree_iter = (const char *const*)opt_trees; *tree_iter; tree_iter++)
{
const gboolean first = (tree_iter == (const char *const*)opt_trees);
tree = *tree_iter;
eq = strchr (tree, '=');
if (!eq)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Missing type in tree specification '%s'", tree);
goto out;
}
g_free (tree_type);
tree_type = g_strndup (tree, eq - tree);
tree = eq + 1;
g_clear_object (&object_to_commit);
if (strcmp (tree_type, "dir") == 0)
{
if (first && opt_selinux_policy_from_base)
{
opt_selinux_policy = g_strdup (tree);
opt_selinux_policy_from_base = FALSE;
}
if (first && opt_selinux_policy)
{
g_assert (modifier);
glnx_autofd int rootfs_dfd = -1;
if (!glnx_opendirat (AT_FDCWD, opt_selinux_policy, TRUE, &rootfs_dfd, error))
goto out;
policy = ostree_sepolicy_new_at (rootfs_dfd, cancellable, error);
if (!policy)
goto out;
ostree_repo_commit_modifier_set_sepolicy (modifier, policy);
}
if (!ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, tree, mtree, modifier,
cancellable, error))
goto out;
}
else if (strcmp (tree_type, "tar") == 0)
{
if (first && opt_selinux_policy_from_base)
{
glnx_throw (error, "Cannot use --selinux-policy-from-base with tar");
goto out;
}
if (!opt_tar_pathname_filter)
{
if (strcmp (tree, "-") == 0)
{
if (!ostree_repo_write_archive_to_mtree_from_fd (repo, STDIN_FILENO, mtree, modifier,
opt_tar_autocreate_parents,
cancellable, error))
goto out;
}
else
{
object_to_commit = g_file_new_for_path (tree);
if (!ostree_repo_write_archive_to_mtree (repo, object_to_commit, mtree, modifier,
opt_tar_autocreate_parents,
cancellable, error))
goto out;
}
}
else
{
#ifdef HAVE_LIBARCHIVE
const char *comma = strchr (opt_tar_pathname_filter, ',');
if (!comma)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Missing ',' in --tar-pathname-filter");
goto out;
}
const char *replacement = comma + 1;
g_autofree char *regexp_text = g_strndup (opt_tar_pathname_filter, comma - opt_tar_pathname_filter);
/* Use new API if we have a pathname filter */
OstreeRepoImportArchiveOptions opts = { 0, };
opts.autocreate_parents = opt_tar_autocreate_parents;
opts.translate_pathname = handle_translate_pathname;
g_autoptr(GRegex) regexp = g_regex_new (regexp_text, 0, 0, error);
TranslatePathnameData tpdata = { regexp, replacement };
if (!regexp)
{
g_prefix_error (error, "--tar-pathname-filter: ");
goto out;
}
opts.translate_pathname_user_data = &tpdata;
g_autoptr(OtAutoArchiveRead) archive;
if (strcmp (tree, "-") == 0)
archive = ot_open_archive_read_fd (STDIN_FILENO, error);
else
archive = ot_open_archive_read (tree, error);
if (!archive)
goto out;
if (!ostree_repo_import_archive_to_mtree (repo, &opts, archive, mtree,
modifier, cancellable, error))
goto out;
#else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"This version of ostree is not compiled with libarchive support");
goto out;
#endif
}
}
else if (strcmp (tree_type, "ref") == 0)
{
if (first && opt_selinux_policy_from_base)
{
g_assert (modifier);
if (!ostree_repo_commit_modifier_set_sepolicy_from_commit (modifier, repo, tree, cancellable, error))
goto out;
}
if (!ostree_repo_read_commit (repo, tree, &object_to_commit, NULL, cancellable, error))
goto out;
if (!ostree_repo_write_directory_to_mtree (repo, object_to_commit, mtree, modifier,
cancellable, error))
goto out;
}
else
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid tree type specification '%s'", tree_type);
goto out;
}
}
if (mode_adds && g_hash_table_size (mode_adds) > 0)
@ -811,12 +874,41 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio
goto out;
}
#ifndef OSTREE_DISABLE_GPGME
if (opt_key_ids)
{
/* Initialize crypto system */
opt_sign_name = opt_sign_name ?: OSTREE_SIGN_NAME_ED25519;
sign = ostree_sign_get_by_name (opt_sign_name, error);
if (sign == NULL)
goto out;
char **iter;
for (iter = opt_key_ids; iter && *iter; iter++)
{
const char *keyid = *iter;
g_autoptr (GVariant) secret_key = NULL;
secret_key = g_variant_new_string (keyid);
if (!ostree_sign_set_sk (sign, secret_key, error))
goto out;
if (!ostree_sign_commit (sign,
repo,
commit_checksum,
cancellable,
error))
goto out;
}
}
#ifndef OSTREE_DISABLE_GPGME
if (opt_gpg_key_ids)
{
char **iter;
for (iter = opt_gpg_key_ids; iter && *iter; iter++)
{
const char *keyid = *iter;

View File

@ -142,7 +142,7 @@ ostree_builtin_diff (int argc, char **argv, OstreeCommandInvocation *invocation,
g_autoptr(GPtrArray) removed = NULL;
g_autoptr(GPtrArray) added = NULL;
context = g_option_context_new ("REV TARGETDIR");
context = g_option_context_new ("REV_OR_DIR REV_OR_DIR");
if (!ostree_option_context_parse (context, options, &argc, &argv, invocation, &repo, cancellable, error))
goto out;

View File

@ -35,6 +35,7 @@ static gchar *opt_cache_dir = NULL;
static gchar *opt_finders = NULL;
static gboolean opt_disable_fsync = FALSE;
static gboolean opt_pull = FALSE;
static gboolean opt_mirror = FALSE;
static GOptionEntry options[] =
{
@ -42,6 +43,7 @@ static GOptionEntry options[] =
{ "disable-fsync", 0, 0, G_OPTION_ARG_NONE, &opt_disable_fsync, "Do not invoke fsync()", NULL },
{ "finders", 0, 0, G_OPTION_ARG_STRING, &opt_finders, "Use the specified comma separated list of finders (e.g. config,lan,mount)", "FINDERS" },
{ "pull", 0, 0, G_OPTION_ARG_NONE, &opt_pull, "Pull the updates after finding them", NULL },
{ "mirror", 0, 0, G_OPTION_ARG_NONE, &opt_mirror, "Do a mirror pull (see ostree pull --mirror)", NULL},
{ NULL }
};
@ -188,6 +190,7 @@ ostree_builtin_find_remotes (int argc,
g_auto(OstreeRepoFinderResultv) results = NULL;
g_auto(GLnxConsoleRef) console = { 0, };
g_autoptr(GHashTable) refs_found = NULL; /* set (element-type OstreeCollectionRef) */
g_autoptr(GVariant) pull_options = NULL;
context = g_option_context_new ("COLLECTION-ID REF [COLLECTION-ID REF...]");
@ -210,6 +213,12 @@ ostree_builtin_find_remotes (int argc,
return FALSE;
}
if (opt_mirror && !opt_pull)
{
ot_util_usage_error (context, "When --mirror is specified, --pull must also be", error);
return FALSE;
}
if (opt_disable_fsync)
ostree_repo_set_disable_fsync (repo, TRUE);
@ -359,13 +368,24 @@ ostree_builtin_find_remotes (int argc,
if (!opt_pull)
return TRUE;
{
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
if (opt_mirror)
g_variant_builder_add (&builder, "{s@v}", "flags",
g_variant_new_variant (g_variant_new_int32 (OSTREE_REPO_PULL_FLAGS_MIRROR)));
pull_options = g_variant_ref_sink (g_variant_builder_end (&builder));
}
/* Run the pull operation. */
if (console.is_tty)
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);
ostree_repo_pull_from_remotes_async (repo,
(const OstreeRepoFinderResult * const *) results,
NULL, /* no options */
pull_options,
progress, cancellable,
get_result_cb, &pull_result);

View File

@ -34,6 +34,7 @@
static char *opt_remote;
static gboolean opt_commit_only;
static gboolean opt_disable_fsync;
static gboolean opt_per_object_fsync;
static gboolean opt_untrusted;
static gboolean opt_bareuseronly_files;
static gboolean opt_require_static_deltas;
@ -50,6 +51,7 @@ static GOptionEntry options[] = {
{ "commit-metadata-only", 0, 0, G_OPTION_ARG_NONE, &opt_commit_only, "Fetch only the commit metadata", NULL },
{ "remote", 0, 0, G_OPTION_ARG_STRING, &opt_remote, "Add REMOTE to refspec", "REMOTE" },
{ "disable-fsync", 0, 0, G_OPTION_ARG_NONE, &opt_disable_fsync, "Do not invoke fsync()", NULL },
{ "per-object-fsync", 0, 0, G_OPTION_ARG_NONE, &opt_per_object_fsync, "Perform writes in such a way that avoids stalling concurrent processes", NULL },
{ "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Verify checksums of local sources (always enabled for HTTP pulls)", NULL },
{ "bareuseronly-files", 0, 0, G_OPTION_ARG_NONE, &opt_bareuseronly_files, "Reject regular files with mode outside of 0775 (world writable, suid, etc.)", NULL },
{ "require-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_require_static_deltas, "Require static deltas", NULL },
@ -181,6 +183,16 @@ ostree_builtin_pull_local (int argc, char **argv, OstreeCommandInvocation *invoc
g_variant_new_variant (g_variant_new_boolean (TRUE)));
g_variant_builder_add (&builder, "{s@v}", "depth",
g_variant_new_variant (g_variant_new_int32 (opt_depth)));
/* local pulls always disable signapi verification. If you don't want this, use
* ostree remote add --sign-verify=<key> file://
*/
g_variant_builder_add (&builder, "{s@v}", "disable-sign-verify",
g_variant_new_variant (g_variant_new_boolean (TRUE)));
g_variant_builder_add (&builder, "{s@v}", "disable-sign-verify-summary",
g_variant_new_variant (g_variant_new_boolean (TRUE)));
if (opt_per_object_fsync)
g_variant_builder_add (&builder, "{s@v}", "per-object-fsync",
g_variant_new_variant (g_variant_new_boolean (TRUE)));
if (console.is_tty)
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);

View File

@ -29,6 +29,7 @@
#include "otutil.h"
static gboolean opt_disable_fsync;
static gboolean opt_per_object_fsync;
static gboolean opt_mirror;
static gboolean opt_commit_only;
static gboolean opt_dry_run;
@ -37,6 +38,7 @@ static gboolean opt_require_static_deltas;
static gboolean opt_untrusted;
static gboolean opt_http_trusted;
static gboolean opt_timestamp_check;
static char* opt_timestamp_check_from_rev;
static gboolean opt_bareuseronly_files;
static char** opt_subpaths;
static char** opt_http_headers;
@ -57,6 +59,7 @@ static GOptionEntry options[] = {
{ "commit-metadata-only", 0, 0, G_OPTION_ARG_NONE, &opt_commit_only, "Fetch only the commit metadata", NULL },
{ "cache-dir", 0, 0, G_OPTION_ARG_FILENAME, &opt_cache_dir, "Use custom cache dir", NULL },
{ "disable-fsync", 0, 0, G_OPTION_ARG_NONE, &opt_disable_fsync, "Do not invoke fsync()", NULL },
{ "per-object-fsync", 0, 0, G_OPTION_ARG_NONE, &opt_per_object_fsync, "Perform writes in such a way that avoids stalling concurrent processes", NULL },
{ "disable-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_disable_static_deltas, "Do not use static deltas", NULL },
{ "require-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_require_static_deltas, "Require static deltas", NULL },
{ "mirror", 0, 0, G_OPTION_ARG_NONE, &opt_mirror, "Write refs suitable for a mirror and fetches all refs if none provided", NULL },
@ -72,6 +75,7 @@ static GOptionEntry options[] = {
{ "network-retries", 0, 0, G_OPTION_ARG_INT, &opt_network_retries, "Specifies how many times each download should be retried upon error (default: 5)", "N"},
{ "localcache-repo", 'L', 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_localcache_repos, "Add REPO as local cache source for objects during this pull", "REPO" },
{ "timestamp-check", 'T', 0, G_OPTION_ARG_NONE, &opt_timestamp_check, "Require fetched commits to have newer timestamps", NULL },
{ "timestamp-check-from-rev", 0, 0, G_OPTION_ARG_STRING, &opt_timestamp_check_from_rev, "Require fetched commits to have newer timestamps than given rev", NULL },
/* let's leave this hidden for now; we just need it for tests */
{ "append-user-agent", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_append_user_agent, "Append string to user agent", NULL },
{ NULL }
@ -313,6 +317,9 @@ ostree_builtin_pull (int argc, char **argv, OstreeCommandInvocation *invocation,
if (opt_timestamp_check)
g_variant_builder_add (&builder, "{s@v}", "timestamp-check",
g_variant_new_variant (g_variant_new_boolean (opt_timestamp_check)));
if (opt_timestamp_check_from_rev)
g_variant_builder_add (&builder, "{s@v}", "timestamp-check-from-rev",
g_variant_new_variant (g_variant_new_string (opt_timestamp_check_from_rev)));
if (override_commit_ids)
g_variant_builder_add (&builder, "{s@v}", "override-commit-ids",
@ -320,7 +327,9 @@ ostree_builtin_pull (int argc, char **argv, OstreeCommandInvocation *invocation,
if (opt_localcache_repos)
g_variant_builder_add (&builder, "{s@v}", "localcache-repos",
g_variant_new_variant (g_variant_new_strv ((const char*const*)opt_localcache_repos, -1)));
if (opt_per_object_fsync)
g_variant_builder_add (&builder, "{s@v}", "per-object-fsync",
g_variant_new_variant (g_variant_new_boolean (TRUE)));
if (opt_http_headers)
{
GVariantBuilder hdr_builder;

View File

@ -0,0 +1,264 @@
/* vim:set et sw=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e2s: */
/*
* Copyright (C) 2015 Colin Walters <walters@verbum.org>
* Copyright (C) 2019 Denis Pynkin (d4s) <denis.pynkin@collabora.com>
*
* SPDX-License-Identifier: LGPL-2.0+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Colin Walters <walters@verbum.org>
*/
#include "config.h"
#include "ot-main.h"
#include "ot-builtins.h"
#include "ostree.h"
#include "otutil.h"
#include "ostree-core-private.h"
#include "ostree-sign.h"
static gboolean opt_delete;
static gboolean opt_verify;
static char *opt_sign_name;
static char *opt_filename;
static char *opt_keysdir;
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-sign.xml) when changing the option list.
*/
static GOptionEntry options[] = {
{ "delete", 'd', 0, G_OPTION_ARG_NONE, &opt_delete, "Delete signatures having any of the KEY-IDs", NULL},
{ "verify", 0, 0, G_OPTION_ARG_NONE, &opt_verify, "Verify signatures", NULL},
{ "sign-type", 's', 0, G_OPTION_ARG_STRING, &opt_sign_name, "Signature type to use (defaults to 'ed25519')", "NAME"},
#if defined(HAVE_LIBSODIUM)
{ "keys-file", 0, 0, G_OPTION_ARG_STRING, &opt_filename, "Read key(s) from file", "NAME"},
{ "keys-dir", 0, 0, G_OPTION_ARG_STRING, &opt_keysdir, "Redefine system-wide directories with public and revoked keys for verification", "NAME"},
#endif
{ NULL }
};
static void
usage_error (GOptionContext *context, const char *message, GError **error)
{
g_autofree char *help = g_option_context_get_help (context, TRUE, NULL);
g_printerr ("%s", help);
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, message);
}
gboolean
ostree_builtin_sign (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
g_autoptr (GOptionContext) context = NULL;
g_autoptr (OstreeRepo) repo = NULL;
g_autoptr (OstreeSign) sign = NULL;
g_autofree char *resolved_commit = NULL;
g_autofree char *success_message = NULL;
const char *commit;
char **key_ids;
int n_key_ids, ii;
gboolean ret = FALSE;
context = g_option_context_new ("COMMIT KEY-ID...");
if (!ostree_option_context_parse (context, options, &argc, &argv, invocation, &repo, cancellable, error))
goto out;
if (argc < 2)
{
usage_error (context, "Need a COMMIT to sign or verify", error);
goto out;
}
commit = argv[1];
/* Verification could be done via system files with public keys */
if (!opt_verify &&
!opt_filename &&
argc < 3)
{
usage_error (context, "Need at least one KEY-ID to sign with", error);
goto out;
}
key_ids = argv + 2;
n_key_ids = argc - 2;
if (!ostree_repo_resolve_rev (repo, commit, FALSE, &resolved_commit, error))
goto out;
/* Initialize crypto system */
opt_sign_name = opt_sign_name ?: OSTREE_SIGN_NAME_ED25519;
sign = ostree_sign_get_by_name (opt_sign_name, error);
if (sign == NULL)
goto out;
for (ii = 0; ii < n_key_ids; ii++)
{
g_autoptr (GVariant) sk = NULL;
g_autoptr (GVariant) pk = NULL;
if (opt_verify)
{
g_autoptr (GError) local_error = NULL;
// Pass the key as a string
pk = g_variant_new_string(key_ids[ii]);
if (!ostree_sign_set_pk (sign, pk, &local_error))
continue;
if (ostree_sign_commit_verify (sign,
repo,
resolved_commit,
&success_message,
cancellable,
&local_error))
{
g_assert (success_message);
g_print ("%s\n", success_message);
ret = TRUE;
goto out;
}
}
else
{
// Pass the key as a string
sk = g_variant_new_string(key_ids[ii]);
if (!ostree_sign_set_sk (sign, sk, error))
{
ret = FALSE;
goto out;
}
ret = ostree_sign_commit (sign,
repo,
resolved_commit,
cancellable,
error);
if (ret != TRUE)
goto out;
}
}
/* Try to verify with user-provided file or system configuration */
if (opt_verify)
{
if ((n_key_ids == 0) || opt_filename)
{
g_autoptr (GVariantBuilder) builder = NULL;
g_autoptr (GVariant) options = NULL;
builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
/* Use custom directory with public and revoked keys instead of system-wide directories */
if (opt_keysdir)
g_variant_builder_add (builder, "{sv}", "basedir", g_variant_new_string (opt_keysdir));
/* The last chance for verification source -- system files */
if (opt_filename)
g_variant_builder_add (builder, "{sv}", "filename", g_variant_new_string (opt_filename));
options = g_variant_builder_end (builder);
if (!ostree_sign_load_pk (sign, options, error))
goto out;
if (ostree_sign_commit_verify (sign,
repo,
resolved_commit,
&success_message,
cancellable,
error))
{
g_print ("%s\n", success_message);
ret = TRUE;
}
} /* Check via file */
}
else
{
/* Sign with keys from provided file */
if (opt_filename)
{
g_autoptr (GFile) keyfile = NULL;
g_autoptr (GFileInputStream) key_stream_in = NULL;
g_autoptr (GDataInputStream) key_data_in = NULL;
if (!g_file_test (opt_filename, G_FILE_TEST_IS_REGULAR))
{
g_warning ("Can't open file '%s' with keys", opt_filename);
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"File object '%s' is not a regular file", opt_filename);
goto out;
}
keyfile = g_file_new_for_path (opt_filename);
key_stream_in = g_file_read (keyfile, NULL, error);
if (key_stream_in == NULL)
goto out;
key_data_in = g_data_input_stream_new (G_INPUT_STREAM(key_stream_in));
g_assert (key_data_in != NULL);
/* Use simple file format with just a list of base64 public keys per line */
while (TRUE)
{
gsize len = 0;
g_autofree char *line = g_data_input_stream_read_line (key_data_in, &len, NULL, error);
g_autoptr (GVariant) sk = NULL;
if (*error != NULL)
goto out;
if (line == NULL)
break;
// Pass the key as a string
sk = g_variant_new_string(line);
if (!ostree_sign_set_sk (sign, sk, error))
{
ret = FALSE;
goto out;
}
ret = ostree_sign_commit (sign,
repo,
resolved_commit,
cancellable,
error);
if (ret != TRUE)
goto out;
}
}
}
// No valid signature found
if (opt_verify && (ret != TRUE) && (*error == NULL))
g_set_error_literal (error,
G_IO_ERROR, G_IO_ERROR_FAILED,
"No valid signatures found");
out:
/* It is possible to have an error due multiple signatures check */
if (ret == TRUE)
g_clear_error (error);
return ret;
}

View File

@ -27,10 +27,13 @@
#include "ot-builtins.h"
#include "ostree.h"
#include "otutil.h"
#include "ostree-sign.h"
static gboolean opt_update, opt_view, opt_raw;
static char **opt_key_ids;
static char **opt_gpg_key_ids;
static char *opt_gpg_homedir;
static char **opt_key_ids;
static char *opt_sign_name;
static char **opt_metadata;
/* ATTENTION:
@ -42,8 +45,10 @@ static GOptionEntry options[] = {
{ "update", 'u', 0, G_OPTION_ARG_NONE, &opt_update, "Update the summary", NULL },
{ "view", 'v', 0, G_OPTION_ARG_NONE, &opt_view, "View the local summary file", NULL },
{ "raw", 0, 0, G_OPTION_ARG_NONE, &opt_raw, "View the raw bytes of the summary file", NULL },
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "GPG Key ID to sign the summary with", "KEY-ID"},
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_gpg_key_ids, "GPG Key ID to sign the summary with", "KEY-ID"},
{ "gpg-homedir", 0, 0, G_OPTION_ARG_FILENAME, &opt_gpg_homedir, "GPG Homedir to use when looking for keyrings", "HOMEDIR"},
{ "sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "Key ID to sign the summary with", "KEY-ID"},
{ "sign-type", 0, 0, G_OPTION_ARG_STRING, &opt_sign_name, "Signature type to use (defaults to 'ed25519')", "NAME"},
{ "add-metadata", 'm', 0, G_OPTION_ARG_STRING_ARRAY, &opt_metadata, "Additional metadata field to add to the summary", "KEY=VALUE" },
{ NULL }
};
@ -87,6 +92,7 @@ ostree_builtin_summary (int argc, char **argv, OstreeCommandInvocation *invocati
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(OstreeRepo) repo = NULL;
g_autoptr (OstreeSign) sign = NULL;
OstreeDumpFlags flags = OSTREE_DUMP_NONE;
context = g_option_context_new ("");
@ -94,6 +100,16 @@ ostree_builtin_summary (int argc, char **argv, OstreeCommandInvocation *invocati
if (!ostree_option_context_parse (context, options, &argc, &argv, invocation, &repo, cancellable, error))
return FALSE;
/* Initialize crypto system */
if (opt_key_ids)
{
opt_sign_name = opt_sign_name ?: OSTREE_SIGN_NAME_ED25519;
sign = ostree_sign_get_by_name (opt_sign_name, error);
if (sign == NULL)
return FALSE;
}
if (opt_update)
{
g_autoptr(GVariant) additional_metadata = NULL;
@ -164,10 +180,9 @@ ostree_builtin_summary (int argc, char **argv, OstreeCommandInvocation *invocati
new_summary_commit, repo_file, &new_ostree_metadata_checksum,
NULL, error))
return FALSE;
if (opt_key_ids != NULL)
if (opt_gpg_key_ids != NULL)
{
for (const char * const *iter = (const char * const *) opt_key_ids;
for (const char * const *iter = (const char * const *) opt_gpg_key_ids;
iter != NULL && *iter != NULL; iter++)
{
const char *key_id = *iter;
@ -182,6 +197,27 @@ ostree_builtin_summary (int argc, char **argv, OstreeCommandInvocation *invocati
}
}
if (opt_key_ids)
{
char **iter;
for (iter = opt_key_ids; iter && *iter; iter++)
{
const char *keyid = *iter;
g_autoptr (GVariant) secret_key = NULL;
secret_key = g_variant_new_string (keyid);
if (!ostree_sign_set_sk (sign, secret_key, error))
return FALSE;
if (!ostree_sign_commit (sign,
repo,
new_ostree_metadata_checksum,
cancellable,
error))
return FALSE;
}
}
ostree_repo_transaction_set_collection_ref (repo, &collection_ref,
new_ostree_metadata_checksum);
@ -194,16 +230,45 @@ ostree_builtin_summary (int argc, char **argv, OstreeCommandInvocation *invocati
return FALSE;
#ifndef OSTREE_DISABLE_GPGME
if (opt_key_ids)
if (opt_gpg_key_ids)
{
if (!ostree_repo_add_gpg_signature_summary (repo,
(const gchar **) opt_key_ids,
(const gchar **) opt_gpg_key_ids,
opt_gpg_homedir,
cancellable,
error))
return FALSE;
}
#endif
if (opt_key_ids)
{
g_autoptr (GVariant) secret_keys = NULL;
g_autoptr (GVariantBuilder) sk_builder = NULL;
sk_builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
char **iter;
for (iter = opt_key_ids; iter && *iter; iter++)
{
const char *keyid = *iter;
GVariant *secret_key = NULL;
/* Currently only strings are used as keys
* for supported signature types */
secret_key = g_variant_new_string (keyid);
g_variant_builder_add (sk_builder, "v", secret_key);
}
secret_keys = g_variant_builder_end (sk_builder);
if (! ostree_sign_summary (sign,
repo,
secret_keys,
cancellable,
error))
return FALSE;
}
}
else if (opt_view || opt_raw)
{

View File

@ -53,6 +53,7 @@ BUILTINPROTO(prune);
BUILTINPROTO(refs);
BUILTINPROTO(reset);
BUILTINPROTO(fsck);
BUILTINPROTO(sign);
BUILTINPROTO(show);
BUILTINPROTO(static_delta);
BUILTINPROTO(summary);

View File

@ -28,9 +28,11 @@
static char **opt_set;
static gboolean opt_no_gpg_verify;
static gboolean opt_no_sign_verify;
static gboolean opt_if_not_exists;
static gboolean opt_force;
static char *opt_gpg_import;
static char **opt_sign_verify;
static char *opt_contenturl;
static char *opt_collection_id;
static char *opt_sysroot;
@ -44,6 +46,8 @@ static char *opt_repo;
static GOptionEntry option_entries[] = {
{ "set", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_set, "Set config option KEY=VALUE for remote", "KEY=VALUE" },
{ "no-gpg-verify", 0, 0, G_OPTION_ARG_NONE, &opt_no_gpg_verify, "Disable GPG verification", NULL },
{ "no-sign-verify", 0, 0, G_OPTION_ARG_NONE, &opt_no_sign_verify, "Disable signature verification", NULL },
{ "sign-verify", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_sign_verify, "Verify signatures using KEYTYPE=inline:PUBKEY or KEYTYPE=file:/path/to/key", "KEYTYPE=[inline|file]:PUBKEY" },
{ "if-not-exists", 0, 0, G_OPTION_ARG_NONE, &opt_if_not_exists, "Do nothing if the provided remote exists", NULL },
{ "force", 0, 0, G_OPTION_ARG_NONE, &opt_force, "Replace the provided remote if it exists", NULL },
{ "gpg-import", 0, 0, G_OPTION_ARG_FILENAME, &opt_gpg_import, "Import GPG key from FILE", "FILE" },
@ -55,12 +59,49 @@ static GOptionEntry option_entries[] = {
{ NULL }
};
static char *
add_verify_opt (GVariantBuilder *builder,
const char *keyspec,
GError **error)
{
g_auto(GStrv) parts = g_strsplit (keyspec, "=", 2);
g_assert (parts && *parts);
const char *keytype = parts[0];
if (!parts[1])
return glnx_null_throw (error, "Failed to parse KEYTYPE=[inline|file]:DATA in %s", keyspec);
g_autoptr(OstreeSign) sign = ostree_sign_get_by_name (keytype, error);
if (!sign)
return NULL;
const char *rest = parts[1];
g_assert (!parts[2]);
g_auto(GStrv) keyparts = g_strsplit (rest, ":", 2);
g_assert (keyparts && *keyparts);
const char *keyref = keyparts[0];
g_assert (keyref);
g_autofree char *optname = NULL;
if (g_str_equal (keyref, "inline"))
optname = g_strdup_printf ("verification-%s-key", keytype);
else if (g_str_equal (keyref, "file"))
optname = g_strdup_printf ("verification-%s-file", keytype);
else
return glnx_null_throw (error, "Invalid key reference %s, expected inline|file", keyref);
g_assert (keyparts[1] && !keyparts[2]);
g_variant_builder_add (builder, "{s@v}",
optname,
g_variant_new_variant (g_variant_new_string (keyparts[1])));
return g_strdup (ostree_sign_get_name (sign));
}
gboolean
ot_remote_builtin_add (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(OstreeSysroot) sysroot = NULL;
g_autoptr(OstreeRepo) repo = NULL;
g_autoptr(GString) sign_verify = NULL;
const char *remote_name;
const char *remote_url;
char **iter;
@ -134,12 +175,43 @@ ot_remote_builtin_add (int argc, char **argv, OstreeCommandInvocation *invocatio
}
#ifndef OSTREE_DISABLE_GPGME
if (opt_no_gpg_verify)
/* No signature verification implies no verification for GPG signature as well */
if (opt_no_gpg_verify || opt_no_sign_verify)
g_variant_builder_add (optbuilder, "{s@v}",
"gpg-verify",
g_variant_new_variant (g_variant_new_boolean (FALSE)));
#endif /* OSTREE_DISABLE_GPGME */
if (opt_no_sign_verify)
{
if (opt_sign_verify)
return glnx_throw (error, "Cannot specify both --sign-verify and --no-sign-verify");
g_variant_builder_add (optbuilder, "{s@v}",
"sign-verify",
g_variant_new_variant (g_variant_new_boolean (FALSE)));
}
for (char **iter = opt_sign_verify; iter && *iter; iter++)
{
const char *keyspec = *iter;
g_autofree char *signname = add_verify_opt (optbuilder, keyspec, error);
if (!signname)
return FALSE;
if (!sign_verify)
{
sign_verify = g_string_new (signname);
}
else
{
g_string_append_c (sign_verify, ',');
g_string_append (sign_verify, signname);
}
}
if (sign_verify != NULL)
g_variant_builder_add (optbuilder, "{s@v}",
"sign-verify",
g_variant_new_variant (g_variant_new_string (sign_verify->str)));
if (opt_collection_id != NULL)
g_variant_builder_add (optbuilder, "{s@v}", "collection-id",
g_variant_new_variant (g_variant_new_take_string (g_steal_pointer (&opt_collection_id))));

Some files were not shown because too many files have changed in this diff Show More