mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-26 08:13:09 -06:00
Pass custom certificates via config file to be added to system pool, fix CreateSession to be conformant to V1 api
This commit is contained in:
parent
01ce9abc5b
commit
d975de3c05
|
|
@ -19,7 +19,6 @@ import (
|
|||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
|
@ -40,6 +39,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/threepid"
|
||||
"github.com/matrix-org/dendrite/clientapi/userutil"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/dendrite/userapi/storage/accounts"
|
||||
|
|
@ -161,33 +161,10 @@ type authDict struct {
|
|||
// Recaptcha
|
||||
Response string `json:"response"`
|
||||
// m.login.email.identity and m.login.msisdn
|
||||
ThreePidCreds *threepidCreds `json:"threepidCreds"`
|
||||
ThreePidCreds *threepid.Credentials `json:"threepidCreds"`
|
||||
// TODO: Lots of custom keys depending on the type
|
||||
}
|
||||
|
||||
type threepidCreds struct {
|
||||
Sid string `json:"sid"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
IdServer string `json:"id_server"`
|
||||
IdAccessToken string `json:"id_access_token"`
|
||||
}
|
||||
|
||||
func (c *threepidCreds) validate() *jsonerror.MatrixError {
|
||||
if c.Sid == "" {
|
||||
return jsonerror.BadJSON("sid field in threepidCreds is required")
|
||||
}
|
||||
if c.ClientSecret == "" {
|
||||
return jsonerror.BadJSON("client_secret in threepidCreds is required")
|
||||
}
|
||||
if c.IdServer == "" {
|
||||
return jsonerror.BadJSON("id_server in threepidCreds is required")
|
||||
}
|
||||
if c.IdAccessToken == "" {
|
||||
return jsonerror.BadJSON("id_access_token in threepidCreds is required")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// http://matrix.org/speculator/spec/HEAD/client_server/unstable.html#user-interactive-authentication-api
|
||||
type userInteractiveResponse struct {
|
||||
Flows []authtypes.Flow `json:"flows"`
|
||||
|
|
@ -352,15 +329,19 @@ func validateRecaptcha(
|
|||
|
||||
func validateEmailIdentity(
|
||||
ctx context.Context,
|
||||
cred *threepidCreds,
|
||||
cred *threepid.Credentials,
|
||||
cfg *config.ClientAPI,
|
||||
) *util.JSONResponse {
|
||||
if err := isTrusted(cred.IDServer, cfg); err != nil {
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.NotTrusted(cred.IDServer),
|
||||
}
|
||||
}
|
||||
util.GetLogger(ctx).Infof("conecting to identity server: %s", cred.IDServer)
|
||||
url := fmt.Sprintf(
|
||||
"https://%s/_matrix/identity/api/v1/3pid/getValidated3pid",
|
||||
cred.IdServer)
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
client := &http.Client{Transport: tr}
|
||||
cred.IDServer)
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", url, nil)
|
||||
if err != nil {
|
||||
return &util.JSONResponse{
|
||||
|
|
@ -369,11 +350,11 @@ func validateEmailIdentity(
|
|||
}
|
||||
}
|
||||
q := req.URL.Query()
|
||||
q.Add("client_secret", cred.ClientSecret)
|
||||
q.Add("sid", cred.Sid)
|
||||
q.Add("client_secret", cred.Secret)
|
||||
q.Add("sid", cred.SID)
|
||||
req.URL.RawQuery = q.Encode()
|
||||
req.Header.Add("Authorization", "Bearer swordfish")
|
||||
resp, err := client.Do(req)
|
||||
resp, err := cfg.Derived.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("failed conecting to identity server")
|
||||
return &util.JSONResponse{
|
||||
|
|
@ -403,6 +384,18 @@ func validateEmailIdentity(
|
|||
}
|
||||
}
|
||||
|
||||
// isTrusted checks if a given identity server is part of the list of trusted
|
||||
// identity servers in the configuration file.
|
||||
// Returns an error if the server isn't trusted.
|
||||
func isTrusted(idServer string, cfg *config.ClientAPI) error {
|
||||
for _, server := range cfg.Matrix.TrustedIDServers {
|
||||
if idServer == server {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return threepid.ErrNotTrusted
|
||||
}
|
||||
|
||||
// UserIDIsWithinApplicationServiceNamespace checks to see if a given userID
|
||||
// falls within any of the namespaces of a given Application Service. If no
|
||||
// Application Service is given, it will check to see if it matches any
|
||||
|
|
@ -759,13 +752,13 @@ func handleRegistrationFlow(
|
|||
JSON: jsonerror.BadJSON("threepidCreds not found in auth field"),
|
||||
}
|
||||
}
|
||||
if err := r.Auth.ThreePidCreds.validate(); err != nil {
|
||||
if err := r.Auth.ThreePidCreds.Validate(); err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: err,
|
||||
}
|
||||
}
|
||||
if err := validateEmailIdentity(req.Context(), r.Auth.ThreePidCreds); err != nil {
|
||||
if err := validateEmailIdentity(req.Context(), r.Auth.ThreePidCreds, cfg); err != nil {
|
||||
return *err
|
||||
}
|
||||
AddCompletedSessionStage(sessionID, authtypes.LoginTypeEmailIdentity)
|
||||
|
|
|
|||
|
|
@ -15,15 +15,16 @@
|
|||
package threepid
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
)
|
||||
|
||||
|
|
@ -48,6 +49,19 @@ type Credentials struct {
|
|||
Secret string `json:"client_secret"`
|
||||
}
|
||||
|
||||
func (c *Credentials) Validate() *jsonerror.MatrixError {
|
||||
if c.SID == "" {
|
||||
return jsonerror.BadJSON("sid field in threepidCreds is required")
|
||||
}
|
||||
if c.Secret == "" {
|
||||
return jsonerror.BadJSON("client_secret in threepidCreds is required")
|
||||
}
|
||||
if c.IDServer == "" {
|
||||
return jsonerror.BadJSON("id_server in threepidCreds is required")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateSession creates a session on an identity server.
|
||||
// Returns the session's ID.
|
||||
// Returns an error if there was a problem sending the request or decoding the
|
||||
|
|
@ -62,22 +76,23 @@ func CreateSession(
|
|||
// Create a session on the ID server
|
||||
postURL := fmt.Sprintf("https://%s/_matrix/identity/api/v1/validate/email/requestToken", req.IDServer)
|
||||
|
||||
data := url.Values{}
|
||||
data.Add("client_secret", req.Secret)
|
||||
data.Add("email", req.Email)
|
||||
data.Add("send_attempt", strconv.Itoa(req.SendAttempt))
|
||||
|
||||
request, err := http.NewRequest(http.MethodPost, postURL, strings.NewReader(data.Encode()))
|
||||
b := bytes.Buffer{}
|
||||
enc := json.NewEncoder(&b)
|
||||
err := enc.Encode(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
client := http.Client{}
|
||||
resp, err := client.Do(request.WithContext(ctx))
|
||||
request, err := http.NewRequest(http.MethodPost, postURL, &b)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
request.Header.Add("Content-Type", "application/json")
|
||||
|
||||
resp, err := cfg.Derived.HttpClient.Do(request.WithContext(ctx))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Error if the status isn't OK
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
|
|
@ -112,11 +127,11 @@ func CheckAssociation(
|
|||
if err != nil {
|
||||
return false, "", "", err
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req.WithContext(ctx))
|
||||
resp, err := cfg.Derived.HttpClient.Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
return false, "", "", err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
var respBody struct {
|
||||
Medium string `json:"medium"`
|
||||
ValidatedAt int64 `json:"validated_at"`
|
||||
|
|
@ -160,8 +175,7 @@ func PublishAssociation(creds Credentials, userID string, cfg *config.ClientAPI)
|
|||
}
|
||||
request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
client := http.Client{}
|
||||
resp, err := client.Do(request)
|
||||
resp, err := cfg.Derived.HttpClient.Do(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,14 @@ package config
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
|
@ -97,6 +101,9 @@ type Derived struct {
|
|||
Params map[string]interface{} `json:"params"`
|
||||
}
|
||||
|
||||
// Used for request to identity server
|
||||
HttpClient *http.Client
|
||||
|
||||
// Application services parsed from their config files
|
||||
// The paths of which were given above in the main config file
|
||||
ApplicationServices []ApplicationService
|
||||
|
|
@ -289,6 +296,26 @@ func (config *Dendrite) Derive() error {
|
|||
return err
|
||||
}
|
||||
|
||||
if config.ClientAPI.CustomCaPath != "" {
|
||||
// Add custom CA cert
|
||||
rootCAs, err := x509.SystemCertPool()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
certs, err := ioutil.ReadFile(config.ClientAPI.CustomCaPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ok := rootCAs.AppendCertsFromPEM(certs); !ok {
|
||||
return errors.New("failed to append custom certificate")
|
||||
}
|
||||
trConfig := &tls.Config{
|
||||
RootCAs: rootCAs,
|
||||
}
|
||||
tr := &http.Transport{TLSClientConfig: trConfig}
|
||||
config.Derived.HttpClient = &http.Client{Transport: tr}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ type ClientAPI struct {
|
|||
Matrix *Global `yaml:"-"`
|
||||
Derived *Derived `yaml:"-"` // TODO: Nuke Derived from orbit
|
||||
|
||||
// The path to file of custom CA certificate to be added to root CA
|
||||
CustomCaPath string `yaml:"custom_ca_path"`
|
||||
|
||||
InternalAPI InternalAPIOptions `yaml:"internal_api"`
|
||||
ExternalAPI ExternalAPIOptions `yaml:"external_api"`
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue