Commit 143377d8 authored by Bernhard Link's avatar Bernhard Link

allow subkey matching in uploader lists, 'unsigned' now only means unsigned...

allow subkey matching in uploader lists, 'unsigned' now only means unsigned while the new 'anybody' means everybody. Preparations for more conditions.
parent b4e1948a
2009-05-22
* allow subkey matching in uploader lists, 'unsigned' now only
means unsigned while the new 'anybody' means everybody.
Preparations for more conditions.
2009-05-12
* copy and copysrc give warnings about not found packages unless
verbosity is reduced by --silent. (To help people catch their typos).
......
Updates between 3.9.2 and 3.10.0:
- fix bug of ListHook not used if in the From: rule of a rule.
- add ListShellHook
- add ListShelllHook
+ rewrite Release.gpg verification code:
- more hops needed to use expired or revoked keys
- earlier check of keys. now all keys in VerifyRelease must be known to gpg
- subkeys are accepted if the key-id is appended with '+'.
* improve uploader lists:
- subkeys are accepted if key-if is appended with '+'
- new 'anybody' while 'unsigned' now means really unsigned
Updates between 3.9.1 and 3.9.2:
+ fix bug (catched by assertion if there is no old index file)
......
......@@ -104,7 +104,7 @@ struct changes {
binaries;
struct fileentry *files;
char *control;
struct strlist fingerprints;
struct signatures *signatures;
/* Things to be set by changes_fixfields: */
/* the component source files are put into */
component_t srccomponent;
......@@ -156,7 +156,7 @@ static void changes_free(/*@only@*/struct changes *changes) {
free(changes->changesfilekey);
// trackedpackage_free(changes->trackedpkg);
free(changes->incomingdirectory);
strlist_done(&changes->fingerprints);
signatures_free(changes->signatures);
}
free(changes);
}
......@@ -391,7 +391,7 @@ static retvalue changes_read(const char *filename, /*@out@*/struct changes **cha
if( c == NULL )
return RET_ERROR_OOM;
r = signature_readsignedchunk(filename, filename,
&c->control, &c->fingerprints, NULL, &broken);
&c->control, &c->signatures, &broken);
R;
if( broken && !IGNORING_(brokensignatures,
"'%s' contains only broken signatures.\n"
......@@ -1158,9 +1158,19 @@ static retvalue changes_includepkgs(struct database *database, struct distributi
return result;
}
static bool permissionssuffice(UNUSED(struct changes *changes),
const struct uploadpermissions *permissions) {
return permissions->allowall;
static bool permissionssuffice(struct changes *changes, struct upload_conditions *conditions) {
do switch( uploaders_nextcondition(conditions) ) {
case uc_ACCEPTED:
return true;
case uc_REJECTED:
return false;
case uc_SOURCENAME:
assert( changes->source != NULL);
if( uploaders_verifystring(conditions,
changes->source) )
return true;
break;
} while( true );
}
/* insert the given .changes into the mirror in the <distribution>
......@@ -1195,39 +1205,23 @@ retvalue changes_add(struct database *database, trackingdb const tracks, package
/* make sure caller has called distribution_loaduploaders */
assert( distribution->uploaders == NULL || distribution->uploaderslist != NULL );
if( distribution->uploaderslist != NULL ) {
const struct uploadpermissions *permissions;
int i;
struct upload_conditions *conditions;
if( changes->fingerprints.count == 0 ) {
r = uploaders_unsignedpermissions(distribution->uploaderslist,
&permissions);
assert( r != RET_NOTHING );
if( RET_WAS_ERROR(r) ) {
changes_free(changes);
return r;
}
if( permissions == NULL || !permissionssuffice(changes,permissions) )
permissions = NULL;
}
for( i = 0; i < changes->fingerprints.count ; i++ ) {
const char *fingerprint = changes->fingerprints.values[i];
r = uploaders_permissions(distribution->uploaderslist,
fingerprint, &permissions);
assert( r != RET_NOTHING );
if( RET_WAS_ERROR(r) ) {
changes_free(changes);
return r;
}
if( permissions != NULL && permissionssuffice(changes,permissions) )
break;
permissions = NULL;
r = uploaders_permissions(distribution->uploaderslist,
changes->signatures, &conditions);
assert( r != RET_NOTHING );
if( RET_WAS_ERROR(r) ) {
changes_free(changes);
return r;
}
if( permissions == NULL &&
if( !permissionssuffice(changes, conditions) &&
!IGNORING_(uploaders,"No rule allowing this package in found in %s!\n",
distribution->uploaders) ) {
free(conditions);
changes_free(changes);
return RET_ERROR;
}
free(conditions);
}
/* look for component, section and priority to be correct or guess them*/
......
......@@ -3,6 +3,9 @@ reprepro (3.10.0-0) UNRELEASED; urgency=low
* new release
- hint at what remove does with packages' files in manpage
(Closes: 528498)
- allow subkeys in uploader lists and Release.gpg checking when
requested (Closes: 522522)
- fix handling of 16-hexdigit keyids in VerifyRelease (Closes: 525941)
* update Vcs-Browser field (Closes: 528291)
-- Bernhard R. Link <brlink@debian.org> Wed, 13 May 2009 13:10:09 +0200
......
......@@ -1498,20 +1498,27 @@ as to be signed with to be included in that distribution.
Empty lines and lines starting with a hash are ignored, every other line
has to be of one of this three forms:
.br
.B allow * by unsigned
.B allow \fIcondition\fP by anybody
which allows everyone to do everything,
.br
which allows everything without a valid signature in,
.B allow \fIcondition\fP by unsigned
.br
.B allow * by any key
which allows everything that has no pgp/gpg header,
.br
.B allow \fIcondition\fP by any key
.br
which allows everything with any valid signature in or
.br
.B allow * by key \fIkey-id\fP
.B allow \fIcondition\fP by key \fIkey-id\fP
.br
which allows everything signed by this \fIkey-id\fP (to be specified
without any spaces) in.
If the \fIkey-id\fP ends with a \fB+\fP (plus), a signature with a subkey of
this primary key also suffices.
The only condition currently supported is \fB*\fP which means any package.
.P
(Other statements
(Other conditions
will follow once somebody tells me what restrictions are useful).
.SH "ERROR IGNORING"
With \fB\-\-ignore\fP on the command line or an \fIignore\fP
......
......@@ -387,7 +387,7 @@ struct candidate {
/* from candidate_read */
int ofs;
char *control;
struct strlist keys, allkeys;
struct signatures *signatures;
/* from candidate_parse */
char *source, *sourceversion, *changesversion;
struct strlist distributions,
......@@ -477,8 +477,7 @@ static void candidate_free(/*@only@*/struct candidate *c) {
if( c == NULL )
return;
free(c->control);
strlist_done(&c->keys);
strlist_done(&c->allkeys);
signatures_free(c->signatures);
free(c->source);
free(c->sourceversion);
free(c->changesversion);
......@@ -562,7 +561,7 @@ static retvalue candidate_read(struct incoming *i, int ofs, struct candidate **r
return r;
}
assert( n->files->tempfilename != NULL );
r = signature_readsignedchunk(n->files->tempfilename, BASENAME(i,ofs), &n->control, &n->keys, &n->allkeys, broken);
r = signature_readsignedchunk(n->files->tempfilename, BASENAME(i,ofs), &n->control, &n->signatures, broken);
assert( r != RET_NOTHING );
if( RET_WAS_ERROR(r) ) {
candidate_free(n);
......@@ -1678,13 +1677,24 @@ static inline retvalue candidate_checkadd_into(struct database *database,const s
return RET_NOTHING;
}
static inline bool isallowed(UNUSED(struct incoming *i), UNUSED(struct candidate *c), UNUSED(struct distribution *into), const struct uploadpermissions *permissions) {
return permissions->allowall;
static inline bool isallowed(UNUSED(struct incoming *i), struct candidate *c, struct distribution *into, struct upload_conditions *conditions) {
do switch( uploaders_nextcondition(conditions) ) {
case uc_ACCEPTED:
return true;
case uc_REJECTED:
return false;
case uc_SOURCENAME:
assert( c->source != NULL);
if( uploaders_verifystring(conditions, c->source) )
return true;
break;
} while( true );
}
static retvalue candidate_checkpermissions(struct incoming *i, struct candidate *c, struct distribution *into) {
retvalue r;
int j;
struct upload_conditions *conditions;
bool allowed;
/* no rules means allowed */
if( into->uploaders == NULL )
......@@ -1695,54 +1705,17 @@ static retvalue candidate_checkpermissions(struct incoming *i, struct candidate
return r;
assert(into->uploaderslist != NULL);
if( c->keys.count == 0 ) {
const struct uploadpermissions *permissions;
r = uploaders_unsignedpermissions(into->uploaderslist,
&permissions);
assert( r != RET_NOTHING );
if( RET_WAS_ERROR(r) )
return r;
if( permissions != NULL && isallowed(i,c,into,permissions) )
return RET_OK;
} else for( j = 0; j < c->keys.count ; j++ ) {
const struct uploadpermissions *permissions;
r = uploaders_permissions(into->uploaderslist,
c->keys.values[j], &permissions);
assert( r != RET_NOTHING );
if( RET_WAS_ERROR(r) )
return r;
if( permissions != NULL && isallowed(i,c,into,permissions) )
return RET_OK;
}
/* reject, check if it would have been accepted with more signatures
* valid: */
if( verbose >= 0 &&
c->allkeys.count != 0 && c->allkeys.count != c->keys.count ) {
for( j = 0; j < c->allkeys.count ; j++ ) {
const struct uploadpermissions *permissions;
r = uploaders_permissions(into->uploaderslist,
c->allkeys.values[j], &permissions);
assert( r != RET_NOTHING );
if( RET_WAS_ERROR(r) )
return r;
if( permissions != NULL &&
isallowed(i,c , into, permissions) ) {
// TODO: get information if it was invalid because
// missing pub-key, expire-state or something else
// here so warning can be more specific.
fprintf(stderr,
"'%s' would have been accepted into '%s' if signature with '%s' was checkable and valid.\n",
i->files.values[c->ofs],
into->codename,
c->allkeys.values[j]);
}
}
}
/* reject */
return RET_NOTHING;
r = uploaders_permissions(into->uploaderslist, c->signatures, &conditions);
assert( r != RET_NOTHING );
if( RET_WAS_ERROR(r) )
return r;
allowed = isallowed(i, c, into, conditions);
free(conditions);
if( allowed )
return RET_OK;
else
/* reject */
return RET_NOTHING;
}
static retvalue check_architecture_availability(const struct incoming *i, const struct candidate *c) {
......
This diff is collapsed.
......@@ -18,9 +18,33 @@ void free_known_keys(void);
retvalue signature_check(const struct signature_requirement *, const char *releasegpg, const char *release);
struct signatures {
int count, validcount;
struct signature {
char *keyid;
char *primary_keyid;
/* valid is only true if none of the others is true,
all may be false due to non-signing keys used for
signing or things like that */
enum signature_state {
sist_error=0, /* internal error */
sist_missing, /* key missing, can not be checked */
sist_bad, /* broken signature, content may be corrupt */
sist_invalid, /* good signature, but may not sign or al */
sist_mostly, /* good signature, but check expire bits */
sist_valid /* good signature, no objections */
} state;
/* subkey or primary key are expired */
bool expired_key;
/* signature is expired */
bool expired_signature;
/* key or primary key revoced */
bool revoced_key;
} signatures[];
};
void signatures_free(/*@null@*//*@only@*/struct signatures *);
/* Read a single chunk from a file, that may be signed. */
struct strlist;
retvalue signature_readsignedchunk(const char *filename, const char *filenametoshow, char **chunkread, /*@null@*/ /*@out@*/struct strlist *validkeys, /*@null@*/ /*@out@*/ struct strlist *allkeys, bool *brokensignature);
retvalue signature_readsignedchunk(const char *filename, const char *filenametoshow, char **chunkread, /*@null@*/ /*@out@*/struct signatures **signatures, bool *brokensignature);
struct signedfile;
......
......@@ -511,7 +511,7 @@ retvalue signature_requirement_add(struct signature_requirement **list_p, const
req->num_keys = 0;
do {
bool allow_subkeys, allow_bad;
char *next_key;
char *next_key IFSTUPIDCC(=NULL);
r = parse_condition_part(&allow_subkeys, &allow_bad,
full_condition, &condition, &next_key);
......
......@@ -470,7 +470,7 @@ retvalue sources_readdsc(struct dsc_headers *dsc, const char *filename, const ch
enum checksumtype cs;
r = signature_readsignedchunk(filename, filenametoshow,
&dsc->control, NULL, NULL, broken);
&dsc->control, NULL, broken);
if( RET_WAS_ERROR(r) ) {
return r;
}
......
......@@ -52,6 +52,7 @@ allow * by key FFFFFFFF
allow * by any key
allow * by unsigned
allow * by key 00000000
allow * by anybody
CONFEND
cat > conf/incoming <<CONFEND
Name: abc
......@@ -264,14 +265,14 @@ stderr
*=No distribution accepting 'testrevsigned.changes'!
-v0*=There have been errors!
-v1*=Ignoring signature with '12D6C95C8C737389EAAF535972F1D61F685AF714' on 'testrevsigned.changes', as the key is revoked.
-v0*='testrevsigned.changes' would have been accepted into 'BTest' if signature with '12D6C95C8C737389EAAF535972F1D61F685AF714' was checkable and valid.
#-v0*='testrevsigned.changes' would have been accepted into 'BTest' if signature with '12D6C95C8C737389EAAF535972F1D61F685AF714' was checkable and valid.
stdout
EOF
testrun - -b . processincoming abc 3<<EOF
stderr
=Data seems not to be signed trying to use directly...
-v1*=Ignoring signature with '12D6C95C8C737389EAAF535972F1D61F685AF714' on 'testrevsigned.changes', as the key is revoked.
-v0*='testrevsigned.changes' would have been accepted into 'BTest' if signature with '12D6C95C8C737389EAAF535972F1D61F685AF714' was checkable and valid.
#-v0*='testrevsigned.changes' would have been accepted into 'BTest' if signature with '12D6C95C8C737389EAAF535972F1D61F685AF714' was checkable and valid.
stdout
-v3*=Will not put 'package' in 'CTest|everything|source', as already there with same version '9-2'.
-v3*=Will not put 'package' in 'CTest|everything|${FAKEARCHITECTURE}', as already there with same version '9-2'.
......
......@@ -596,7 +596,7 @@ static retvalue read_dscfile(const char *fullfilename, struct dscfile **dsc) {
if( n == NULL )
return RET_ERROR_OOM;
r = signature_readsignedchunk(fullfilename, fullfilename,
&n->controlchunk, NULL, NULL, NULL);
&n->controlchunk, NULL, NULL);
assert( r != RET_NOTHING );
// TODO: can this be ignored sometimes?
if( RET_WAS_ERROR(r) ) {
......@@ -2836,7 +2836,7 @@ int main(int argc,char *argv[]) {
char *changes;
r = signature_readsignedchunk(changesfilename, changesfilename,
&changes, NULL, NULL, NULL);
&changes, NULL, NULL);
if( !RET_IS_OK(r) ) {
signatures_done();
if( r == RET_ERROR_OOM )
......
This diff is collapsed.
#ifndef REPREPRO_UPLOADERSLIST_H
#define REPREPRO_UPLOADERSLIST_H
struct uploadpermissions {
/* later more fine grained permissions */
bool allowall;
};
struct upload_condition;
struct upload_conditions;
struct uploaders;
enum upload_condition_type { uc_REJECTED, uc_ALWAYS,
/* uc_COMPONENT, uc_ARCHITECTURE, */
uc_SOURCENAME, /* uc_SECTION */ };
#define uc_ACCEPTED uc_ALWAYS
retvalue uploaders_get(/*@out@*/struct uploaders **list, const char *filename);
void uploaders_unlock(/*@only@*//*@null@*/struct uploaders *);
retvalue uploaders_unsignedpermissions(struct uploaders *,
/*@out@*/const struct uploadpermissions **);
retvalue uploaders_permissions(struct uploaders *,const char *fingerprint,
/*@out@*/const struct uploadpermissions **);
struct signatures;
retvalue uploaders_permissions(struct uploaders *, const struct signatures *, /*@out@*/struct upload_conditions **);
/* uc_FAILED means rejected, uc_ACCEPTED means can go in */
enum upload_condition_type uploaders_nextcondition(struct upload_conditions *);
bool uploaders_verifystring(struct upload_conditions *, const char *);
bool uploaders_verifyatomlist(struct upload_conditions *, const struct atomlist *);
void upload_conditions_free(/*@only@*/struct upload_conditions *);
#endif
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