mirror of
https://github.com/matrix-org/dendrite
synced 2024-11-10 15:14:36 +00:00
7482cd2b47
`/_synapse/admin/v1/register` has a `displayname` field that we were previously ignoring. This handles that field and adds the displayname to the new user if one was provided.
100 lines
2.6 KiB
Go
100 lines
2.6 KiB
Go
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"`
|
|
DisplayName string `json:"displayname,omitempty"`
|
|
}
|
|
|
|
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
|
|
}
|