mirror of
https://github.com/element-hq/dendrite.git
synced 2025-09-13 21:02:25 +03:00
Implement /_synapse/admin/v1/register (#1911)
* Implement /_synapse/admin/v1/register This is implemented identically to Synapse, so scripts which work with Synapse should work with Dendrite. ``` Test 27 POST /_synapse/admin/v1/register with shared secret... OK Test 28 POST /_synapse/admin/v1/register admin with shared secret... OK Test 29 POST /_synapse/admin/v1/register with shared secret downcases capitals... OK Test 30 POST /_synapse/admin/v1/register with shared secret disallows symbols... OK ``` Sytest however has `implementation_specific => "synapse"` which stops these tests from running. * Add missing muxes to gobind * Linting
This commit is contained in:
parent
c8408a6387
commit
1ed732cc78
18 changed files with 220 additions and 66 deletions
99
clientapi/routing/register_secret.go
Normal file
99
clientapi/routing/register_secret.go
Normal file
|
@ -0,0 +1,99 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/internal"
|
||||
"github.com/matrix-org/util"
|
||||
cache "github.com/patrickmn/go-cache"
|
||||
)
|
||||
|
||||
type SharedSecretRegistrationRequest struct {
|
||||
User string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Nonce string `json:"nonce"`
|
||||
MacBytes []byte
|
||||
MacStr string `json:"mac"`
|
||||
Admin bool `json:"admin"`
|
||||
}
|
||||
|
||||
func NewSharedSecretRegistrationRequest(reader io.ReadCloser) (*SharedSecretRegistrationRequest, error) {
|
||||
defer internal.CloseAndLogIfError(context.Background(), reader, "NewSharedSecretRegistrationRequest: failed to close request body")
|
||||
var ssrr SharedSecretRegistrationRequest
|
||||
err := json.NewDecoder(reader).Decode(&ssrr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ssrr.MacBytes, err = hex.DecodeString(ssrr.MacStr)
|
||||
return &ssrr, err
|
||||
}
|
||||
|
||||
type SharedSecretRegistration struct {
|
||||
sharedSecret string
|
||||
nonces *cache.Cache
|
||||
}
|
||||
|
||||
func NewSharedSecretRegistration(sharedSecret string) *SharedSecretRegistration {
|
||||
return &SharedSecretRegistration{
|
||||
sharedSecret: sharedSecret,
|
||||
// nonces live for 5mins, purge every 10mins
|
||||
nonces: cache.New(5*time.Minute, 10*time.Minute),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *SharedSecretRegistration) GenerateNonce() string {
|
||||
nonce := util.RandomString(16)
|
||||
r.nonces.Set(nonce, true, cache.DefaultExpiration)
|
||||
return nonce
|
||||
}
|
||||
|
||||
func (r *SharedSecretRegistration) validNonce(nonce string) bool {
|
||||
_, exists := r.nonces.Get(nonce)
|
||||
return exists
|
||||
}
|
||||
|
||||
func (r *SharedSecretRegistration) IsValidMacLogin(
|
||||
nonce, username, password string,
|
||||
isAdmin bool,
|
||||
givenMac []byte,
|
||||
) (bool, error) {
|
||||
// Check that shared secret registration isn't disabled.
|
||||
if r.sharedSecret == "" {
|
||||
return false, errors.New("Shared secret registration is disabled")
|
||||
}
|
||||
if !r.validNonce(nonce) {
|
||||
return false, fmt.Errorf("Incorrect or expired nonce: %s", nonce)
|
||||
}
|
||||
|
||||
// Check that username/password don't contain the HMAC delimiters.
|
||||
if strings.Contains(username, "\x00") {
|
||||
return false, errors.New("Username contains invalid character")
|
||||
}
|
||||
if strings.Contains(password, "\x00") {
|
||||
return false, errors.New("Password contains invalid character")
|
||||
}
|
||||
|
||||
adminString := "notadmin"
|
||||
if isAdmin {
|
||||
adminString = "admin"
|
||||
}
|
||||
joined := strings.Join([]string{nonce, username, password, adminString}, "\x00")
|
||||
|
||||
mac := hmac.New(sha1.New, []byte(r.sharedSecret))
|
||||
_, err := mac.Write([]byte(joined))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
expectedMAC := mac.Sum(nil)
|
||||
|
||||
return hmac.Equal(givenMac, expectedMAC), nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue