Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3564051
D7538.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Referenced Files
None
Subscribers
None
D7538.diff
View Options
diff --git a/services/identity/src/client_service.rs b/services/identity/src/client_service.rs
--- a/services/identity/src/client_service.rs
+++ b/services/identity/src/client_service.rs
@@ -29,6 +29,7 @@
pub use client_proto::identity_client_service_server::{
IdentityClientService, IdentityClientServiceServer,
};
+use comm_opaque2::grpc::protocol_error_to_grpc_status;
use moka::future::Cache;
use rand::rngs::OsRng;
use tonic::Response;
@@ -47,7 +48,10 @@
}
#[derive(Clone)]
-pub struct UserLoginInfo(FlattenedDeviceKeyUpload);
+pub struct UserLoginInfo {
+ pub flattened_device_key_upload: FlattenedDeviceKeyUpload,
+ pub opaque_server_login: comm_opaque2::server::Login,
+}
#[derive(Clone)]
pub struct FlattenedDeviceKeyUpload {
@@ -118,7 +122,7 @@
let server_registration = comm_opaque2::server::Registration::new();
let server_message = server_registration
.start(&CONFIG.server_setup, ®ister_message, username.as_bytes())
- .map_err(comm_opaque2::grpc::protocol_error_to_grpc_status)?;
+ .map_err(protocol_error_to_grpc_status)?;
let key_info = KeyPayload::from_str(&payload)
.map_err(|_| tonic::Status::invalid_argument("malformed payload"))?;
let registration_state = UserRegistrationInfo {
@@ -168,7 +172,7 @@
let server_registration = comm_opaque2::server::Registration::new();
let password_file = server_registration
.finish(&message.opaque_registration_upload)
- .map_err(comm_opaque2::grpc::protocol_error_to_grpc_status)?;
+ .map_err(protocol_error_to_grpc_status)?;
let device_id = state.flattened_device_key_upload.device_id_key.clone();
let user_id = self
@@ -221,9 +225,83 @@
async fn login_password_user_start(
&self,
- _request: tonic::Request<OpaqueLoginStartRequest>,
+ request: tonic::Request<OpaqueLoginStartRequest>,
) -> Result<tonic::Response<OpaqueLoginStartResponse>, tonic::Status> {
- unimplemented!();
+ let message = request.into_inner();
+
+ let password_file_bytes = self
+ .client
+ .get_password_file_from_username(&message.username)
+ .await
+ .map_err(handle_db_error)?
+ .ok_or(tonic::Status::not_found("user not found"))?;
+
+ if let client_proto::OpaqueLoginStartRequest {
+ opaque_login_request: login_message,
+ username,
+ device_key_upload:
+ Some(client_proto::DeviceKeyUpload {
+ device_key_info:
+ Some(client_proto::IdentityKeyInfo {
+ payload,
+ payload_signature,
+ social_proof: _social_proof,
+ }),
+ identity_upload:
+ Some(client_proto::PreKey {
+ pre_key: identity_prekey,
+ pre_key_signature: identity_prekey_signature,
+ }),
+ notif_upload:
+ Some(client_proto::PreKey {
+ pre_key: notif_prekey,
+ pre_key_signature: notif_prekey_signature,
+ }),
+ onetime_identity_prekeys,
+ onetime_notif_prekeys,
+ }),
+ } = message
+ {
+ let mut server_login = comm_opaque2::server::Login::new();
+ let server_response = server_login
+ .start(
+ &CONFIG.server_setup,
+ &password_file_bytes,
+ &login_message,
+ username.as_bytes(),
+ )
+ .map_err(protocol_error_to_grpc_status)?;
+
+ let key_info = KeyPayload::from_str(&payload)
+ .map_err(|_| tonic::Status::invalid_argument("malformed payload"))?;
+ let login_state = UserLoginInfo {
+ opaque_server_login: server_login,
+ flattened_device_key_upload: FlattenedDeviceKeyUpload {
+ device_id_key: key_info.primary_identity_public_keys.curve25519,
+ key_payload: payload,
+ key_payload_signature: payload_signature,
+ identity_prekey,
+ identity_prekey_signature,
+ identity_onetime_keys: onetime_identity_prekeys,
+ notif_prekey,
+ notif_prekey_signature,
+ notif_onetime_keys: onetime_notif_prekeys,
+ },
+ };
+ let session_id = generate_uuid();
+ self
+ .cache
+ .insert(session_id.clone(), WorkflowInProgress::Login(login_state))
+ .await;
+
+ let response = Response::new(OpaqueLoginStartResponse {
+ session_id,
+ opaque_login_response: server_response,
+ });
+ Ok(response)
+ } else {
+ Err(tonic::Status::invalid_argument("unexpected message data"))
+ }
}
async fn login_password_user_finish(
diff --git a/services/identity/src/database.rs b/services/identity/src/database.rs
--- a/services/identity/src/database.rs
+++ b/services/identity/src/database.rs
@@ -105,36 +105,6 @@
}
}
- pub async fn get_pake_registration(
- &self,
- user_id: String,
- ) -> Result<Option<ServerRegistration<Cipher>>, Error> {
- match self.get_item_from_users_table(&user_id).await {
- Ok(GetItemOutput {
- item: Some(mut item),
- ..
- }) => parse_registration_data_attribute(
- item.remove(USERS_TABLE_REGISTRATION_ATTRIBUTE),
- )
- .map(Some)
- .map_err(Error::Attribute),
- Ok(_) => {
- info!(
- "No item found for user {} in PAKE registration table",
- user_id
- );
- Ok(None)
- }
- Err(e) => {
- error!(
- "DynamoDB client failed to get registration data for user {}: {}",
- user_id, e
- );
- Err(e)
- }
- }
- }
-
pub async fn add_user_to_users_table(
&self,
registration_state: UserRegistrationInfo,
@@ -397,11 +367,11 @@
Ok(result.is_some())
}
- pub async fn get_user_id_from_user_info(
+ async fn get_user_from_user_info(
&self,
user_info: String,
auth_type: AuthType,
- ) -> Result<Option<String>, Error> {
+ ) -> Result<Option<HashMap<String, AttributeValue>>, Error> {
let (index, attribute_name) = match auth_type {
AuthType::Password => {
(USERS_TABLE_USERNAME_INDEX, USERS_TABLE_USERNAME_ATTRIBUTE)
@@ -422,8 +392,7 @@
.await
{
Ok(QueryOutput {
- items: Some(mut items),
- ..
+ items: Some(items), ..
}) => {
let num_items = items.len();
if num_items == 0 {
@@ -435,12 +404,8 @@
num_items, attribute_name, user_info, items
);
}
- parse_string_attribute(
- USERS_TABLE_PARTITION_KEY,
- items[0].remove(USERS_TABLE_PARTITION_KEY),
- )
- .map(Some)
- .map_err(Error::Attribute)
+ let first_item = items[0].clone();
+ Ok(Some(first_item))
}
Ok(_) => {
info!(
@@ -451,7 +416,7 @@
}
Err(e) => {
error!(
- "DynamoDB client failed to get user ID from {} {}: {}",
+ "DynamoDB client failed to get user from {} {}: {}",
attribute_name, user_info, e
);
Err(Error::AwsSdk(e.into()))
@@ -459,6 +424,56 @@
}
}
+ pub async fn get_user_id_from_user_info(
+ &self,
+ user_info: String,
+ auth_type: AuthType,
+ ) -> Result<Option<String>, Error> {
+ match self
+ .get_user_from_user_info(user_info.clone(), auth_type)
+ .await
+ {
+ Ok(Some(mut user)) => parse_string_attribute(
+ USERS_TABLE_PARTITION_KEY,
+ user.remove(USERS_TABLE_PARTITION_KEY),
+ )
+ .map(Some)
+ .map_err(Error::Attribute),
+ Ok(_) => Ok(None),
+ Err(e) => Err(e),
+ }
+ }
+
+ pub async fn get_password_file_from_username(
+ &self,
+ username: &str,
+ ) -> Result<Option<Vec<u8>>, Error> {
+ match self
+ .get_user_from_user_info(username.to_string(), AuthType::Password)
+ .await
+ {
+ Ok(Some(mut user)) => parse_registration_data_attribute(
+ user.remove(USERS_TABLE_REGISTRATION_ATTRIBUTE),
+ )
+ .map(Some)
+ .map_err(Error::Attribute),
+ Ok(_) => {
+ info!(
+ "No item found for user {} in PAKE registration table",
+ username
+ );
+ Ok(None)
+ }
+ Err(e) => {
+ error!(
+ "DynamoDB client failed to get registration data for user {}: {}",
+ username, e
+ );
+ Err(e)
+ }
+ }
+ }
+
pub async fn get_item_from_users_table(
&self,
user_id: &str,
@@ -673,19 +688,10 @@
fn parse_registration_data_attribute(
attribute: Option<AttributeValue>,
-) -> Result<ServerRegistration<Cipher>, DBItemError> {
- match &attribute {
+) -> Result<Vec<u8>, DBItemError> {
+ match attribute {
Some(AttributeValue::B(server_registration_bytes)) => {
- match ServerRegistration::<Cipher>::deserialize(
- server_registration_bytes.as_ref(),
- ) {
- Ok(server_registration) => Ok(server_registration),
- Err(e) => Err(DBItemError::new(
- USERS_TABLE_REGISTRATION_ATTRIBUTE,
- attribute,
- DBItemAttributeError::Pake(e),
- )),
- }
+ Ok(server_registration_bytes.into_inner())
}
Some(_) => Err(DBItemError::new(
USERS_TABLE_REGISTRATION_ATTRIBUTE,
diff --git a/shared/comm-opaque2/src/server/login.rs b/shared/comm-opaque2/src/server/login.rs
--- a/shared/comm-opaque2/src/server/login.rs
+++ b/shared/comm-opaque2/src/server/login.rs
@@ -7,6 +7,7 @@
use crate::Cipher;
+#[derive(Clone)]
pub struct Login {
state: Option<ServerLogin<Cipher>>,
rng: OsRng,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 28, 1:10 PM (8 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2726747
Default Alt Text
D7538.diff (9 KB)
Attached To
Mode
D7538: [identity] login start
Attached
Detach File
Event Timeline
Log In to Comment