Skip to content

Commit

Permalink
[ELY-2078] Added logging for accessing realm with invalid SecretKey a…
Browse files Browse the repository at this point in the history
…nd general code cleanup
  • Loading branch information
Ashpan committed Mar 18, 2022
1 parent 9710c35 commit 7050f15
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,13 @@ interface ElytronMessages extends BasicLogger {
@LogMessage(level = Logger.Level.DEBUG)
@Message(id = 13004, value = "JAAS logout failed for principal %s")
void debugInfoJaasLogoutFailure(Principal principal, @Cause Throwable cause);

@Message(id = 13005, value = "Filesystem-backed realm unable to decrypt identity")
RealmUnavailableException fileSystemRealmDecryptionFailed(@Cause Throwable cause);

@Message(id = 13006, value = "Filesystem-backed realm unable to encrypt identity")
RealmUnavailableException fileSystemRealmEncryptionFailed(@Cause Throwable cause);

@Message(id = 13007, value = "Filesystem-backed realm found an incompatible identity version. Requires at least version: %s")
RealmUnavailableException fileSystemRealmIncompatibleIdentityVersion(String expectedVersion);
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.Provider;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
Expand Down Expand Up @@ -533,7 +534,7 @@ static class Identity implements ModifiableRealmIdentity {
this.lock = lock;
this.hashCharset = hashCharset;
this.hashEncoding = hashEncoding;
this.providers = providers != null ? providers : INSTALLED_PROVIDERS;
this.providers = providers;
this.secretKey = secretKey;
}

Expand Down Expand Up @@ -738,7 +739,7 @@ public void setCredentials(final Collection<? extends Credential> credentials) t
throw ElytronMessages.log.fileSystemRealmNotFound(name);
}

final LoadedIdentity newIdentity = new LoadedIdentity(name, new ArrayList<>(credentials), loadedIdentity.getAttributes(), hashEncoding, providers);
final LoadedIdentity newIdentity = new LoadedIdentity(name, new ArrayList<>(credentials), loadedIdentity.getAttributes(), hashEncoding);
replaceIdentity(newIdentity);
}

Expand All @@ -748,7 +749,7 @@ public void setAttributes(final Attributes attributes) throws RealmUnavailableEx
if (loadedIdentity == null) {
throw ElytronMessages.log.fileSystemRealmNotFound(name);
}
final LoadedIdentity newIdentity = new LoadedIdentity(name, loadedIdentity.getCredentials(), attributes, hashEncoding, providers);
final LoadedIdentity newIdentity = new LoadedIdentity(name, loadedIdentity.getCredentials(), attributes, hashEncoding);
replaceIdentity(newIdentity);
}

Expand Down Expand Up @@ -784,8 +785,10 @@ private Void replaceIdentityPrivileged(final LoadedIdentity newIdentity) throws
try (OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(tempPath, WRITE, CREATE_NEW, DSYNC))) {
try (AutoCloseableXMLStreamWriterHolder holder = new AutoCloseableXMLStreamWriterHolder(xmlOutputFactory.createXMLStreamWriter(outputStream))) {
writeIdentity(holder.getXmlStreamWriter(), newIdentity);
} catch (XMLStreamException | GeneralSecurityException e) {
} catch (XMLStreamException | InvalidKeySpecException | NoSuchAlgorithmException | CertificateEncodingException e) {
throw ElytronMessages.log.fileSystemRealmFailedToWrite(tempPath, name, e);
} catch (GeneralSecurityException e) {
throw ElytronMessages.log.fileSystemRealmEncryptionFailed(e);
}
} catch (FileAlreadyExistsException ignored) {
// try a new name
Expand Down Expand Up @@ -837,7 +840,6 @@ private Version requiredVersion(final LoadedIdentity identityToWrite) {
// if new functionality is used then use the required schema version otherwise fallback
// to an older version.

// Do we require version 1.1?
if (secretKey != null) {
return Version.VERSION_1_1;
}
Expand Down Expand Up @@ -1001,7 +1003,7 @@ private LoadedIdentity parseIdentityContents(final XMLStreamReader streamReader,
//modifiable version of Attributes;
attributes = new MapAttributes();
}
return new LoadedIdentity(name, credentials, attributes, hashEncoding, providers);
return new LoadedIdentity(name, credentials, attributes, hashEncoding);
}
if (! version.getNamespace().equals(streamReader.getNamespaceURI())) {
// Mixed versions unsupported.
Expand Down Expand Up @@ -1041,7 +1043,7 @@ private List<Credential> parseCredentials(final XMLStreamReader streamReader, fi
throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
}
if ("password".equals(streamReader.getLocalName())) {
parsePassword(credentials, streamReader);
parsePassword(credentials, streamReader, version);
} else if ("public-key".equals(streamReader.getLocalName())) {
parsePublicKey(credentials, streamReader);
} else if ("certificate".equals(streamReader.getLocalName())) {
Expand Down Expand Up @@ -1115,16 +1117,24 @@ private void parsePublicKey(final List<Credential> credentials, final XMLStreamR
});
}

private void parsePassword(final List<Credential> credentials, final XMLStreamReader streamReader) throws XMLStreamException, RealmUnavailableException {
private void parsePassword(final List<Credential> credentials, final XMLStreamReader streamReader, final Version version) throws XMLStreamException, RealmUnavailableException {
parseCredential(streamReader, (algorithm, format, text) -> {
try {
if (ENCRYPTION_FORMAT.equals(format)) {
if (! version.isAtLeast(Version.VERSION_1_1)) {
throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
}
if (algorithm == null) {
throw ElytronMessages.log.fileSystemRealmMissingAttribute("algorithm", path, streamReader.getLocation().getLineNumber(), name);
}
PasswordFactory passwordFactory = PasswordFactory.getInstance(algorithm, providers);
byte[] encryptedPasswordBytes = CodePointIterator.ofChars(text.toCharArray()).base64Decode().drain();
byte[] decryptedPasswordBytes = CipherUtil.decrypt(encryptedPasswordBytes, secretKey);
byte[] decryptedPasswordBytes;
try {
decryptedPasswordBytes = CipherUtil.decrypt(encryptedPasswordBytes, secretKey);
} catch (GeneralSecurityException e) {
throw ElytronMessages.log.fileSystemRealmDecryptionFailed(e);
}
PasswordSpec passwordSpec = BasicPasswordSpecEncoding.decode(decryptedPasswordBytes);

if (passwordSpec != null) {
Expand Down Expand Up @@ -1155,7 +1165,7 @@ private void parsePassword(final List<Credential> credentials, final XMLStreamRe
} else {
throw ElytronMessages.log.fileSystemRealmInvalidPasswordFormat(format, path, streamReader.getLocation().getLineNumber(), name);
}
} catch (GeneralSecurityException e) {
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
}
});
Expand Down Expand Up @@ -1256,14 +1266,14 @@ private void parseAttribute(final XMLStreamReader streamReader, final Attributes
if (value == null) {
throw ElytronMessages.log.fileSystemRealmMissingAttribute("value", path, streamReader.getLocation().getLineNumber(), this.name);
}
try {
if (secretKey != null) {
if (secretKey != null) {
try {
attributes.addLast(CipherUtil.decrypt(name, secretKey), CipherUtil.decrypt(value, secretKey));
} else {
attributes.addLast(name, value);
} catch (GeneralSecurityException e){
throw ElytronMessages.log.fileSystemRealmDecryptionFailed(e);
}
} catch (GeneralSecurityException e) {
throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), this.name);
} else {
attributes.addLast(name, value);
}
if (streamReader.nextTag() != END_ELEMENT) {
throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), this.name);
Expand Down Expand Up @@ -1291,14 +1301,12 @@ protected static final class LoadedIdentity {
private final List<Credential> credentials;
private final Attributes attributes;
private final Encoding hashEncoding;
private final Supplier<Provider[]> providers;

LoadedIdentity(final String name, final List<Credential> credentials, final Attributes attributes, final Encoding hashEncoding, final Supplier<Provider[]> providers) {
LoadedIdentity(final String name, final List<Credential> credentials, final Attributes attributes, final Encoding hashEncoding) {
this.name = name;
this.credentials = credentials;
this.attributes = attributes;
this.hashEncoding = hashEncoding;
this.providers = providers;
}

public String getName() {
Expand All @@ -1317,10 +1325,6 @@ public Encoding getHashEncoding() {
return hashEncoding;
}

public Supplier<Provider[]> getProviders() {
return providers;
}

}

static class AutoCloseableXMLStreamReaderHolder implements AutoCloseable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public FileSystemSecurityRealmBuilder setNameRewriter(final NameRewriter nameRew
* @return this builder.
*/
public FileSystemSecurityRealmBuilder setLevels(final int levels) {
Assert.checkMinimumParameter("levels", 0, levels);
this.levels = levels;
return this;
}
Expand Down

0 comments on commit 7050f15

Please sign in to comment.