/upload checked for completeness/correctness

This commit is contained in:
SUMUKHA-PK 2019-10-25 17:47:20 +05:30
parent d7664a1c96
commit a89da890b9
5 changed files with 205 additions and 80 deletions

View file

@ -28,7 +28,6 @@ import (
"github.com/matrix-org/dendrite/common/basecomponent" "github.com/matrix-org/dendrite/common/basecomponent"
"github.com/matrix-org/dendrite/encryptoapi/storage" "github.com/matrix-org/dendrite/encryptoapi/storage"
"github.com/matrix-org/dendrite/encryptoapi/types" "github.com/matrix-org/dendrite/encryptoapi/types"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util" "github.com/matrix-org/util"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -79,6 +78,7 @@ func UploadPKeys(
&keySpecific, &keySpecific,
userID, deviceID) userID, deviceID)
// numMap is algorithm-num map // numMap is algorithm-num map
// this gets the number of unclaimed OTkeys
numMap, ok := (queryOneTimeKeys( numMap, ok := (queryOneTimeKeys(
req.Context(), req.Context(),
TYPESUM, TYPESUM,
@ -116,13 +116,12 @@ func QueryPKeys(
) util.JSONResponse { ) util.JSONResponse {
var err error var err error
var queryRq types.QueryRequest var queryRq types.QueryRequest
queryRp := types.QueryResponse{}
queryRp.Failure = make(map[string]interface{})
queryRp.DeviceKeys = make(map[string]map[string]types.DeviceKeysQuery)
if reqErr := httputil.UnmarshalJSONRequest(req, &queryRq); reqErr != nil { if reqErr := httputil.UnmarshalJSONRequest(req, &queryRq); reqErr != nil {
return *reqErr return *reqErr
} }
sendDKToFed := queryRq.DeviceKeys
queryRp.Failure = make(map[string]interface{})
// FED must return the keys from the other user // FED must return the keys from the other user
/* /*
federation consideration: when user id is in federation, a federation consideration: when user id is in federation, a
@ -156,44 +155,12 @@ func QueryPKeys(
} }
} }
// query one's device key from user corresponding to uid //
for uid, arr := range queryRq.DeviceKeys { //
queryRp.DeviceKeys[uid] = make(map[string]types.DeviceKeysQuery) //
deviceKeysQueryMap := queryRp.DeviceKeys[uid] //
// backward compatible to old interface // Forward the request to the federation server and get the required info
midArr := []string{}
// figure out device list from devices described as device which is actually deviceID
for device := range arr.(map[string]interface{}) {
midArr = append(midArr, device)
}
// all device keys
dkeys, _ := encryptionDB.QueryInRange(req.Context(), uid, midArr)
// build response for them
for _, key := range dkeys {
deviceKeysQueryMap = presetDeviceKeysQueryMap(deviceKeysQueryMap, uid, key)
// load for accomplishment
single := deviceKeysQueryMap[key.DeviceID]
resKey := fmt.Sprintf("%s:%s", key.KeyAlgorithm, key.DeviceID)
resBody := key.Key
single.Keys[resKey] = resBody
single.DeviceID = key.DeviceID
single.UserID = key.UserID
single.Signature[uid][fmt.Sprintf("%s:%s", "ed25519", key.DeviceID)] = key.Signature
single.Algorithm, err = takeAL(req.Context(), *encryptionDB, key.UserID, key.DeviceID)
localpart, _, _ := gomatrixserverlib.SplitID('@', uid)
device, _ := deviceDB.GetDeviceByID(req.Context(), localpart, deviceID)
single.Unsigned.Info = device.DisplayName
deviceKeysQueryMap[key.DeviceID] = single
}
}
if err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: queryRp,
}
}
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusOK, Code: http.StatusOK,
JSON: queryRp, JSON: queryRp,
@ -426,15 +393,6 @@ func persistAl(
return return
} }
func takeAL(
ctx context.Context,
encryptDB storage.Database,
uid, device string,
) (al []string, err error) {
al, err = encryptDB.SelectAl(ctx, uid, device)
return
}
func pickOne( func pickOne(
ctx context.Context, ctx context.Context,
encryptDB storage.Database, encryptDB storage.Database,
@ -460,35 +418,6 @@ func InitNotifier(base *basecomponent.BaseDendrite) {
keyProducer.ch = pro keyProducer.ch = pro
} }
func presetDeviceKeysQueryMap(
deviceKeysQueryMap map[string]types.DeviceKeysQuery,
uid string,
key types.KeyHolder,
) map[string]types.DeviceKeysQuery {
// preset for complicated nested map struct
if _, ok := deviceKeysQueryMap[key.DeviceID]; !ok {
// make consistency
deviceKeysQueryMap[key.DeviceID] = types.DeviceKeysQuery{}
}
if deviceKeysQueryMap[key.DeviceID].Signature == nil {
mid := make(map[string]map[string]string)
midmap := deviceKeysQueryMap[key.DeviceID]
midmap.Signature = mid
deviceKeysQueryMap[key.DeviceID] = midmap
}
if deviceKeysQueryMap[key.DeviceID].Keys == nil {
mid := make(map[string]string)
midmap := deviceKeysQueryMap[key.DeviceID]
midmap.Keys = mid
deviceKeysQueryMap[key.DeviceID] = midmap
}
if _, ok := deviceKeysQueryMap[key.DeviceID].Signature[uid]; !ok {
// make consistency
deviceKeysQueryMap[key.DeviceID].Signature[uid] = make(map[string]string)
}
return deviceKeysQueryMap
}
func persistBothKeys( func persistBothKeys(
ctx context.Context, ctx context.Context,
body *types.UploadEncryptSpecific, body *types.UploadEncryptSpecific,

View file

@ -59,7 +59,7 @@ func (d *Database) InsertKey(
return return
} }
// SelectOneTimeKeyCount for key upload response usage a map from key algorithm to sum to counterpart // SelectOneTimeKeyCount provides the number of un-claimed OTKeys
func (d *Database) SelectOneTimeKeyCount( func (d *Database) SelectOneTimeKeyCount(
ctx context.Context, ctx context.Context,
deviceID, userID string, deviceID, userID string,

View file

@ -0,0 +1,137 @@
// Copyright Sumukha PK 2019
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package routing
import (
"context"
"fmt"
"net/http"
"github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/encryptoapi/storage"
"github.com/matrix-org/dendrite/federationapi/types"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
)
// ClaimKeys provides the e2ee keys of the user
func ClaimKeys(
httpReq *http.Request,
request *gomatrixserverlib.FederationRequest,
encryptionDB *storage.Database,
) util.JSONResponse {
return util.JSONResponse{
Code: http.StatusOK,
JSON: struct{}{},
}
}
// QueryKeys provides the public identity keys and supported algorithms.
func QueryKeys(
httpReq *http.Request,
request *gomatrixserverlib.FederationRequest,
encryptionDB *storage.Database,
) util.JSONResponse {
var err error
var queryRq types.QueryRequest
if reqErr := httputil.UnmarshalJSONRequest(httpReq, &queryRq); reqErr != nil {
return *reqErr
}
queryRp := types.QueryResponse{}
queryRp.DeviceKeys = make(map[string]map[string]types.DeviceKeys)
// query one's device key from user corresponding to uid
for uid, arr := range queryRq.DeviceKeys {
queryRp.DeviceKeys[uid] = make(map[string]types.DeviceKeys)
deviceKeysQueryMap := queryRp.DeviceKeys[uid]
// backward compatible to old interface
midArr := []string{}
// figure out device list from devices described as device which is actually deviceID
for device := range arr.(map[string]interface{}) {
midArr = append(midArr, device)
}
// all device keys
dkeys, _ := encryptionDB.QueryInRange(httpReq.Context(), uid, midArr)
// build response for them
for _, key := range dkeys {
deviceKeysQueryMap = presetDeviceKeysQueryMap(deviceKeysQueryMap, uid, key)
// load for accomplishment
single := deviceKeysQueryMap[key.DeviceID]
resKey := fmt.Sprintf("%s:%s", key.KeyAlgorithm, key.DeviceID)
resBody := key.Key
single.Keys[resKey] = resBody
single.DeviceID = key.DeviceID
single.UserID = key.UserID
single.Signature[uid][fmt.Sprintf("%s:%s", "ed25519", key.DeviceID)] = key.Signature
single.Algorithm, err = takeAL(httpReq.Context(), *encryptionDB, key.UserID, key.DeviceID)
localpart, _, _ := gomatrixserverlib.SplitID('@', uid)
device, _ := deviceDB.GetDeviceByID(req.Context(), localpart, deviceID)
single.Unsigned.Info = device.DisplayName
deviceKeysQueryMap[key.DeviceID] = single
}
}
if err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: struct{}{},
}
}
return util.JSONResponse{
Code: http.StatusOK,
JSON: struct{}{},
}
}
func presetDeviceKeysQueryMap(
deviceKeysQueryMap map[string]types.DeviceKeys,
uid string,
key types.KeyHolder,
) map[string]types.DeviceKeys {
// preset for complicated nested map struct
if _, ok := deviceKeysQueryMap[key.DeviceID]; !ok {
// make consistency
deviceKeysQueryMap[key.DeviceID] = types.DeviceKeysQuery{}
}
if deviceKeysQueryMap[key.DeviceID].Signature == nil {
mid := make(map[string]map[string]string)
midmap := deviceKeysQueryMap[key.DeviceID]
midmap.Signature = mid
deviceKeysQueryMap[key.DeviceID] = midmap
}
if deviceKeysQueryMap[key.DeviceID].Keys == nil {
mid := make(map[string]string)
midmap := deviceKeysQueryMap[key.DeviceID]
midmap.Keys = mid
deviceKeysQueryMap[key.DeviceID] = midmap
}
if _, ok := deviceKeysQueryMap[key.DeviceID].Signature[uid]; !ok {
// make consistency
deviceKeysQueryMap[key.DeviceID].Signature[uid] = make(map[string]string)
}
return deviceKeysQueryMap
}
func takeAL(
ctx context.Context,
encryptDB storage.Database,
uid, device string,
) (al []string, err error) {
al, err = encryptDB.SelectAl(ctx, uid, device)
return
}

View file

@ -271,4 +271,27 @@ func Setup(
return Backfill(httpReq, request, query, vars["roomID"], cfg) return Backfill(httpReq, request, query, vars["roomID"], cfg)
}, },
)).Methods(http.MethodGet) )).Methods(http.MethodGet)
v1fedmux.Handle("/keys/claim", common.MakeFedAPI(
"federation_claim_e2ee_keys", cfg.Matrix.ServerName, keys,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse {
// vars, err := common.URLDecodeMapValues(mux.Vars(httpReq))
// if err != nil {
// return util.ErrorResponse(err)
// }
return ClaimKeys(httpReq, request)
},
)).Methods(http.MethodPost)
v1fedmux.Handle("/keys/query", common.MakeFedAPI(
"federation_query_e2ee_keys", cfg.Matrix.ServerName, keys,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse {
// vars, err := common.URLDecodeMapValues(mux.Vars(httpReq))
// if err != nil {
// return util.ErrorResponse(err)
// }
return QueryKeys(httpReq, request)
},
)).Methods(http.MethodPost)
} }

View file

@ -41,3 +41,39 @@ func NewTransaction() Transaction {
return Transaction{OriginServerTS: ts} return Transaction{OriginServerTS: ts}
} }
// QueryRequest is the request for /query
type QueryRequest struct {
DeviceKeys map[string][]string `json:"device_keys"`
}
// UnsignedDeviceInfo is the struct for UDI
type UnsignedDeviceInfo struct {
DeviceDisplayName string `json:"device_display_name"`
}
// DeviceKeys has the data of the keys of the device
type DeviceKeys struct {
UserID string `json:"user_id"`
DeviceID string `json:"edvice_id"`
Algorithms []string `json:"algorithms"`
Keys map[string]string `json:"keys"`
Signatures map[string]map[string]string `json:"signatures"`
Unsigned UnsignedDeviceInfo `json:"unsigned"`
}
// QueryResponse is the response for /query
type QueryResponse struct {
DeviceKeys map[string]DeviceKeys `json:"device_keys"`
}
// KeyHolder structure
type KeyHolder struct {
UserID,
DeviceID,
Signature,
KeyAlgorithm,
KeyID,
Key,
KeyType string
}