aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Hunt <will@half-shot.uk>2020-12-18 14:36:59 +0000
committerGitHub <noreply@github.com>2020-12-18 14:36:59 +0000
commite4d1f0958fb297d4a8cb112de794e62dee8fbcae (patch)
treec4e8832d81bebaeb282f77c2fa9100a9360175be
parent4fe4c180e638985cbb88beb764da9a2c3273069a (diff)
Do not check if a username is exclusive if the request is for an appservice in /register (#1652)
* Do not check if a username is exclusive if the request is for an appservice in /register * remove useless comment * Move statements * fix broken test * Also fix the senderLocalpart problem * Check domain name is ours * Handle accessTokenErr * Return unauthorised instead of forbidden Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
-rw-r--r--clientapi/routing/register.go86
1 files changed, 50 insertions, 36 deletions
diff --git a/clientapi/routing/register.go b/clientapi/routing/register.go
index c6365c67..820c7484 100644
--- a/clientapi/routing/register.go
+++ b/clientapi/routing/register.go
@@ -328,7 +328,22 @@ func UserIDIsWithinApplicationServiceNamespace(
userID string,
appservice *config.ApplicationService,
) bool {
+
+ var local, domain, err = gomatrixserverlib.SplitID('@', userID)
+ if err != nil {
+ // Not a valid userID
+ return false
+ }
+
+ if domain != cfg.Matrix.ServerName {
+ return false
+ }
+
if appservice != nil {
+ if appservice.SenderLocalpart == local {
+ return true
+ }
+
// Loop through given application service's namespaces and see if any match
for _, namespace := range appservice.NamespaceMap["users"] {
// AS namespaces are checked for validity in config
@@ -341,6 +356,9 @@ func UserIDIsWithinApplicationServiceNamespace(
// Loop through all known application service's namespaces and see if any match
for _, knownAppService := range cfg.Derived.ApplicationServices {
+ if knownAppService.SenderLocalpart == local {
+ return true
+ }
for _, namespace := range knownAppService.NamespaceMap["users"] {
// AS namespaces are checked for validity in config
if namespace.RegexpObject.MatchString(userID) {
@@ -488,17 +506,6 @@ func Register(
return *resErr
}
- // Make sure normal user isn't registering under an exclusive application
- // service namespace. Skip this check if no app services are registered.
- if r.Auth.Type != authtypes.LoginTypeApplicationService &&
- len(cfg.Derived.ApplicationServices) != 0 &&
- UsernameMatchesExclusiveNamespaces(cfg, r.Username) {
- return util.JSONResponse{
- Code: http.StatusBadRequest,
- JSON: jsonerror.ASExclusive("This username is reserved by an application service."),
- }
- }
-
logger := util.GetLogger(req.Context())
logger.WithFields(log.Fields{
"username": r.Username,
@@ -581,11 +588,39 @@ func handleRegistrationFlow(
// TODO: Handle mapping registrationRequest parameters into session parameters
// TODO: email / msisdn auth types.
+ accessToken, accessTokenErr := auth.ExtractAccessToken(req)
+ if accessTokenErr != nil {
+ return util.JSONResponse{
+ Code: http.StatusUnauthorized,
+ JSON: jsonerror.MissingToken(accessTokenErr.Error()),
+ }
+ }
+
+ // Appservices are special and are not affected by disabled
+ // registration or user exclusivity.
+ if r.Auth.Type == authtypes.LoginTypeApplicationService ||
+ (r.Auth.Type == "" && accessTokenErr == nil) {
+ return handleApplicationServiceRegistration(
+ accessToken, accessTokenErr, req, r, cfg, userAPI,
+ )
+ }
if cfg.RegistrationDisabled && r.Auth.Type != authtypes.LoginTypeSharedSecret {
return util.MessageResponse(http.StatusForbidden, "Registration has been disabled")
}
+ // Make sure normal user isn't registering under an exclusive application
+ // service namespace. Skip this check if no app services are registered.
+ // If an access token is provided, ignore this check this is an appservice
+ // request and we will validate in validateApplicationService
+ if len(cfg.Derived.ApplicationServices) != 0 &&
+ UsernameMatchesExclusiveNamespaces(cfg, r.Username) {
+ return util.JSONResponse{
+ Code: http.StatusBadRequest,
+ JSON: jsonerror.ASExclusive("This username is reserved by an application service."),
+ }
+ }
+
switch r.Auth.Type {
case authtypes.LoginTypeRecaptcha:
// Check given captcha response
@@ -611,36 +646,15 @@ func handleRegistrationFlow(
// Add SharedSecret to the list of completed registration stages
AddCompletedSessionStage(sessionID, authtypes.LoginTypeSharedSecret)
- case "":
- // Extract the access token from the request, if there's one to extract
- // (which we can know by checking whether the error is nil or not).
- accessToken, err := auth.ExtractAccessToken(req)
-
- // A missing auth type can mean either the registration is performed by
- // an AS or the request is made as the first step of a registration
- // using the User-Interactive Authentication API. This can be determined
- // by whether the request contains an access token.
- if err == nil {
- return handleApplicationServiceRegistration(
- accessToken, err, req, r, cfg, userAPI,
- )
- }
-
- case authtypes.LoginTypeApplicationService:
- // Extract the access token from the request.
- accessToken, err := auth.ExtractAccessToken(req)
- // Let the AS registration handler handle the process from here. We
- // don't need a condition on that call since the registration is clearly
- // stated as being AS-related.
- return handleApplicationServiceRegistration(
- accessToken, err, req, r, cfg, userAPI,
- )
-
case authtypes.LoginTypeDummy:
// there is nothing to do
// Add Dummy to the list of completed registration stages
AddCompletedSessionStage(sessionID, authtypes.LoginTypeDummy)
+ case "":
+ // An empty auth type means that we want to fetch the available
+ // flows. It can also mean that we want to register as an appservice
+ // but that is handed above.
default:
return util.JSONResponse{
Code: http.StatusNotImplemented,