Reworked MSC1915. Add request validation.
This commit is contained in:
@@ -118,7 +118,7 @@ public class Mxisd {
|
||||
idStrategy = new RecursivePriorityLookupStrategy(cfg.getLookup(), ThreePidProviders.get(), bridgeFetcher);
|
||||
pMgr = new ProfileManager(ProfileProviders.get(), clientDns, httpClient);
|
||||
notifMgr = new NotificationManager(cfg.getNotification(), NotificationHandlers.get());
|
||||
sessMgr = new SessionManager(cfg.getSession(), cfg.getMatrix(), store, notifMgr);
|
||||
sessMgr = new SessionManager(cfg.getSession(), cfg.getMatrix(), store, notifMgr, resolver, httpClient, signMgr);
|
||||
invMgr = new InvitationManager(cfg, store, idStrategy, keyMgr, signMgr, resolver, notifMgr, pMgr);
|
||||
authMgr = new AuthManager(cfg, AuthProviders.get(), idStrategy, invMgr, clientDns, httpClient);
|
||||
dirMgr = new DirectoryManager(cfg.getDirectory(), clientDns, httpClient, DirectoryProviders.get());
|
||||
|
||||
@@ -62,6 +62,7 @@ public class MatrixConfig {
|
||||
private transient final Logger log = LoggerFactory.getLogger(MatrixConfig.class);
|
||||
|
||||
private String domain;
|
||||
private String trustedIdServer;
|
||||
private Identity identity = new Identity();
|
||||
|
||||
public String getDomain() {
|
||||
@@ -72,6 +73,14 @@ public class MatrixConfig {
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
public String getTrustedIdServer() {
|
||||
return trustedIdServer;
|
||||
}
|
||||
|
||||
public void setTrustedIdServer(String trustedIdServer) {
|
||||
this.trustedIdServer = trustedIdServer;
|
||||
}
|
||||
|
||||
public Identity getIdentity() {
|
||||
return identity;
|
||||
}
|
||||
|
||||
@@ -46,30 +46,15 @@ public class SessionConfig {
|
||||
|
||||
public static class PolicyUnbind {
|
||||
|
||||
public static class PolicyUnbindFraudulent {
|
||||
private boolean enabled = true;
|
||||
|
||||
private boolean sendWarning = true;
|
||||
|
||||
public boolean getSendWarning() {
|
||||
return sendWarning;
|
||||
}
|
||||
|
||||
public void setSendWarning(boolean sendWarning) {
|
||||
this.sendWarning = sendWarning;
|
||||
}
|
||||
public boolean getEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
||||
private PolicyUnbindFraudulent fraudulent = new PolicyUnbindFraudulent();
|
||||
|
||||
public PolicyUnbindFraudulent getFraudulent() {
|
||||
return fraudulent;
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public void setFraudulent(PolicyUnbindFraudulent fraudulent) {
|
||||
this.fraudulent = fraudulent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Policy() {
|
||||
|
||||
@@ -115,24 +115,10 @@ public class EmailSendGridConfig {
|
||||
|
||||
public static class Templates {
|
||||
|
||||
public static class TemplateSessionUnbind {
|
||||
|
||||
private EmailTemplate fraudulent = new EmailTemplate();
|
||||
|
||||
public EmailTemplate getFraudulent() {
|
||||
return fraudulent;
|
||||
}
|
||||
|
||||
public void setFraudulent(EmailTemplate fraudulent) {
|
||||
this.fraudulent = fraudulent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class TemplateSession {
|
||||
|
||||
private EmailTemplate validation = new EmailTemplate();
|
||||
private TemplateSessionUnbind unbind = new TemplateSessionUnbind();
|
||||
private EmailTemplate unbind = new EmailTemplate();
|
||||
|
||||
public EmailTemplate getValidation() {
|
||||
return validation;
|
||||
@@ -142,11 +128,11 @@ public class EmailSendGridConfig {
|
||||
this.validation = validation;
|
||||
}
|
||||
|
||||
public TemplateSessionUnbind getUnbind() {
|
||||
public EmailTemplate getUnbind() {
|
||||
return unbind;
|
||||
}
|
||||
|
||||
public void setUnbind(TemplateSessionUnbind unbind) {
|
||||
public void setUnbind(EmailTemplate unbind) {
|
||||
this.unbind = unbind;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ public class EmailTemplateConfig extends GenericTemplateConfig {
|
||||
setInvite("classpath:/threepids/email/invite-template.eml");
|
||||
getGeneric().put("matrixId", "classpath:/threepids/email/mxid-template.eml");
|
||||
getSession().setValidation("classpath:/threepids/email/validate-template.eml");
|
||||
getSession().getUnbind().setFraudulent("classpath:/threepids/email/unbind-fraudulent.eml");
|
||||
getSession().getUnbind().setValidation("classpath:/threepids/email/unbind-template.eml");
|
||||
getSession().getUnbind().setNotification("classpath:/threepids/email/unbind-notification.eml");
|
||||
}
|
||||
|
||||
public EmailTemplateConfig build() {
|
||||
@@ -40,7 +41,8 @@ public class EmailTemplateConfig extends GenericTemplateConfig {
|
||||
log.info("Session:");
|
||||
log.info(" Validation: {}", getSession().getValidation());
|
||||
log.info(" Unbind:");
|
||||
log.info(" Fraudulent: {}", getSession().getUnbind().getFraudulent());
|
||||
log.info(" Validation: {}", getSession().getUnbind().getValidation());
|
||||
log.info(" Notification: {}", getSession().getUnbind().getNotification());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -41,16 +41,25 @@ public class GenericTemplateConfig {
|
||||
|
||||
public static class SessionUnbind {
|
||||
|
||||
private String fraudulent;
|
||||
private String validation;
|
||||
|
||||
public String getFraudulent() {
|
||||
return fraudulent;
|
||||
private String notification;
|
||||
|
||||
public String getValidation() {
|
||||
return validation;
|
||||
}
|
||||
|
||||
public void setFraudulent(String fraudulent) {
|
||||
this.fraudulent = fraudulent;
|
||||
public void setValidation(String validation) {
|
||||
this.validation = validation;
|
||||
}
|
||||
|
||||
public String getNotification() {
|
||||
return notification;
|
||||
}
|
||||
|
||||
public void setNotification(String notification) {
|
||||
this.notification = notification;
|
||||
}
|
||||
}
|
||||
|
||||
private String validation;
|
||||
|
||||
@@ -30,7 +30,8 @@ public class PhoneSmsTemplateConfig extends GenericTemplateConfig {
|
||||
public PhoneSmsTemplateConfig() {
|
||||
setInvite("classpath:/threepids/sms/invite-template.txt");
|
||||
getSession().setValidation("classpath:/threepids/sms/validate-template.txt");
|
||||
getSession().getUnbind().setFraudulent("classpath:/threepids/sms/unbind-fraudulent.txt");
|
||||
getSession().getUnbind().setValidation("classpath:/threepids/sms/unbind-validation.txt");
|
||||
getSession().getUnbind().setNotification("classpath:/threepids/sms/unbind-notification.txt");
|
||||
}
|
||||
|
||||
public PhoneSmsTemplateConfig build() {
|
||||
@@ -39,7 +40,8 @@ public class PhoneSmsTemplateConfig extends GenericTemplateConfig {
|
||||
log.info("Session:");
|
||||
log.info(" Validation: {}", getSession().getValidation());
|
||||
log.info(" Unbind:");
|
||||
log.info(" Fraudulent: {}", getSession().getUnbind().getFraudulent());
|
||||
log.info(" Validation: {}", getSession().getUnbind().getValidation());
|
||||
log.info(" Notification: {}", getSession().getUnbind().getNotification());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -58,5 +58,4 @@ public class CryptoFactory {
|
||||
public static SignatureManager getSignatureManager(MxisdConfig cfg, Ed25519KeyManager keyMgr) {
|
||||
return new Ed25519SignatureManager(cfg, keyMgr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import io.kamax.matrix.event.EventKey;
|
||||
import io.kamax.matrix.json.MatrixJson;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.PublicKey;
|
||||
import java.util.Objects;
|
||||
|
||||
public interface SignatureManager {
|
||||
@@ -106,4 +107,13 @@ public interface SignatureManager {
|
||||
*/
|
||||
Signature sign(byte[] data);
|
||||
|
||||
/**
|
||||
* Verify the data.
|
||||
*
|
||||
* @param publicKey public key to verify
|
||||
* @param signature signature to verify
|
||||
* @param data the data to verify
|
||||
* @return {@code true} if signature is valid, else {@code false}
|
||||
*/
|
||||
boolean verify(PublicKey publicKey, String signature, byte[] data);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,9 @@ import net.i2p.crypto.eddsa.EdDSAEngine;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SignatureException;
|
||||
import java.util.Base64;
|
||||
|
||||
public class Ed25519SignatureManager implements SignatureManager {
|
||||
|
||||
@@ -92,4 +94,15 @@ public class Ed25519SignatureManager implements SignatureManager {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verify(PublicKey publicKey, String signature, byte[] data) {
|
||||
try {
|
||||
EdDSAEngine signEngine = new EdDSAEngine(MessageDigest.getInstance(keyMgr.getKeySpecs().getHashAlgorithm()));
|
||||
signEngine.initVerify(publicKey);
|
||||
signEngine.update(data);
|
||||
return signEngine.verify(Base64.getDecoder().decode(signature));
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,10 @@
|
||||
package io.kamax.mxisd.http.undertow.handler.identity.v1;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import io.kamax.mxisd.exception.BadRequestException;
|
||||
import io.kamax.mxisd.exception.NotAllowedException;
|
||||
import io.kamax.mxisd.http.IsAPIv1;
|
||||
import io.kamax.mxisd.http.undertow.handler.BasicHttpHandler;
|
||||
import io.kamax.mxisd.session.SessionManager;
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -46,20 +43,9 @@ public class SessionTpidUnbindHandler extends BasicHttpHandler {
|
||||
@Override
|
||||
public void handleRequest(HttpServerExchange exchange) {
|
||||
String auth = exchange.getRequestHeaders().getFirst("Authorization");
|
||||
if (StringUtils.isNotEmpty(auth)) {
|
||||
// We have a auth header to process
|
||||
if (StringUtils.startsWith(auth, "X-Matrix ")) {
|
||||
log.warn("A remote host attempted to unbind without proper authorization. Request was denied");
|
||||
log.warn("See https://github.com/kamax-matrix/mxisd/wiki/mxisd-and-your-privacy for more info");
|
||||
throw new NotAllowedException("3PID can only be removed via 3PID sessions, not via Homeserver signature");
|
||||
} else {
|
||||
throw new BadRequestException("Illegal authorization type");
|
||||
}
|
||||
}
|
||||
|
||||
JsonObject body = parseJsonObject(exchange);
|
||||
sessionMgr.unbind(body);
|
||||
sessionMgr.unbind(auth, body);
|
||||
writeBodyAsUtf8(exchange, "{}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,6 +37,6 @@ public interface NotificationHandler {
|
||||
|
||||
void sendForValidation(IThreePidSession session);
|
||||
|
||||
void sendForFraudulentUnbind(ThreePid tpid);
|
||||
void sendForUnbind(ThreePid tpid);
|
||||
|
||||
}
|
||||
|
||||
@@ -78,8 +78,8 @@ public class NotificationManager {
|
||||
ensureMedium(session.getThreePid().getMedium()).sendForValidation(session);
|
||||
}
|
||||
|
||||
public void sendForFraudulentUnbind(ThreePid tpid) throws NotImplementedException {
|
||||
ensureMedium(tpid.getMedium()).sendForFraudulentUnbind(tpid);
|
||||
public void sendForUnbind(ThreePid tpid) throws NotImplementedException {
|
||||
ensureMedium(tpid.getMedium()).sendForUnbind(tpid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,33 +20,49 @@
|
||||
|
||||
package io.kamax.mxisd.session;
|
||||
|
||||
import static io.kamax.mxisd.config.SessionConfig.Policy.PolicyTemplate;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import io.kamax.matrix.MatrixID;
|
||||
import io.kamax.matrix.ThreePid;
|
||||
import io.kamax.matrix._MatrixID;
|
||||
import io.kamax.matrix.json.GsonUtil;
|
||||
import io.kamax.matrix.json.MatrixJson;
|
||||
import io.kamax.mxisd.config.MatrixConfig;
|
||||
import io.kamax.mxisd.config.SessionConfig;
|
||||
import io.kamax.mxisd.crypto.SignatureManager;
|
||||
import io.kamax.mxisd.exception.BadRequestException;
|
||||
import io.kamax.mxisd.exception.NotAllowedException;
|
||||
import io.kamax.mxisd.exception.RemoteHomeServerException;
|
||||
import io.kamax.mxisd.exception.SessionNotValidatedException;
|
||||
import io.kamax.mxisd.exception.SessionUnknownException;
|
||||
import io.kamax.mxisd.lookup.SingleLookupReply;
|
||||
import io.kamax.mxisd.lookup.SingleLookupRequest;
|
||||
import io.kamax.mxisd.lookup.ThreePidValidation;
|
||||
import io.kamax.mxisd.matrix.HomeserverFederationResolver;
|
||||
import io.kamax.mxisd.notification.NotificationManager;
|
||||
import io.kamax.mxisd.storage.IStorage;
|
||||
import io.kamax.mxisd.storage.dao.IThreePidSessionDao;
|
||||
import io.kamax.mxisd.threepid.session.ThreePidSession;
|
||||
import net.i2p.crypto.eddsa.EdDSAPublicKey;
|
||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
|
||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
|
||||
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.Calendar;
|
||||
import java.util.Optional;
|
||||
|
||||
import static io.kamax.mxisd.config.SessionConfig.Policy.PolicyTemplate;
|
||||
|
||||
public class SessionManager {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SessionManager.class);
|
||||
@@ -55,17 +71,26 @@ public class SessionManager {
|
||||
private MatrixConfig mxCfg;
|
||||
private IStorage storage;
|
||||
private NotificationManager notifMgr;
|
||||
private HomeserverFederationResolver resolver;
|
||||
private CloseableHttpClient client;
|
||||
private SignatureManager signatureManager;
|
||||
|
||||
public SessionManager(
|
||||
SessionConfig cfg,
|
||||
MatrixConfig mxCfg,
|
||||
IStorage storage,
|
||||
NotificationManager notifMgr
|
||||
SessionConfig cfg,
|
||||
MatrixConfig mxCfg,
|
||||
IStorage storage,
|
||||
NotificationManager notifMgr,
|
||||
HomeserverFederationResolver resolver,
|
||||
CloseableHttpClient client,
|
||||
SignatureManager signatureManager
|
||||
) {
|
||||
this.cfg = cfg;
|
||||
this.mxCfg = mxCfg;
|
||||
this.storage = storage;
|
||||
this.notifMgr = notifMgr;
|
||||
this.resolver = resolver;
|
||||
this.client = client;
|
||||
this.signatureManager = signatureManager;
|
||||
}
|
||||
|
||||
private ThreePidSession getSession(String sid, String secret) {
|
||||
@@ -98,7 +123,8 @@ public class SessionManager {
|
||||
ThreePidSession session = new ThreePidSession(dao.get());
|
||||
log.info("We already have a session for {}: {}", tpid, session.getId());
|
||||
if (session.getAttempt() < attempt) {
|
||||
log.info("Received attempt {} is greater than stored attempt {}, sending validation communication", attempt, session.getAttempt());
|
||||
log.info("Received attempt {} is greater than stored attempt {}, sending validation communication", attempt,
|
||||
session.getAttempt());
|
||||
notifMgr.sendForValidation(session);
|
||||
log.info("Sent validation notification to {}", tpid);
|
||||
session.increaseAttempt();
|
||||
@@ -166,7 +192,7 @@ public class SessionManager {
|
||||
}
|
||||
|
||||
log.info("Session {}: Binding of {}:{} to Matrix ID {} is accepted",
|
||||
session.getId(), session.getThreePid().getMedium(), session.getThreePid().getAddress(), mxid.getId());
|
||||
session.getId(), session.getThreePid().getMedium(), session.getThreePid().getAddress(), mxid.getId());
|
||||
|
||||
SingleLookupRequest request = new SingleLookupRequest();
|
||||
request.setType(session.getThreePid().getMedium());
|
||||
@@ -174,7 +200,7 @@ public class SessionManager {
|
||||
return new SingleLookupReply(request, mxid);
|
||||
}
|
||||
|
||||
public void unbind(JsonObject reqData) {
|
||||
public void unbind(String auth, JsonObject reqData) {
|
||||
_MatrixID mxid;
|
||||
try {
|
||||
mxid = MatrixID.asAcceptable(GsonUtil.getStringOrThrow(reqData, "mxid"));
|
||||
@@ -186,6 +212,128 @@ public class SessionManager {
|
||||
String secret = GsonUtil.getStringOrNull(reqData, "client_secret");
|
||||
ThreePid tpid = GsonUtil.get().fromJson(GsonUtil.getObj(reqData, "threepid"), ThreePid.class);
|
||||
|
||||
if (StringUtils.isNotBlank(sid) && StringUtils.isNotBlank(secret)) {
|
||||
checkSession(sid, secret, tpid, mxid);
|
||||
} else if (StringUtils.isNotBlank(auth)) {
|
||||
checkAuthorization(auth, reqData);
|
||||
} else {
|
||||
throw new NotAllowedException("Unable to validate request");
|
||||
}
|
||||
|
||||
// TODO make invalid all 3PID with specified medium and address.
|
||||
}
|
||||
|
||||
private void checkAuthorization(String auth, JsonObject reqData) {
|
||||
if (!auth.startsWith("X-Matrix ")) {
|
||||
throw new NotAllowedException("Wrong authorization header");
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(mxCfg.getTrustedIdServer())) {
|
||||
throw new NotAllowedException("Unable to verify request, missing `matrix.trustedIdServer` variable");
|
||||
}
|
||||
|
||||
String[] params = auth.substring("X-Matrix ".length()).split(",");
|
||||
|
||||
String origin = null;
|
||||
String key = null;
|
||||
String sig = null;
|
||||
for (String param : params) {
|
||||
String[] paramItems = param.split("=");
|
||||
String paramKey = paramItems[0];
|
||||
String paramValue = paramItems[1];
|
||||
switch (paramKey) {
|
||||
case "origin":
|
||||
origin = removeQuotes(paramValue);
|
||||
break;
|
||||
case "key":
|
||||
key = removeQuotes(paramValue);
|
||||
break;
|
||||
case "sig":
|
||||
sig = removeQuotes(paramValue);
|
||||
break;
|
||||
default:
|
||||
log.error("Unknown parameter: {}", param);
|
||||
throw new BadRequestException("Authorization with unknown parameter");
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(origin) || StringUtils.isBlank(key) || StringUtils.isBlank(sig)) {
|
||||
log.error("Missing required parameters");
|
||||
throw new BadRequestException("Missing required header parameters");
|
||||
}
|
||||
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("method", "POST");
|
||||
jsonObject.addProperty("uri", "/_matrix/identity/api/v1/3pid/unbind");
|
||||
jsonObject.addProperty("origin", origin);
|
||||
jsonObject.addProperty("destination_is", mxCfg.getTrustedIdServer());
|
||||
jsonObject.add("content", reqData);
|
||||
|
||||
String canonical = MatrixJson.encodeCanonical(jsonObject);
|
||||
|
||||
String originUrl = resolver.resolve(origin).toString();
|
||||
|
||||
validateServerKey(key, sig, canonical, originUrl);
|
||||
}
|
||||
|
||||
private String removeQuotes(String origin) {
|
||||
return origin.startsWith("\"") && origin.endsWith("\"") ? origin.substring(1, origin.length() - 1) : origin;
|
||||
}
|
||||
|
||||
private void validateServerKey(String key, String signature, String canonical, String originUrl) {
|
||||
HttpGet request = new HttpGet(originUrl + "/_matrix/key/v2/server");
|
||||
log.info("Get keys from the server {}", request.getURI());
|
||||
try (CloseableHttpResponse response = client.execute(request)) {
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
log.info("Answer code: {}", statusCode);
|
||||
if (statusCode == 200) {
|
||||
verifyKey(key, signature, canonical, response);
|
||||
} else {
|
||||
throw new RemoteHomeServerException("Unable to fetch server keys.");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
String message = "Unable to get server keys: " + originUrl;
|
||||
log.error(message, e);
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyKey(String key, String signature, String canonical, CloseableHttpResponse response) throws IOException {
|
||||
final String content = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
log.info("Answer body: {}", content);
|
||||
final JsonObject responseObject = GsonUtil.parseObj(content);
|
||||
final long validUntilTs = GsonUtil.getLong(responseObject, "valid_until_ts");
|
||||
|
||||
final Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTimeInMillis(validUntilTs);
|
||||
if (calendar.before(Calendar.getInstance())) {
|
||||
final String msg = "Key is expired";
|
||||
log.error(msg);
|
||||
throw new RemoteHomeServerException(msg);
|
||||
}
|
||||
|
||||
final JsonObject verifyKeys = GsonUtil.getObj(responseObject, "verify_keys");
|
||||
final JsonObject keyObject = GsonUtil.getObj(verifyKeys, key);
|
||||
final String publicKey = GsonUtil.getStringOrNull(keyObject, "key");
|
||||
|
||||
if (StringUtils.isBlank(publicKey)) {
|
||||
throw new RemoteHomeServerException("Missing server key.");
|
||||
}
|
||||
|
||||
EdDSANamedCurveSpec ed25519CurveSpec = EdDSANamedCurveTable.ED_25519_CURVE_SPEC;
|
||||
EdDSAPublicKeySpec publicKeySpec = new EdDSAPublicKeySpec(Base64.getDecoder().decode(publicKey), ed25519CurveSpec);
|
||||
EdDSAPublicKey dsaPublicKey = new EdDSAPublicKey(publicKeySpec);
|
||||
|
||||
final boolean verificationResult = signatureManager.verify(dsaPublicKey, signature, canonical.getBytes(StandardCharsets.UTF_8));
|
||||
log.info("Verification result: {}", verificationResult);
|
||||
if (!verificationResult) {
|
||||
throw new RemoteHomeServerException("Unable to verify request.");
|
||||
}
|
||||
|
||||
log.info("Request was authorized.");
|
||||
}
|
||||
|
||||
private void checkSession(String sid, String secret, ThreePid tpid, _MatrixID mxid) {
|
||||
// We ensure the session was validated
|
||||
ThreePidSession session = getSessionIfValidated(sid, secret);
|
||||
|
||||
@@ -199,8 +347,6 @@ public class SessionManager {
|
||||
throw new NotAllowedException("Only Matrix IDs from domain " + mxCfg.getDomain() + " can be unbound");
|
||||
}
|
||||
|
||||
log.info("Session {}: Unbinding of {}:{} to Matrix ID {} is accepted",
|
||||
session.getId(), session.getThreePid().getMedium(), session.getThreePid().getAddress(), mxid.getId());
|
||||
log.info("Request was authorized.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -79,9 +79,9 @@ public abstract class GenericTemplateNotificationGenerator extends PlaceholderNo
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getForFraudulentUnbind(ThreePid tpid) {
|
||||
log.info("Generating notification content for fraudulent unbind");
|
||||
return populateForFraudulentUndind(tpid, getTemplateContent(cfg.getSession().getUnbind().getFraudulent()));
|
||||
public String getForNotificationUnbind(ThreePid tpid) {
|
||||
log.info("Generating notification content for unbind");
|
||||
return populateForNotificationUndind(tpid, getTemplateContent(cfg.getSession().getUnbind().getNotification()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,6 +37,6 @@ public interface NotificationGenerator {
|
||||
|
||||
String getForValidation(IThreePidSession session);
|
||||
|
||||
String getForFraudulentUnbind(ThreePid tpid);
|
||||
String getForNotificationUnbind(ThreePid tpid);
|
||||
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ public abstract class PlaceholderNotificationGenerator {
|
||||
.replace("%NEXT_URL%", validationLink);
|
||||
}
|
||||
|
||||
protected String populateForFraudulentUndind(ThreePid tpid, String input) {
|
||||
protected String populateForNotificationUndind(ThreePid tpid, String input) {
|
||||
return populateForCommon(tpid, input);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,8 +73,8 @@ public abstract class GenericNotificationHandler<A extends ThreePidConnector, B
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendForFraudulentUnbind(ThreePid tpid) {
|
||||
send(connector, tpid.getAddress(), generator.getForFraudulentUnbind(tpid));
|
||||
public void sendForUnbind(ThreePid tpid) {
|
||||
send(connector, tpid.getAddress(), generator.getForNotificationUnbind(tpid));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -129,10 +129,10 @@ public class EmailSendGridNotificationHandler extends PlaceholderNotificationGen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendForFraudulentUnbind(ThreePid tpid) {
|
||||
EmailTemplate template = cfg.getTemplates().getSession().getUnbind().getFraudulent();
|
||||
public void sendForUnbind(ThreePid tpid) {
|
||||
EmailTemplate template = cfg.getTemplates().getSession().getUnbind();
|
||||
if (StringUtils.isAllBlank(template.getBody().getText(), template.getBody().getHtml())) {
|
||||
throw new FeatureNotAvailable("No template has been configured for fraudulent unbind notifications");
|
||||
throw new FeatureNotAvailable("No template has been configured for unbind notifications");
|
||||
}
|
||||
|
||||
Email email = getEmail();
|
||||
|
||||
Reference in New Issue
Block a user