Commit ac4ab298 authored by Bernhard Link's avatar Bernhard Link

create InRelease file (additionally to Release.gpg)

parent cf481263
2010-07-10
* create InRelease files when signing...
2010-07-05
* special $Component in override files will force
placing packages in the specified component
......
......@@ -2,6 +2,7 @@ Updates between 4.1.1 and 4.2.0:
- allow patterns in override files
- apply override files when doing 'pull' and 'update'
- add special '$Component' override field
- create InRelease file additionally to Release.gpg
Updates between 4.1.1 and 4.1.2:
- fix parsing of .orig-*.tar.* lines in .changes files,
......
......@@ -1218,14 +1218,9 @@ retvalue release_prepare(struct release *release, struct distribution *distribut
return RET_ERROR;
}
}
if( distribution->signwith != NULL )
r = signature_startsignedfile(release->dirofdist, "Release",
distribution->signwith,
&release->signedfile);
else
r = signature_startunsignedfile(release->dirofdist, "Release",
&release->signedfile);
r = signature_startsignedfile(release->dirofdist,
"Release", "InRelease",
&release->signedfile);
if( RET_WAS_ERROR(r) ) {
return r;
}
......
/* This file is part of "reprepro"
* Copyright (C) 2003,2004,2005,2006,2007,2009 Bernhard R. Link
* Copyright (C) 2003,2004,2005,2006,2007,2009,2010 Bernhard R. Link
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
......@@ -101,7 +101,9 @@ void signatures_done(void) {
#endif /* HAVE_LIBGPGME */
}
static retvalue signature_sign(const char *options, const char *filename, const char *signaturename, bool willcleanup) {
// TODO: move the two signing steps (Release.gpg and InRelease)
// in here so that key retrieval needs only be done once...
static retvalue signature_sign(const char *options, const char *filename, void *data, size_t datalen, const char *signaturename, bool willcleanup, bool signinline) {
retvalue r;
int ret, e;
#ifdef HAVE_LIBGPGME
......@@ -171,18 +173,18 @@ static retvalue signature_sign(const char *options, const char *filename, const
gpgme_op_keylist_end(context);
}
// TODO: Supply our own read functions to get sensible error messages.
err = gpgme_data_new(&dh_gpg);
if( err != 0 ) {
return gpgerror(err);
}
err = gpgme_data_new_from_file(&dh,filename,1);
err = gpgme_data_new_from_mem(&dh, data, datalen, 0);
if( err != 0 ) {
gpgme_data_release(dh_gpg);
return gpgerror(err);
}
err = gpgme_op_sign(context,dh,dh_gpg,GPGME_SIG_MODE_DETACH);
err = gpgme_op_sign(context, dh, dh_gpg,
signinline?GPGME_SIG_MODE_CLEAR:GPGME_SIG_MODE_DETACH);
gpgme_data_release(dh);
if( err != 0 ) {
gpgme_data_release(dh_gpg);
......@@ -807,6 +809,7 @@ retvalue signature_readsignedchunk(const char *filename, const char *filenametos
struct signedfile {
char *plainfilename, *newplainfilename;
char *signfilename, *newsignfilename;
char *inlinefilename, *newinlinefilename;
retvalue result;
#define DATABUFFERUNITS (128ul * 1024ul)
size_t bufferlen, buffersize;
......@@ -814,7 +817,7 @@ struct signedfile {
};
static retvalue newpossiblysignedfile(const char *directory, const char *basefilename, struct signedfile **out) {
retvalue signature_startsignedfile(const char *directory, const char *basefilename, const char *inlinefilename, struct signedfile **out) {
struct signedfile *n;
n = calloc(1, sizeof(struct signedfile));
......@@ -825,13 +828,19 @@ static retvalue newpossiblysignedfile(const char *directory, const char *basefil
free(n);
return RET_ERROR_OOM;
}
n->inlinefilename = calc_dirconcat(directory, inlinefilename);
if( n->inlinefilename == NULL ) {
free(n->plainfilename);
free(n);
return RET_ERROR_OOM;
}
n->newplainfilename = NULL;
n->bufferlen = 0;
n->buffersize = DATABUFFERUNITS;
n->buffer = malloc(n->buffersize);
if( FAILEDTOALLOC(n->buffer) ) {
free(n->newplainfilename);
free(n->plainfilename);
free(n->inlinefilename);
free(n);
return RET_ERROR_OOM;
}
......@@ -854,32 +863,17 @@ void signedfile_free(struct signedfile *f, bool cleanup) {
free(f->newsignfilename);
}
free(f->signfilename);
if( f->newinlinefilename != NULL ) {
if( cleanup )
(void)unlink(f->newinlinefilename);
free(f->newinlinefilename);
}
free(f->inlinefilename);
free(f->buffer);
free(f);
return;
}
retvalue signature_startsignedfile(const char *directory, const char *basefilename, UNUSED(const char *options), struct signedfile **out) {
retvalue r;
struct signedfile *n;
r = newpossiblysignedfile(directory, basefilename, &n);
if( RET_WAS_ERROR(r) )
return r;
*out = n;
return RET_OK;
}
retvalue signature_startunsignedfile(const char *directory, const char *basefilename, struct signedfile **out) {
retvalue r;
struct signedfile *n;
r = newpossiblysignedfile(directory, basefilename, &n);
if( RET_WAS_ERROR(r) )
return r;
*out = n;
return RET_OK;
}
/* store data into buffer */
void signedfile_write(struct signedfile *f, const void *data, size_t len) {
......@@ -980,13 +974,20 @@ retvalue signedfile_prepare(struct signedfile *f, const char *options, bool will
f->newsignfilename = calc_addsuffix(f->signfilename, "new");
if( f->newsignfilename == NULL )
return RET_ERROR_OOM;
// TODO: make this in-situ (i.e. not signing the file but the memory
// content to be saved before):
f->newinlinefilename = calc_addsuffix(f->inlinefilename, "new");
if( FAILEDTOALLOC(f->newinlinefilename) )
return RET_ERROR_OOM;
r = signature_sign(options,
f->newplainfilename,
f->newsignfilename, willcleanup);
f->buffer, f->bufferlen,
f->newsignfilename, willcleanup, false);
if( RET_WAS_ERROR(r) )
return r;
r = signature_sign(options,
f->newplainfilename,
f->buffer, f->bufferlen,
f->newinlinefilename, willcleanup, true);
if( RET_WAS_ERROR(r) )
return r;
}
......@@ -1016,6 +1017,25 @@ retvalue signedfile_finalize(struct signedfile *f, bool *toolate) {
*toolate = true;
}
}
if( f->newinlinefilename != NULL && f->inlinefilename != NULL ) {
e = rename(f->newinlinefilename, f->inlinefilename);
if( e < 0 ) {
e = errno;
fprintf(stderr, "Error %d moving %s to %s: %s!\n", e,
f->newinlinefilename,
f->inlinefilename, strerror(e));
result = RET_ERRNO(e);
/* after something was done, do not stop
* but try to do as much as possible */
if( !*toolate )
return result;
} else {
/* does not need deletion any more */
free(f->newinlinefilename);
f->newinlinefilename = NULL;
*toolate = true;
}
}
e = rename(f->newplainfilename, f->plainfilename);
if( e < 0 ) {
e = errno;
......
......@@ -48,8 +48,7 @@ retvalue signature_readsignedchunk(const char *filename, const char *filenametos
struct signedfile;
retvalue signature_startsignedfile(const char *directory, const char *basename, /*@out@*/const char *options, struct signedfile **);
retvalue signature_startunsignedfile(const char *directory, const char *basename, /*@out@*/struct signedfile **);
retvalue signature_startsignedfile(const char */*directory*/, const char */*basename*/, const char */*inlinebasename*/, /*@out@*/struct signedfile **);
void signedfile_write(struct signedfile *, const void *, size_t);
/* generate signature in temporary file */
retvalue signedfile_prepare(struct signedfile *, const char *options, bool willcleanup);
......
......@@ -21,6 +21,7 @@ testonlysmalldeletes.sh \
testoverride.sh \
testpackagediff.sh \
testsignatures.sh \
testsigned.sh \
testsnapshotcopyrestore.sh \
testsubcomponents.sh \
testtemplate.sh \
......
#!/bin/bash
set -e
if test "${MAINTESTOPTIONS+set}" != set ; then
source $(dirname $0)/test.inc
STANDALONE="true"
else
STANDALONE=""
fi
rm -rf db dists pool lists conf gpgtestdir
mkdir -p gpgtestdir
export GNUPGHOME="`pwd`/gpgtestdir"
gpg --import $SRCDIR/tests/good.key
mkdir -p conf
cat > conf/distributions <<CONFEND
Codename: ATest
Architectures: ${FAKEARCHITECTURE} source
Components: everything
SignWith: good@nowhere.tld
CONFEND
gpg --list-keys
testrun - -b . export 3<<EOF
stdout
-v2*=Created directory "./db"
-v1*=Exporting ATest...
-v2*=Created directory "./dists"
-v2*=Created directory "./dists/ATest"
-v2*=Created directory "./dists/ATest/everything"
-v2*=Created directory "./dists/ATest/everything/binary-${FAKEARCHITECTURE}"
-v6*= exporting 'ATest|everything|${FAKEARCHITECTURE}'...
-v6*= creating './dists/ATest/everything/binary-${FAKEARCHITECTURE}/Packages' (uncompressed,gzipped)
-v2*=Created directory "./dists/ATest/everything/source"
-v6*= exporting 'ATest|everything|source'...
-v6*= creating './dists/ATest/everything/source/Sources' (gzipped)
-v2*=Successfully created './dists/ATest/Release.gpg.new'
-v2*=Successfully created './dists/ATest/InRelease.new'
EOF
find dists/ATest | sort > results
cat > results.expected <<EOF
dists/ATest
dists/ATest/InRelease
dists/ATest/Release
dists/ATest/Release.gpg
dists/ATest/everything
dists/ATest/everything/binary-abacus
dists/ATest/everything/binary-abacus/Packages
dists/ATest/everything/binary-abacus/Packages.gz
dists/ATest/everything/binary-abacus/Release
dists/ATest/everything/source
dists/ATest/everything/source/Release
dists/ATest/everything/source/Sources.gz
EOF
dodiff results.expected results
dodo gpg --verify dists/ATest/Release.gpg dists/ATest/Release
dodo gpg --verify dists/ATest/InRelease
cp dists/ATest/InRelease InRelease
ed -s InRelease <<'EOF'
H
/^-----BEGIN PGP SIGNED MESSAGE-----$/,/^$/d
/^-----BEGIN PGP SIGNATURE-----$/,$d
w
q
EOF
dodiff dists/ATest/Release InRelease
rm -r conf db dists gpgtestdir InRelease results results.expected
if test x$STANDALONE = xtrue ; then
set +v +x
echo
echo "If the script is still running to show this,"
echo "all tested cases seem to work. (Though writing some tests more can never harm)."
fi
exit 0
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment