From 635f6fdbe794a9e096801aa5ebd102c7612aac67 Mon Sep 17 00:00:00 2001 From: Max Dor Date: Fri, 1 Feb 2019 02:34:52 +0100 Subject: [PATCH] Implementation for blocking fraudulent 3PID /unbind attempts --- .../notification/sendgrid-handler.md | 6 + .../notification/template-generator.md | 4 +- docs/threepids/session/session.md | 11 ++ src/main/java/io/kamax/mxisd/HttpMxisd.java | 2 +- src/main/java/io/kamax/mxisd/Mxisd.java | 2 +- .../io/kamax/mxisd/config/SessionConfig.java | 37 ++++++ .../connector/EmailSendGridConfig.java | 39 +++++- .../threepid/medium/EmailTemplateConfig.java | 1 + .../medium/GenericTemplateConfig.java | 23 ++++ .../medium/PhoneSmsTemplateConfig.java | 1 + .../identity/v1/SessionTpidUnbindHandler.java | 40 ++---- .../notification/NotificationHandler.java | 3 + .../notification/NotificationManager.java | 5 + .../kamax/mxisd/session/SessionMananger.java | 62 ++++++++- .../GenericTemplateNotificationGenerator.java | 7 + .../generator/NotificationGenerator.java | 3 + .../PlaceholderNotificationGenerator.java | 4 + .../GenericNotificationHandler.java | 6 + .../EmailSendGridNotificationHandler.java | 16 ++- .../threepids/email/unbind-fraudulent.eml | 125 ++++++++++++++++++ .../threepids/sms/unbind-fraudulent.txt | 1 + 21 files changed, 361 insertions(+), 37 deletions(-) create mode 100644 src/main/resources/threepids/email/unbind-fraudulent.eml create mode 100644 src/main/resources/threepids/sms/unbind-fraudulent.txt diff --git a/docs/threepids/notification/sendgrid-handler.md b/docs/threepids/notification/sendgrid-handler.md index 9887668..5719d18 100644 --- a/docs/threepids/notification/sendgrid-handler.md +++ b/docs/threepids/notification/sendgrid-handler.md @@ -36,4 +36,10 @@ notification: body: text: html: + unbind: + fraudulent: + subject: + body: + text: + html: ``` diff --git a/docs/threepids/notification/template-generator.md b/docs/threepids/notification/template-generator.md index 3691a78..9a10af7 100644 --- a/docs/threepids/notification/template-generator.md +++ b/docs/threepids/notification/template-generator.md @@ -20,7 +20,9 @@ threepid: session: validation: local: '/path/to/validate-local-template.eml' - remote: 'path/to/validate-remote-template.eml' + remote: '/path/to/validate-remote-template.eml' + unbind: + frandulent: '/path/to/unbind-fraudulent-template.eml' generic: matrixId: '/path/to/mxid-invite-template.eml' ``` diff --git a/docs/threepids/session/session.md b/docs/threepids/session/session.md index 4cdaece..60dce6b 100644 --- a/docs/threepids/session/session.md +++ b/docs/threepids/session/session.md @@ -149,6 +149,9 @@ session: toRemote: enabled: true server: 'configExample' # Not to be included in config! Already present in default config! + unbind: + fraudulent: + sendWarning: true # DO NOT COPY/PASTE THIS IN YOUR CONFIGURATION # CONFIGURATION EXAMPLE ``` @@ -168,6 +171,14 @@ Each scope is divided into three parts: If both `toLocal` and `toRemote` are enabled, the user will be offered to initiate a remote session once their 3PID locally validated. +--- + +`unbind.fraudulent` controls warning notifications if an illegal/fraudulent 3PID removal is attempted on the Identity server. +This is directly related to synapse disregard for privacy and new GDPR laws in Europe in an attempt to inform users about +potential privacy leaks. + +For more information, see the corresponding [synapse issue](https://github.com/matrix-org/synapse/issues/4540). + ### Web views Once a user click on a validation link, it is taken to the Identity Server validation page where the token is submitted. If the session or token is invalid, an error page is displayed. diff --git a/src/main/java/io/kamax/mxisd/HttpMxisd.java b/src/main/java/io/kamax/mxisd/HttpMxisd.java index 4962622..2b7f270 100644 --- a/src/main/java/io/kamax/mxisd/HttpMxisd.java +++ b/src/main/java/io/kamax/mxisd/HttpMxisd.java @@ -85,7 +85,7 @@ public class HttpMxisd { .post(SessionValidateHandler.Path, sessValidateHandler) .get(SessionTpidGetValidatedHandler.Path, SaneHandler.around(new SessionTpidGetValidatedHandler(m.getSession()))) .post(SessionTpidBindHandler.Path, SaneHandler.around(new SessionTpidBindHandler(m.getSession(), m.getInvitationManager()))) - .post(SessionTpidUnbindHandler.Path, SaneHandler.around(new SessionTpidUnbindHandler())) + .post(SessionTpidUnbindHandler.Path, SaneHandler.around(new SessionTpidUnbindHandler(m.getSession()))) .get(RemoteIdentityAPIv1.SESSION_REQUEST_TOKEN, SaneHandler.around(new RemoteSessionStartHandler(m.getSession(), m.getConfig().getView()))) .get(RemoteIdentityAPIv1.SESSION_CHECK, SaneHandler.around(new RemoteSessionCheckHandler(m.getSession(), m.getConfig().getView()))) diff --git a/src/main/java/io/kamax/mxisd/Mxisd.java b/src/main/java/io/kamax/mxisd/Mxisd.java index 4640f68..0d8dbac 100644 --- a/src/main/java/io/kamax/mxisd/Mxisd.java +++ b/src/main/java/io/kamax/mxisd/Mxisd.java @@ -102,7 +102,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 SessionMananger(cfg.getSession(), cfg.getMatrix(), store, notifMgr, httpClient); + sessMgr = new SessionMananger(cfg.getSession(), cfg.getMatrix(), store, notifMgr, idStrategy, httpClient); invMgr = new InvitationManager(cfg.getInvite(), store, idStrategy, signMgr, fedDns, notifMgr); authMgr = new AuthManager(cfg, AuthProviders.get(), idStrategy, invMgr, clientDns, httpClient); dirMgr = new DirectoryManager(cfg.getDirectory(), clientDns, httpClient, DirectoryProviders.get()); diff --git a/src/main/java/io/kamax/mxisd/config/SessionConfig.java b/src/main/java/io/kamax/mxisd/config/SessionConfig.java index 5ac535b..8f0af91 100644 --- a/src/main/java/io/kamax/mxisd/config/SessionConfig.java +++ b/src/main/java/io/kamax/mxisd/config/SessionConfig.java @@ -125,6 +125,34 @@ public class SessionConfig { } + public static class PolicyUnbind { + + public static class PolicyUnbindFraudulent { + + private boolean sendWarning = true; + + public boolean getSendWarning() { + return sendWarning; + } + + public void setSendWarning(boolean sendWarning) { + this.sendWarning = sendWarning; + } + } + + + private PolicyUnbindFraudulent fraudulent = new PolicyUnbindFraudulent(); + + public PolicyUnbindFraudulent getFraudulent() { + return fraudulent; + } + + public void setFraudulent(PolicyUnbindFraudulent fraudulent) { + this.fraudulent = fraudulent; + } + + } + public Policy() { validation.enabled = true; validation.forLocal.enabled = true; @@ -139,6 +167,7 @@ public class SessionConfig { } private PolicyTemplate validation = new PolicyTemplate(); + private PolicyUnbind unbind = new PolicyUnbind(); public PolicyTemplate getValidation() { return validation; @@ -148,6 +177,14 @@ public class SessionConfig { this.validation = validation; } + public PolicyUnbind getUnbind() { + return unbind; + } + + public void setUnbind(PolicyUnbind unbind) { + this.unbind = unbind; + } + } private Policy policy = new Policy(); diff --git a/src/main/java/io/kamax/mxisd/config/threepid/connector/EmailSendGridConfig.java b/src/main/java/io/kamax/mxisd/config/threepid/connector/EmailSendGridConfig.java index b6a3e7a..956fdf7 100644 --- a/src/main/java/io/kamax/mxisd/config/threepid/connector/EmailSendGridConfig.java +++ b/src/main/java/io/kamax/mxisd/config/threepid/connector/EmailSendGridConfig.java @@ -115,7 +115,7 @@ public class EmailSendGridConfig { public static class Templates { - public static class TemplateSession { + public static class TemplateSessionValidation { private EmailTemplate local = new EmailTemplate(); private EmailTemplate remote = new EmailTemplate(); @@ -137,6 +137,43 @@ public class EmailSendGridConfig { } } + 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 TemplateSessionValidation validation = new TemplateSessionValidation(); + private TemplateSessionUnbind unbind = new TemplateSessionUnbind(); + + public TemplateSessionValidation getValidation() { + return validation; + } + + public void setValidation(TemplateSessionValidation validation) { + this.validation = validation; + } + + public TemplateSessionUnbind getUnbind() { + return unbind; + } + + public void setUnbind(TemplateSessionUnbind unbind) { + this.unbind = unbind; + } + + } + private EmailTemplate invite = new EmailTemplate(); private TemplateSession session = new TemplateSession(); private Map generic = new HashMap<>(); diff --git a/src/main/java/io/kamax/mxisd/config/threepid/medium/EmailTemplateConfig.java b/src/main/java/io/kamax/mxisd/config/threepid/medium/EmailTemplateConfig.java index bd8b849..712a52e 100644 --- a/src/main/java/io/kamax/mxisd/config/threepid/medium/EmailTemplateConfig.java +++ b/src/main/java/io/kamax/mxisd/config/threepid/medium/EmailTemplateConfig.java @@ -32,6 +32,7 @@ public class EmailTemplateConfig extends GenericTemplateConfig { getGeneric().put("matrixId", "classpath:/threepids/email/mxid-template.eml"); getSession().getValidation().setLocal("classpath:/threepids/email/validate-local-template.eml"); getSession().getValidation().setRemote("classpath:/threepids/email/validate-remote-template.eml"); + getSession().getUnbind().setFraudulent("classpath:/threepids/email/unbind-fraudulent.eml"); } public EmailTemplateConfig build() { diff --git a/src/main/java/io/kamax/mxisd/config/threepid/medium/GenericTemplateConfig.java b/src/main/java/io/kamax/mxisd/config/threepid/medium/GenericTemplateConfig.java index d29f2cf..434829e 100644 --- a/src/main/java/io/kamax/mxisd/config/threepid/medium/GenericTemplateConfig.java +++ b/src/main/java/io/kamax/mxisd/config/threepid/medium/GenericTemplateConfig.java @@ -62,7 +62,22 @@ public class GenericTemplateConfig { } + public static class SessionUnbind { + + private String fraudulent; + + public String getFraudulent() { + return fraudulent; + } + + public void setFraudulent(String fraudulent) { + this.fraudulent = fraudulent; + } + + } + private SessionValidation validation = new SessionValidation(); + private SessionUnbind unbind = new SessionUnbind(); public SessionValidation getValidation() { return validation; @@ -72,6 +87,14 @@ public class GenericTemplateConfig { this.validation = validation; } + public SessionUnbind getUnbind() { + return unbind; + } + + public void setUnbind(SessionUnbind unbind) { + this.unbind = unbind; + } + } private String invite; diff --git a/src/main/java/io/kamax/mxisd/config/threepid/medium/PhoneSmsTemplateConfig.java b/src/main/java/io/kamax/mxisd/config/threepid/medium/PhoneSmsTemplateConfig.java index 42352b2..909d6fa 100644 --- a/src/main/java/io/kamax/mxisd/config/threepid/medium/PhoneSmsTemplateConfig.java +++ b/src/main/java/io/kamax/mxisd/config/threepid/medium/PhoneSmsTemplateConfig.java @@ -32,6 +32,7 @@ public class PhoneSmsTemplateConfig extends GenericTemplateConfig { getGeneric().put("matrixId", "classpath:/threepids/email/mxid-template.eml"); getSession().getValidation().setLocal("classpath:/threepids/sms/validate-local-template.txt"); getSession().getValidation().setRemote("classpath:/threepids/sms/validate-remote-template.txt"); + getSession().getUnbind().setFraudulent("classpath:/threepids/sms/unbind-fraudulent.txt"); } public PhoneSmsTemplateConfig build() { diff --git a/src/main/java/io/kamax/mxisd/http/undertow/handler/identity/v1/SessionTpidUnbindHandler.java b/src/main/java/io/kamax/mxisd/http/undertow/handler/identity/v1/SessionTpidUnbindHandler.java index dd3b146..4cdd05a 100644 --- a/src/main/java/io/kamax/mxisd/http/undertow/handler/identity/v1/SessionTpidUnbindHandler.java +++ b/src/main/java/io/kamax/mxisd/http/undertow/handler/identity/v1/SessionTpidUnbindHandler.java @@ -21,10 +21,9 @@ package io.kamax.mxisd.http.undertow.handler.identity.v1; import com.google.gson.JsonObject; -import io.kamax.mxisd.exception.FeatureNotAvailable; -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.SessionMananger; import io.undertow.server.HttpServerExchange; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,38 +32,19 @@ public class SessionTpidUnbindHandler extends BasicHttpHandler { public static final String Path = IsAPIv1.Base + "/3pid/unbind"; - private transient final Logger log = LoggerFactory.getLogger(SessionTpidUnbindHandler.class); + private static final Logger log = LoggerFactory.getLogger(SessionTpidUnbindHandler.class); + + private final SessionMananger sessMgr; + + public SessionTpidUnbindHandler(SessionMananger sessMgr) { + this.sessMgr = sessMgr; + } @Override public void handleRequest(HttpServerExchange exchange) { JsonObject body = parseJsonObject(exchange); - - // TODO also check for HS header to know which domain attempting the unbind - if (body.entrySet().size() == 2 && body.has("mxisd") && body.has("threepid")) { - /* This is a HS request to remove a 3PID and is considered: - * - An attack on user privacy - * - A baffling spec breakage requiring IS and HS 3PID info to be independent [1] - * - A baffling spec breakage that 3PID (un)bind is only one way [2] - * - * Given the lack of response on our extensive feedback on the proposal [3] which has not landed in the spec yet [4], - * We'll be denying such unbind requests and will inform users using their 3PID that a fraudulent attempt of - * removing their 3PID binding has been attempting but blocked. - * - * [1]: https://matrix.org/docs/spec/client_server/r0.4.0.html#adding-account-administrative-contact-information - * [2]: https://matrix.org/docs/spec/identity_service/r0.1.0.html#privacy - * [3]: https://docs.google.com/document/d/135g2muVxmuml0iUnLoTZxk8M2ZSt3kJzg81chGh51yg/edit - * [4]: https://github.com/matrix-org/matrix-doc/issues/1194 - */ - - log.warn("A remote host attempted to unbind without proper authorization. Request was denied"); - - // TODO notify the 3PID owner - - throw new NotAllowedException("You have attempted to alter 3PID bindings, which can only be done by the 3PID owner directly. " + - "We have informed the 3PID owner of your fraudulent attempt."); - } - - throw new FeatureNotAvailable("Unbind using a 3PID session is not defined in the spec"); + sessMgr.unbind(body); + writeBodyAsUtf8(exchange, "{}"); } } diff --git a/src/main/java/io/kamax/mxisd/notification/NotificationHandler.java b/src/main/java/io/kamax/mxisd/notification/NotificationHandler.java index a1418c5..1b7fbd8 100644 --- a/src/main/java/io/kamax/mxisd/notification/NotificationHandler.java +++ b/src/main/java/io/kamax/mxisd/notification/NotificationHandler.java @@ -20,6 +20,7 @@ package io.kamax.mxisd.notification; +import io.kamax.matrix.ThreePid; import io.kamax.mxisd.as.IMatrixIdInvite; import io.kamax.mxisd.invitation.IThreePidInviteReply; import io.kamax.mxisd.threepid.session.IThreePidSession; @@ -38,4 +39,6 @@ public interface NotificationHandler { void sendForRemoteValidation(IThreePidSession session); + void sendForFraudulentUnbind(ThreePid tpid); + } diff --git a/src/main/java/io/kamax/mxisd/notification/NotificationManager.java b/src/main/java/io/kamax/mxisd/notification/NotificationManager.java index 813dd3c..5091f86 100644 --- a/src/main/java/io/kamax/mxisd/notification/NotificationManager.java +++ b/src/main/java/io/kamax/mxisd/notification/NotificationManager.java @@ -20,6 +20,7 @@ package io.kamax.mxisd.notification; +import io.kamax.matrix.ThreePid; import io.kamax.mxisd.as.IMatrixIdInvite; import io.kamax.mxisd.config.threepid.notification.NotificationConfig; import io.kamax.mxisd.exception.NotImplementedException; @@ -81,4 +82,8 @@ public class NotificationManager { ensureMedium(session.getThreePid().getMedium()).sendForRemoteValidation(session); } + public void sendForFraudulentUnbind(ThreePid tpid) throws NotImplementedException { + ensureMedium(tpid.getMedium()).sendForFraudulentUnbind(tpid); + } + } diff --git a/src/main/java/io/kamax/mxisd/session/SessionMananger.java b/src/main/java/io/kamax/mxisd/session/SessionMananger.java index 5f81898..b0b51a5 100644 --- a/src/main/java/io/kamax/mxisd/session/SessionMananger.java +++ b/src/main/java/io/kamax/mxisd/session/SessionMananger.java @@ -28,12 +28,15 @@ import io.kamax.matrix.MatrixID; import io.kamax.matrix.ThreePid; import io.kamax.matrix.ThreePidMedium; import io.kamax.matrix._MatrixID; +import io.kamax.matrix.json.GsonUtil; import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.SessionConfig; import io.kamax.mxisd.exception.*; import io.kamax.mxisd.http.io.identity.RequestTokenResponse; import io.kamax.mxisd.http.undertow.handler.identity.v1.RemoteIdentityAPIv1; +import io.kamax.mxisd.lookup.SingleLookupReply; import io.kamax.mxisd.lookup.ThreePidValidation; +import io.kamax.mxisd.lookup.strategy.LookupStrategy; import io.kamax.mxisd.matrix.IdentityServerUtils; import io.kamax.mxisd.notification.NotificationManager; import io.kamax.mxisd.storage.IStorage; @@ -71,6 +74,7 @@ public class SessionMananger { private MatrixConfig mxCfg; private IStorage storage; private NotificationManager notifMgr; + private LookupStrategy lookupMgr; private GsonParser parser = new GsonParser(); private PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); // FIXME refactor for sessions handling their own stuff @@ -78,11 +82,19 @@ public class SessionMananger { // FIXME export into central class, set version private CloseableHttpClient client; - public SessionMananger(SessionConfig cfg, MatrixConfig mxCfg, IStorage storage, NotificationManager notifMgr, CloseableHttpClient client) { + public SessionMananger( + SessionConfig cfg, + MatrixConfig mxCfg, + IStorage storage, + NotificationManager notifMgr, + LookupStrategy lookupMgr, + CloseableHttpClient client + ) { this.cfg = cfg; this.mxCfg = mxCfg; this.storage = storage; this.notifMgr = notifMgr; + this.lookupMgr = lookupMgr; this.client = client; } @@ -259,6 +271,54 @@ public class SessionMananger { } } + public void unbind(JsonObject reqData) { + // TODO also check for HS header to know which domain attempting the unbind + if (reqData.entrySet().size() == 2 && reqData.has("mxid") && reqData.has("threepid")) { + /* This is a HS request to remove a 3PID and is considered: + * - An attack on user privacy + * - A baffling spec breakage requiring IS and HS 3PID info to be independent [1] + * - A baffling spec breakage that 3PID (un)bind is only one way [2] + * + * Given the lack of response on our extensive feedback on the proposal [3] which has not landed in the spec yet [4], + * We'll be denying such unbind requests and will inform users using their 3PID that a fraudulent attempt of + * removing their 3PID binding has been attempted and blocked. + * + * [1]: https://matrix.org/docs/spec/client_server/r0.4.0.html#adding-account-administrative-contact-information + * [2]: https://matrix.org/docs/spec/identity_service/r0.1.0.html#privacy + * [3]: https://docs.google.com/document/d/135g2muVxmuml0iUnLoTZxk8M2ZSt3kJzg81chGh51yg/edit + * [4]: https://github.com/matrix-org/matrix-doc/issues/1194 + */ + + log.warn("A remote host attempted to unbind without proper authorization. Request was denied"); + + if (!cfg.getPolicy().getUnbind().getFraudulent().getSendWarning()) { + log.info("Not sending notification to 3PID owner as per configuration"); + } else { + log.info("Sending notification to 3PID owner as per configuration"); + + ThreePid tpid = GsonUtil.get().fromJson(GsonUtil.getObj(reqData, "threepid"), ThreePid.class); + Optional lookup = lookupMgr.findLocal(tpid.getMedium(), tpid.getAddress()); + if (!lookup.isPresent()) { + log.info("No 3PID owner found, not sending any notification"); + } else { + log.info("3PID owner found, sending notification"); + try { + notifMgr.sendForFraudulentUnbind(tpid); + log.info("Notification sent"); + } catch (NotImplementedException e) { + log.warn("Unable to send notification: {}", e.getMessage()); + } catch (RuntimeException e) { + log.warn("Unable to send notification due to unknown error. See stacktrace below", e); + } + } + } + } + + log.info("Denying request"); + throw new NotAllowedException("You have attempted to alter 3PID bindings, which can only be done by the 3PID owner directly. " + + "We have informed the 3PID owner of your fraudulent attempt."); + } + public IThreePidSession createRemote(String sid, String secret) { ThreePidSession session = getSessionIfValidated(sid, secret); log.info("Creating remote 3PID session for {} with local session [{}] to {}", session.getThreePid(), sid); diff --git a/src/main/java/io/kamax/mxisd/threepid/generator/GenericTemplateNotificationGenerator.java b/src/main/java/io/kamax/mxisd/threepid/generator/GenericTemplateNotificationGenerator.java index e34ef63..f6abde1 100644 --- a/src/main/java/io/kamax/mxisd/threepid/generator/GenericTemplateNotificationGenerator.java +++ b/src/main/java/io/kamax/mxisd/threepid/generator/GenericTemplateNotificationGenerator.java @@ -20,6 +20,7 @@ package io.kamax.mxisd.threepid.generator; +import io.kamax.matrix.ThreePid; import io.kamax.mxisd.as.IMatrixIdInvite; import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.ServerConfig; @@ -82,4 +83,10 @@ public abstract class GenericTemplateNotificationGenerator extends PlaceholderNo return populateForRemoteValidation(session, getTemplateContent(cfg.getSession().getValidation().getRemote())); } + @Override + public String getForFraudulentUnbind(ThreePid tpid) { + log.info("Generating notification content for fraudulent unbind"); + return populateForFraudulentUndind(tpid, getTemplateContent(cfg.getSession().getUnbind().getFraudulent())); + } + } diff --git a/src/main/java/io/kamax/mxisd/threepid/generator/NotificationGenerator.java b/src/main/java/io/kamax/mxisd/threepid/generator/NotificationGenerator.java index ddfcc3a..3e6ade1 100644 --- a/src/main/java/io/kamax/mxisd/threepid/generator/NotificationGenerator.java +++ b/src/main/java/io/kamax/mxisd/threepid/generator/NotificationGenerator.java @@ -20,6 +20,7 @@ package io.kamax.mxisd.threepid.generator; +import io.kamax.matrix.ThreePid; import io.kamax.mxisd.as.IMatrixIdInvite; import io.kamax.mxisd.invitation.IThreePidInviteReply; import io.kamax.mxisd.threepid.session.IThreePidSession; @@ -38,4 +39,6 @@ public interface NotificationGenerator { String getForRemoteValidation(IThreePidSession session); + String getForFraudulentUnbind(ThreePid tpid); + } diff --git a/src/main/java/io/kamax/mxisd/threepid/generator/PlaceholderNotificationGenerator.java b/src/main/java/io/kamax/mxisd/threepid/generator/PlaceholderNotificationGenerator.java index eb7a57f..34d6e05 100644 --- a/src/main/java/io/kamax/mxisd/threepid/generator/PlaceholderNotificationGenerator.java +++ b/src/main/java/io/kamax/mxisd/threepid/generator/PlaceholderNotificationGenerator.java @@ -106,4 +106,8 @@ public abstract class PlaceholderNotificationGenerator { return populateForValidation(session, input); } + protected String populateForFraudulentUndind(ThreePid tpid, String input) { + return populateForCommon(tpid, input); + } + } diff --git a/src/main/java/io/kamax/mxisd/threepid/notification/GenericNotificationHandler.java b/src/main/java/io/kamax/mxisd/threepid/notification/GenericNotificationHandler.java index fd3a5f2..3b4f72a 100644 --- a/src/main/java/io/kamax/mxisd/threepid/notification/GenericNotificationHandler.java +++ b/src/main/java/io/kamax/mxisd/threepid/notification/GenericNotificationHandler.java @@ -20,6 +20,7 @@ package io.kamax.mxisd.threepid.notification; +import io.kamax.matrix.ThreePid; import io.kamax.mxisd.as.IMatrixIdInvite; import io.kamax.mxisd.exception.ConfigurationException; import io.kamax.mxisd.invitation.IThreePidInviteReply; @@ -76,4 +77,9 @@ public abstract class GenericNotificationHandler + + + + + + + + + + + +
+

Hi,

+ +

THIS IS IMPORTANT, PLEASE READ CAREFULLY.
+If you are the system administrator of the Matrix installation, read the second section.

+ +

This is a notification email that a possibly unauthorized entity has attempted to alter your + 3PIDs (email, phone numbers, etc.) settings. The request was denied and no change has been made.

+ +

This is so you are aware of a possible failure in case you just tried to remove a 3PID from your account.

+ +

If you do not understand this email, please forward it to your System administrator.

+ +
+ +

As the system administrator:

+ +

If you are using synapse as a Homeserver, this is a known issue and abuse of separation of concerns. As a privacy-centric + product and given that it is not possible to remove 3PIDs using mxisd as those only exists in your Identity stores, the + request was actively blocked.

+ +

We have open an issue on the synapse repos to reflect the related privacy concerns and GDPR violation(s) and would + appreciate if you could comment on it or simply adds a thumbs up so the concerns are finally dealt with by the synapse dev team.
+ Issue: https://github.com/matrix-org/synapse/issues/4540

+ +

If you are using another Homeserver or this came following no action from your own users, then you have been the target + of an unbind attack from a rogue entity which was blocked. You may want to check your logs to see the exact source of + the attack and take relevant actions following your policy.

+ +

If you would like to disable these notifications, please see the 3PID sessions configuration documentation.

+ +

Thanks,

+ +

%DOMAIN_PRETTY% Admins

+
+ + +--M3yzHl5YZehm9v4bAM8sKEdcOoVnRnKR-- + +--7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ-- diff --git a/src/main/resources/threepids/sms/unbind-fraudulent.txt b/src/main/resources/threepids/sms/unbind-fraudulent.txt new file mode 100644 index 0000000..fd2f738 --- /dev/null +++ b/src/main/resources/threepids/sms/unbind-fraudulent.txt @@ -0,0 +1 @@ +INFORMATIONAL ONLY - Someone attempted to change your Matrix 3PIDs, with a potential data leak. Please contact your system administrator. \ No newline at end of file