diff --git a/encryptoapi/routing/keys.go b/encryptoapi/routing/keys.go index 69988dca1..6f65a3d8e 100644 --- a/encryptoapi/routing/keys.go +++ b/encryptoapi/routing/keys.go @@ -107,7 +107,11 @@ func UploadPKeys( } } -// QueryPKeys enables the user to query for other devices's keys +// QueryPKeys returns the public identity keys +// and supported algorithms of "intended user" +// This just forwards the request to the Federation, +// and waits/checks for timeouts and failures. Response +// of the FedSenderAPI is bundled with the failures and returned. func QueryPKeys( req *http.Request, encryptionDB *storage.Database, @@ -119,8 +123,14 @@ func QueryPKeys( if reqErr := httputil.UnmarshalJSONRequest(req, &queryRq); reqErr != nil { return *reqErr } + queryRp := types.QueryResponse{} + + // sendDKToFed := queryRq.DeviceKeys + + var obtainedFromFed types.QueryResponse + obtainedKeysFromFed := obtainedFromFed.DeviceKeys + queryRp.DeviceKeys = obtainedKeysFromFed - sendDKToFed := queryRq.DeviceKeys queryRp.Failure = make(map[string]interface{}) // FED must return the keys from the other user /* diff --git a/encryptoapi/storage/encrypt_keys_table.go b/encryptoapi/storage/encrypt_keys_table.go index 66bf24066..4bb163cf5 100644 --- a/encryptoapi/storage/encrypt_keys_table.go +++ b/encryptoapi/storage/encrypt_keys_table.go @@ -210,7 +210,7 @@ func (s *keyStatements) selectInKeys( holders := []types.KeyHolder{} stmt := s.selectAllKeyStmt if len(arr) == 0 { - // mapping for all device keys + // empty array indicates - get all devices from corresponding user rowsP, err := stmt.QueryContext(ctx, userID, "device_key") if err != nil { return nil, err diff --git a/encryptoapi/storage/storage.go b/encryptoapi/storage/storage.go index f4e66819e..bfc1172d8 100644 --- a/encryptoapi/storage/storage.go +++ b/encryptoapi/storage/storage.go @@ -102,7 +102,7 @@ func (d *Database) InsertAl( } // SelectAl select algorithms -func (d *Database) SelectAl( +func (d *Database) SelectAlgo( ctx context.Context, uid, device string, ) (res []string, err error) { err = common.WithTransaction(d.db, func(txn *sql.Tx) (err error) { diff --git a/encryptoapi/types/query.go b/encryptoapi/types/query.go index c7dae9ea7..4b6c1ff31 100644 --- a/encryptoapi/types/query.go +++ b/encryptoapi/types/query.go @@ -29,12 +29,12 @@ type QueryResponse struct { // DeviceKeysQuery structure type DeviceKeysQuery struct { - UserID string `json:"user_id"` - DeviceID string `json:"device_id"` - Algorithm []string `json:"algorithms"` - Keys map[string]string `json:"keys"` - Signature map[string]map[string]string `json:"signatures"` - Unsigned UnsignedDeviceInfo `json:"unsigned"` + UserID string `json:"user_id"` + DeviceID string `json:"device_id"` + Algorithm []string `json:"algorithms"` + Keys map[string]string `json:"keys"` + Signatures map[string]map[string]string `json:"signatures"` + Unsigned UnsignedDeviceInfo `json:"unsigned"` } // UnsignedDeviceInfo structure diff --git a/federationapi/routing/e2ee.go b/federationapi/routing/e2ee.go index b48ab01ee..6649251a3 100644 --- a/federationapi/routing/e2ee.go +++ b/federationapi/routing/e2ee.go @@ -19,8 +19,11 @@ import ( "fmt" "net/http" + "github.com/matrix-org/dendrite/clientapi/auth/storage/devices" + "github.com/matrix-org/dendrite/clientapi/httputil" "github.com/matrix-org/dendrite/encryptoapi/storage" + ecTypes "github.com/matrix-org/dendrite/encryptoapi/types" "github.com/matrix-org/dendrite/federationapi/types" "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/util" @@ -42,46 +45,51 @@ func ClaimKeys( // QueryKeys provides the public identity keys and supported algorithms. func QueryKeys( httpReq *http.Request, - request *gomatrixserverlib.FederationRequest, encryptionDB *storage.Database, + deviceID string, + deviceDB *devices.Database, ) util.JSONResponse { var err error - var queryRq types.QueryRequest - if reqErr := httputil.UnmarshalJSONRequest(httpReq, &queryRq); reqErr != nil { + var queryReq types.QueryRequest + if reqErr := httputil.UnmarshalJSONRequest(httpReq, &queryReq); reqErr != nil { return *reqErr } - queryRp := types.QueryResponse{} + queryRes := 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] + queryRes.DeviceKeys = make(map[string]map[string]types.DeviceKeys) + // iterate through all demanded device keys + for uid, arr := range queryReq.DeviceKeys { + queryRes.DeviceKeys[uid] = make(map[string]types.DeviceKeys) + deviceKeysQueryMap := queryRes.DeviceKeys[uid] // backward compatible to old interface - midArr := []string{} + // 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) - } + // for device := range arr.(map[string]interface{}) { + // midArr = append(midArr, device) + // } // all device keys - dkeys, _ := encryptionDB.QueryInRange(httpReq.Context(), uid, midArr) + dkeys, err := encryptionDB.QueryInRange(httpReq.Context(), uid, arr) + if err != nil { + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: struct{}{}, + } + } // build response for them - for _, key := range dkeys { - deviceKeysQueryMap = presetDeviceKeysQueryMap(deviceKeysQueryMap, uid, key) - // load for accomplishment + // group the keys as intended in the response 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) + single.Signatures[uid][fmt.Sprintf("%s:%s", "ed25519", key.DeviceID)] = key.Signature + single.Algorithms, err = takeAlgo(httpReq.Context(), *encryptionDB, key.UserID, key.DeviceID) localpart, _, _ := gomatrixserverlib.SplitID('@', uid) - device, _ := deviceDB.GetDeviceByID(req.Context(), localpart, deviceID) - single.Unsigned.Info = device.DisplayName + device, _ := deviceDB.GetDeviceByID(httpReq.Context(), localpart, deviceID) + single.Unsigned.DeviceDisplayName = device.DisplayName deviceKeysQueryMap[key.DeviceID] = single } } @@ -94,24 +102,24 @@ func QueryKeys( return util.JSONResponse{ Code: http.StatusOK, - JSON: struct{}{}, + JSON: queryRes, } } func presetDeviceKeysQueryMap( deviceKeysQueryMap map[string]types.DeviceKeys, uid string, - key types.KeyHolder, + key ecTypes.KeyHolder, ) map[string]types.DeviceKeys { // preset for complicated nested map struct if _, ok := deviceKeysQueryMap[key.DeviceID]; !ok { // make consistency - deviceKeysQueryMap[key.DeviceID] = types.DeviceKeysQuery{} + deviceKeysQueryMap[key.DeviceID] = types.DeviceKeys{} } - if deviceKeysQueryMap[key.DeviceID].Signature == nil { + if deviceKeysQueryMap[key.DeviceID].Signatures == nil { mid := make(map[string]map[string]string) midmap := deviceKeysQueryMap[key.DeviceID] - midmap.Signature = mid + midmap.Signatures = mid deviceKeysQueryMap[key.DeviceID] = midmap } if deviceKeysQueryMap[key.DeviceID].Keys == nil { @@ -120,18 +128,18 @@ func presetDeviceKeysQueryMap( midmap.Keys = mid deviceKeysQueryMap[key.DeviceID] = midmap } - if _, ok := deviceKeysQueryMap[key.DeviceID].Signature[uid]; !ok { + if _, ok := deviceKeysQueryMap[key.DeviceID].Signatures[uid]; !ok { // make consistency - deviceKeysQueryMap[key.DeviceID].Signature[uid] = make(map[string]string) + deviceKeysQueryMap[key.DeviceID].Signatures[uid] = make(map[string]string) } return deviceKeysQueryMap } -func takeAL( +func takeAlgo( ctx context.Context, encryptDB storage.Database, uid, device string, ) (al []string, err error) { - al, err = encryptDB.SelectAl(ctx, uid, device) + al, err = encryptDB.SelectAlgo(ctx, uid, device) return } diff --git a/federationapi/types/query.go b/federationapi/types/query.go new file mode 100644 index 000000000..53fbc368d --- /dev/null +++ b/federationapi/types/query.go @@ -0,0 +1,51 @@ +// Copyright 2019 Sumukha PK +// +// 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 types + +// 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]map[string]DeviceKeys `json:"device_keys"` +} + +// KeyHolder structure +type KeyHolder struct { + UserID, + DeviceID, + Signature, + KeyAlgorithm, + KeyID, + Key, + KeyType string +} diff --git a/federationapi/types/types.go b/federationapi/types/types.go index 0b2009dda..24838d547 100644 --- a/federationapi/types/types.go +++ b/federationapi/types/types.go @@ -41,39 +41,3 @@ func NewTransaction() Transaction { 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 -}