Skip to content

Commit 6e19c16

Browse files
ffestidmnks
authored andcommitted
Implement openpgp.cert.d based keystore
This does implement the layout on the file system and the write lock of the openpgp.cert.d proposal according to https://www.ietf.org/archive/id/draft-nwjw-openpgp-cert-d-00.html but not the Trust root, Petname mapping or Trusted introducers. Resolves: #3341
1 parent 360c96e commit 6e19c16

File tree

4 files changed

+175
-0
lines changed

4 files changed

+175
-0
lines changed

lib/keystore.cc

+89
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <string>
44

55
#include <fcntl.h>
6+
#include <unistd.h>
7+
#include <sys/file.h>
68

79
#include <rpm/header.h>
810
#include <rpm/rpmbase64.h>
@@ -148,6 +150,93 @@ rpmRC keystore_fs::import_key(rpmtxn txn, rpmPubkey key, int replace, rpmFlags f
148150
return rc;
149151
}
150152

153+
/*****************************************************************************/
154+
155+
static int acquire_write_lock(rpmtxn txn)
156+
{
157+
char * keyringpath = rpmGenPath(rpmtxnRootDir(txn), "%{_keyringpath}/", NULL);
158+
char * lockpath = rpmGenPath(rpmtxnRootDir(txn), "%{_keyringpath}/", "writelock");
159+
int fd = -1;
160+
161+
if (rpmMkdirs(NULL, keyringpath)) {
162+
rpmlog(RPMLOG_ERR, _("failed to create keyring directory %s: %s\n"),
163+
keyringpath, strerror(errno));
164+
goto exit;
165+
}
166+
167+
if ((fd = open(lockpath, O_WRONLY|O_CREAT)) == -1) {
168+
rpmlog(RPMLOG_ERR, _("Can't create writelock for keyring at %s: %s\n"), keyringpath, strerror(errno));
169+
} else if (flock(fd, LOCK_EX|LOCK_NB)) {
170+
rpmlog(RPMLOG_ERR, _("Can't acquire writelock for keyring at %s\n"), keyringpath);
171+
close(fd);
172+
fd = -1;
173+
}
174+
175+
exit:
176+
free(keyringpath);
177+
free(lockpath);
178+
return fd;
179+
}
180+
181+
static void free_write_lock(int fd)
182+
{
183+
flock(fd, LOCK_UN);
184+
}
185+
186+
rpmRC keystore_openpgp_cert_d::load_keys(rpmtxn txn, rpmKeyring keyring)
187+
{
188+
return load_keys_from_glob(txn, keyring, "%{_keyringpath}/*/*");
189+
}
190+
191+
rpmRC keystore_openpgp_cert_d::delete_key(rpmtxn txn, rpmPubkey key)
192+
{
193+
rpmRC rc = RPMRC_NOTFOUND;
194+
int lock_fd = -1;
195+
196+
if ((lock_fd = acquire_write_lock(txn)) == -1)
197+
return RPMRC_FAIL;
198+
199+
string fp = rpmPubkeyFingerprintAsHex(key);
200+
string dir = fp.substr(0, 2);
201+
string filename = fp.substr(2);
202+
char * filepath = rpmGetPath(rpmtxnRootDir(txn), "%{_keyringpath}/", dir.c_str(), "/", filename.c_str(), NULL);
203+
char * dirpath = rpmGetPath(rpmtxnRootDir(txn), "%{_keyringpath}/", dir.c_str(), NULL);
204+
205+
if (!access(filepath, F_OK))
206+
rc = unlink(filepath) ? RPMRC_FAIL : RPMRC_OK;
207+
/* delete directory if empty */
208+
rmdir(dirpath);
209+
210+
free(filepath);
211+
free(dirpath);
212+
free_write_lock(lock_fd);
213+
return rc;
214+
}
215+
216+
rpmRC keystore_openpgp_cert_d::import_key(rpmtxn txn, rpmPubkey key, int replace, rpmFlags flags)
217+
{
218+
rpmRC rc = RPMRC_NOTFOUND;
219+
int lock_fd = -1;
220+
221+
if ((lock_fd = acquire_write_lock(txn)) == -1)
222+
return RPMRC_FAIL;
223+
224+
string fp = rpmPubkeyFingerprintAsHex(key);
225+
string dir = fp.substr(0, 2);
226+
string filename = fp.substr(2);
227+
char *dirpath = rpmGetPath(rpmtxnRootDir(txn), "%{_keyringpath}/", dir.c_str(), NULL);
228+
string dirstr = dirpath;
229+
230+
rc = write_key_to_disk(key, dirstr, filename, replace, flags);
231+
232+
free_write_lock(lock_fd);
233+
free(dirpath);
234+
235+
return rc;
236+
}
237+
238+
/*****************************************************************************/
239+
151240
rpmRC keystore_rpmdb::load_keys(rpmtxn txn, rpmKeyring keyring)
152241
{
153242
Header h;

lib/keystore.hh

+7
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ private:
3737
rpmRC delete_key(rpmtxn txn, const std::string & keyid, unsigned int newinstance = 0);
3838
};
3939

40+
class keystore_openpgp_cert_d : public keystore {
41+
public:
42+
virtual rpmRC load_keys(rpmtxn txn, rpmKeyring keyring);
43+
virtual rpmRC import_key(rpmtxn txn, rpmPubkey key, int replace = 1, rpmFlags flags = 0);
44+
virtual rpmRC delete_key(rpmtxn txn, rpmPubkey key);
45+
};
46+
4047
}; /* namespace */
4148

4249
#endif /* _KEYSTORE_H */

lib/rpmts.cc

+2
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,8 @@ static keystore *getKeystore(rpmts ts)
275275
ts->keystore = new keystore_fs();
276276
} else if (rstreq(krtype, "rpmdb")) {
277277
ts->keystore = new keystore_rpmdb();
278+
} else if (rstreq(krtype, "openpgp")) {
279+
ts->keystore = new keystore_openpgp_cert_d();
278280
} else {
279281
/* Fall back to using rpmdb if unknown, for now at least */
280282
rpmlog(RPMLOG_WARNING,

tests/rpmsigdig.at

+77
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,83 @@ runroot rpmkeys -Kv /data/RPMS/hello-2.0-1.x86_64.rpm /data/RPMS/hello-1.0-1.i38
264264
RPMTEST_CLEANUP
265265

266266

267+
AT_SETUP([rpmkeys key update (openpgp)])
268+
AT_KEYWORDS([rpmkeys signature])
269+
RPMDB_INIT
270+
# root's .rpmmacros used to keep this build prefix independent
271+
echo "%_keyring openpgp" >> "${RPMTEST}"/root/.rpmmacros
272+
RPMTEST_CHECK([
273+
runroot rpmkeys --import /data/keys/rpm.org-rsa-2048-test.pub
274+
runroot rpmkeys -Kv /data/RPMS/hello-2.0-1.x86_64-signed-with-new-subkey.rpm
275+
],
276+
[1],
277+
[/data/RPMS/hello-2.0-1.x86_64-signed-with-new-subkey.rpm:
278+
Header OpenPGP V4 EdDSA/SHA512 signature, key ID 6323c42711450b6c: NOKEY
279+
Header SHA256 digest: OK
280+
Payload SHA256 digest: OK
281+
],
282+
[])
283+
284+
RPMTEST_CHECK([
285+
runroot_other touch /usr/lib/sysimage/rpm/pubkeys/writelock
286+
runroot_other flock -x /usr/lib/sysimage/rpm/pubkeys/writelock -c "rpmkeys --import /data/keys/rpm.org-rsa-2048-add-subkey.asc"
287+
runroot_other rm /usr/lib/sysimage/rpm/pubkeys/writelock
288+
],
289+
[0],
290+
[],
291+
[error: Can't acquire writelock for keyring at /usr/lib/sysimage/rpm/pubkeys
292+
error: /data/keys/rpm.org-rsa-2048-add-subkey.asc: key 1 import failed.
293+
])
294+
295+
296+
RPMTEST_CHECK([
297+
runroot rpmkeys --list | wc -l
298+
runroot rpmkeys --import /data/keys/rpm.org-rsa-2048-add-subkey.asc
299+
runroot rpmkeys --list | wc -l
300+
],
301+
[0],
302+
[1
303+
1
304+
],
305+
[])
306+
307+
RPMTEST_CHECK([
308+
runroot rpmkeys -Kv /data/RPMS/hello-2.0-1.x86_64-signed-with-new-subkey.rpm
309+
],
310+
[0],
311+
[/data/RPMS/hello-2.0-1.x86_64-signed-with-new-subkey.rpm:
312+
Header OpenPGP V4 EdDSA/SHA512 signature, key fingerprint: 771b18d3d7baa28734333c424344591e1964c5fc: OK
313+
Header SHA256 digest: OK
314+
Payload SHA256 digest: OK
315+
],
316+
[])
317+
318+
RPMTEST_CHECK([
319+
runroot rpmkeys --delete abcd gimmekey 1111aaaa2222bbbb
320+
],
321+
[1],
322+
[],
323+
[error: invalid key id: abcd
324+
error: invalid key id: gimmekey
325+
error: key not found: 1111aaaa2222bbbb
326+
])
327+
328+
RPMTEST_CHECK([
329+
runroot rpmkeys --delete 1964c5fc
330+
],
331+
[0],
332+
[],
333+
[])
334+
335+
RPMTEST_CHECK([
336+
runroot rpmkeys --list | wc -l
337+
],
338+
[0],
339+
[0
340+
],
341+
[])
342+
RPMTEST_CLEANUP
343+
267344
AT_SETUP([rpmkeys -Kv <reconstructed> 1])
268345
AT_KEYWORDS([rpmkeys digest])
269346
RPMDB_INIT

0 commit comments

Comments
 (0)