diff --git a/gradle/changelog/prevent_overwrite_read_only_gpg_keys.yaml b/gradle/changelog/prevent_overwrite_read_only_gpg_keys.yaml new file mode 100644 index 0000000000..ea6f9e4cf8 --- /dev/null +++ b/gradle/changelog/prevent_overwrite_read_only_gpg_keys.yaml @@ -0,0 +1,2 @@ +- type: fixed + description: Prevent overwrite read-only gpg keys ([#1713](https://github.com/scm-manager/scm-manager/pull/1713)) diff --git a/scm-webapp/src/main/java/sonia/scm/security/gpg/PublicKeyStore.java b/scm-webapp/src/main/java/sonia/scm/security/gpg/PublicKeyStore.java index d271f41769..1aace520b1 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/gpg/PublicKeyStore.java +++ b/scm-webapp/src/main/java/sonia/scm/security/gpg/PublicKeyStore.java @@ -71,9 +71,14 @@ public class PublicKeyStore { UserPermissions.changePublicKeys(username).check(); if (!rawKey.contains("PUBLIC KEY")) { - throw new NotPublicKeyException(ContextEntry.ContextBuilder.entity(RawGpgKey.class, displayName).build(), "The provided key is not a public key"); + throw new NotPublicKeyException( + ContextEntry.ContextBuilder.entity(RawGpgKey.class, displayName).build(), + "The provided key is not a public key" + ); } + preventOverwriteReadOnlyKeys(rawKey); + Keys keys = Keys.resolve(rawKey); String master = keys.getMaster(); @@ -90,6 +95,17 @@ public class PublicKeyStore { } + private void preventOverwriteReadOnlyKeys(String rawKey) { + Optional existingReadOnlyKey = store.getAll().values() + .stream() + .filter(k -> k.getRaw().trim().equals(rawKey.trim())) + .filter(RawGpgKey::isReadonly) + .findFirst(); + if (existingReadOnlyKey.isPresent()) { + throw new DeletingReadonlyKeyNotAllowedException(existingReadOnlyKey.get().getId()); + } + } + private Set getContactsFromPublicKey(String rawKey) { List userIds = new ArrayList<>(); PGPPublicKey publicKeyFromRawKey = extractPublicKey(rawKey); diff --git a/scm-webapp/src/test/java/sonia/scm/security/gpg/PublicKeyStoreTest.java b/scm-webapp/src/test/java/sonia/scm/security/gpg/PublicKeyStoreTest.java index 910feaf4e1..8bd4171ce9 100644 --- a/scm-webapp/src/test/java/sonia/scm/security/gpg/PublicKeyStoreTest.java +++ b/scm-webapp/src/test/java/sonia/scm/security/gpg/PublicKeyStoreTest.java @@ -169,6 +169,19 @@ class PublicKeyStoreTest { verify(eventBus, never()).post(any(PublicKeyDeletedEvent.class)); } + @Test() + void shouldThrowOnOverwriteReadonlyKey() throws IOException { + String rawKey = GPGTestHelper.readResourceAsString("single.asc"); + keyStore.add("SCM Package Key", "trillian", rawKey, true); + Optional key = keyStore.findById("0x975922F193B07D6E"); + + assertThat(key).isPresent(); + + assertThrows(DeletingReadonlyKeyNotAllowedException.class, () -> keyStore.add("Some other entry with same raw key", "trillian", rawKey, false)); + + verify(eventBus, never()).post(any(PublicKeyDeletedEvent.class)); + } + @Test void shouldReturnEmptyListIfNoKeysAvailable() { List keys = keyStore.findByUsername("zaphod");