Layer 78. Initial Telegram Passport support.
GitOrigin-RevId: 197994bcf62a76cd963f32a8dd7f5951d7b6588b
This commit is contained in:
parent
ccf8064821
commit
fb79d6f95a
@ -401,6 +401,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/SecretChatDb.cpp
|
||||
td/telegram/SecretChatsManager.cpp
|
||||
td/telegram/SecureStorage.cpp
|
||||
td/telegram/SecureValue.cpp
|
||||
td/telegram/SequenceDispatcher.cpp
|
||||
td/telegram/StateManager.cpp
|
||||
td/telegram/StickersManager.cpp
|
||||
@ -521,6 +522,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/SecretChatsManager.h
|
||||
td/telegram/SecretInputMedia.h
|
||||
td/telegram/SecureStorage.h
|
||||
td/telegram/SecureValue.h
|
||||
td/telegram/SequenceDispatcher.h
|
||||
td/telegram/StateManager.h
|
||||
td/telegram/StickersManager.h
|
||||
@ -551,6 +553,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/Payments.hpp
|
||||
td/telegram/Photo.hpp
|
||||
td/telegram/ReplyMarkup.hpp
|
||||
td/telegram/SecureValue.hpp
|
||||
td/telegram/StickersManager.hpp
|
||||
td/telegram/VideoNotesManager.hpp
|
||||
td/telegram/VideosManager.hpp
|
||||
|
@ -59,6 +59,9 @@ authenticationCodeTypeFlashCall pattern:string = AuthenticationCodeType;
|
||||
//@description Information about the authentication code that was sent @phone_number A phone number that is being authenticated @type Describes the way the code was sent to the user @next_type Describes the way the next code will be sent to the user; may be null @timeout Timeout before the code should be re-sent, in seconds
|
||||
authenticationCodeInfo phone_number:string type:AuthenticationCodeType next_type:AuthenticationCodeType timeout:int32 = AuthenticationCodeInfo;
|
||||
|
||||
//@description Information about the email address authentication code that was sent @email_address_pattern Pattern of the email address to which an authentication code was sent
|
||||
emailAddressAuthenticationCodeInfo email_address_pattern:string = EmailAddressAuthenticationCodeInfo;
|
||||
|
||||
|
||||
//@class AuthorizationState @description Represents the current authorization state of the client
|
||||
|
||||
@ -95,9 +98,6 @@ authorizationStateClosed = AuthorizationState;
|
||||
//@description Represents the current state of 2-step verification @has_password True if a 2-step verification password has been set up @password_hint Hint for the password; can be empty @has_recovery_email_address True if a recovery email has been set up @unconfirmed_recovery_email_address_pattern Pattern of the email address to which a confirmation email was sent
|
||||
passwordState has_password:Bool password_hint:string has_recovery_email_address:Bool unconfirmed_recovery_email_address_pattern:string = PasswordState;
|
||||
|
||||
//@description Contains information available to the user after requesting password recovery @recovery_email_address_pattern Pattern of the email address to which a recovery email was sent
|
||||
passwordRecoveryInfo recovery_email_address_pattern:string = PasswordRecoveryInfo;
|
||||
|
||||
//@description Contains information about the current recovery email address @recovery_email_address Recovery email address
|
||||
recoveryEmailAddress recovery_email_address:string = RecoveryEmailAddress;
|
||||
|
||||
@ -797,6 +797,58 @@ paymentResult success:Bool verification_url:string = PaymentResult;
|
||||
paymentReceipt date:int32 payments_provider_user_id:int32 invoice:invoice order_info:orderInfo shipping_option:shippingOption credentials_title:string = PaymentReceipt;
|
||||
|
||||
|
||||
//@class PassportDataType @description Contains type of a Telegram Passport data
|
||||
|
||||
//@description The Telegram Passport data contains a user's personal details
|
||||
passportDataTypePersonalDetails = PassportDataType;
|
||||
|
||||
//@description The Telegram Passport data contains a user's passport
|
||||
passportDataTypePassport = PassportDataType;
|
||||
|
||||
//@description The Telegram Passport data contains a user's driver license
|
||||
passportDataTypeDriverLicense = PassportDataType;
|
||||
|
||||
//@description The Telegram Passport data contains a user's identity card
|
||||
passportDataTypeIdentityCard = PassportDataType;
|
||||
|
||||
//@description The Telegram Passport data contains a user's address
|
||||
passportDataTypeAddress = PassportDataType;
|
||||
|
||||
//@description The Telegram Passport data contains a user's utility bill
|
||||
passportDataTypeUtilityBill = PassportDataType;
|
||||
|
||||
//@description The Telegram Passport data contains a user's bank statement
|
||||
passportDataTypeBankStatement = PassportDataType;
|
||||
|
||||
//@description The Telegram Passport data contains a user's rental agreement
|
||||
passportDataTypeRentalAgreement = PassportDataType;
|
||||
|
||||
//@description The Telegram Passport data contains a user's phone number
|
||||
passportDataTypePhoneNumber = PassportDataType;
|
||||
|
||||
//@description The Telegram Passport data contains a user's email address
|
||||
passportDataTypeEmailAddress = PassportDataType;
|
||||
|
||||
|
||||
//@description Contains information about a Telegram Passport data @type Telegram Passport data type @data TODO data should be typed @files List of attached files
|
||||
passportData type:PassportDataType data:string files:vector<file> = PassportData;
|
||||
|
||||
//@description Contains information about a Telegram Passport data to save @type Telegram Passport data type @data TODO data should be typed @files List of attached files
|
||||
inputPassportData type:PassportDataType data:string files:vector<InputFile> = InputPassportData;
|
||||
|
||||
|
||||
//@class PassportAuthorizationForm Contains information about requested Telegram Passport authorization form @data Available data
|
||||
passportAuthorizationForm id:int32 data:vector<PassportData> = PassportAuthorizationForm;
|
||||
|
||||
|
||||
//@class EncryptedCredentials Contains an encrypted Telegram Passport data credentials @data The encrypted credentials @hash The decrypted data hash @secret Encrypted by service public key secret for data decryption
|
||||
encryptedCredentials data:bytes hash:bytes secret:bytes = EncryptedCredentials;
|
||||
|
||||
|
||||
//@description Contains information about an encrypted Telegram Passport data @type Telegram Passport data type @data Encrypted data about the user @files List of attached files @value Unencrypted data, phone number or email address
|
||||
encryptedPassportData type:PassportDataType data:bytes files:vector<file> value:string = EncryptedPassportData;
|
||||
|
||||
|
||||
//@class MessageContent @description Contains the content of a message
|
||||
|
||||
//@description A text message @text Text of the message @web_page A preview of the web page that's mentioned in the text; may be null
|
||||
@ -912,6 +964,12 @@ messageContactRegistered = MessageContent;
|
||||
//@description The current user has connected a website by logging in using Telegram Login Widget on it @domain_name Domain name of the connected website
|
||||
messageWebsiteConnected domain_name:string = MessageContent;
|
||||
|
||||
//@description Telegram Passport data has been sent @types List of types of sent data
|
||||
messagePassportDataSent types:vector<PassportDataType> = MessageContent;
|
||||
|
||||
//@description Telegram Passport data has been received; for bots only @data List of received Telegram Passport data @credentials Encrypted Secure storage data credentials
|
||||
messagePassportDataReceived data:vector<EncryptedPassportData> credentials:encryptedCredentials = MessageContent;
|
||||
|
||||
//@description Message content that is not supported by the client
|
||||
messageUnsupported = MessageContent;
|
||||
|
||||
@ -1617,6 +1675,9 @@ fileTypeProfilePhoto = FileType;
|
||||
//@description The file was sent to a secret chat (the file type is not known to the server)
|
||||
fileTypeSecret = FileType;
|
||||
|
||||
fileTypeSecure = FileType;
|
||||
fileTypeSecureEncrypted = FileType;
|
||||
|
||||
//@description The file is a sticker
|
||||
fileTypeSticker = FileType;
|
||||
|
||||
@ -2032,7 +2093,7 @@ getRecoveryEmailAddress password:string = RecoveryEmailAddress;
|
||||
setRecoveryEmailAddress password:string new_recovery_email_address:string = PasswordState;
|
||||
|
||||
//@description Requests to send a password recovery code to an email address that was previously set up
|
||||
requestPasswordRecovery = PasswordRecoveryInfo;
|
||||
requestPasswordRecovery = EmailAddressAuthenticationCodeInfo;
|
||||
|
||||
//@description Recovers the password using a recovery code sent to an email address that was previously set up @recovery_code Recovery code to check
|
||||
recoverPassword recovery_code:string = PasswordState;
|
||||
@ -2814,6 +2875,44 @@ addNetworkStatistics entry:NetworkStatisticsEntry = Ok;
|
||||
resetNetworkStatistics = Ok;
|
||||
|
||||
|
||||
//@description Returns filled Telegram Passport data @type Data type @password Password of the current user
|
||||
getPassportData type:PassportDataType password:string = PassportData;
|
||||
|
||||
//@description Sets Telegram Passport data @type Data type @password Password of the current user
|
||||
setPassportData value:InputPassportData password:string = PassportData;
|
||||
|
||||
//@description Deletes Telegram Passport data @type Data type
|
||||
deletePassportData type:PassportDataType = Ok;
|
||||
|
||||
|
||||
//@description Sends phone number verification code for Telegram Passport
|
||||
//@phone_number The phone number of the user, in international format @allow_flash_call Pass true if the authentication code may be sent via flash call to the specified phone number @is_current_phone_number Pass true if the phone number is used on the current device. Ignored if allow_flash_call is false
|
||||
sendPhoneNumberVerificationCode phone_number:string allow_flash_call:Bool is_current_phone_number:Bool = AuthenticationCodeInfo;
|
||||
|
||||
//@description Resends phone number verification code for Telegram Passport
|
||||
resendPhoneNumberVerificationCode = AuthenticationCodeInfo;
|
||||
|
||||
//@description Checks phone number verification code for Telegram Passport @code The verification code
|
||||
checkPhoneNumberVerificationCode code:string = Ok;
|
||||
|
||||
|
||||
//@description Sends email address verification code for Telegram Passport @email_address The email address
|
||||
sendEmailAddressVerificationCode email_address:string = EmailAddressAuthenticationCodeInfo;
|
||||
|
||||
//@description Resends email address verification code for Telegram Passport
|
||||
resendEmailAddressVerificationCode = EmailAddressAuthenticationCodeInfo;
|
||||
|
||||
//@description Checks email address verification code for Telegram Passport @code The verification code
|
||||
checkEmailAddressVerificationCode code:string = Ok;
|
||||
|
||||
|
||||
//@description Returns Telegram Passport authorization form for sharing data with a service @bot_id Service's bot identifier @scope Telegram Passport data types requested by the service @public_key Service's public_key
|
||||
getPassportAuthorizationForm bot_id:int32 scope:string public_key:string = PassportAuthorizationForm;
|
||||
|
||||
//@description Sends Telegram Passport authorization form, effectively sharing data with the service @autorization_form_id Authorization form identifier
|
||||
sendPassportAuthorizationForm autorization_form_id:int32 = Ok;
|
||||
|
||||
|
||||
//@description Informs the server about the number of pending bot updates if they haven't been processed for a long time; for bots only @pending_update_count The number of pending updates @error_message The last error message
|
||||
setBotUpdatesStatus pending_update_count:int32 error_message:string = Ok;
|
||||
|
||||
|
Binary file not shown.
@ -67,6 +67,7 @@ inputPhoto#fb95c6c4 id:long access_hash:long = InputPhoto;
|
||||
inputFileLocation#14637196 volume_id:long local_id:int secret:long = InputFileLocation;
|
||||
inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation;
|
||||
inputDocumentFileLocation#430f0724 id:long access_hash:long version:int = InputFileLocation;
|
||||
inputSecureFileLocation#cbc7ee28 id:long access_hash:long = InputFileLocation;
|
||||
|
||||
inputAppEvent#770656a8 time:double type:string peer:long data:string = InputAppEvent;
|
||||
|
||||
@ -104,7 +105,7 @@ userStatusLastMonth#77ebc742 = UserStatus;
|
||||
chatEmpty#9ba2d800 id:int = Chat;
|
||||
chat#d91cdd54 flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true admins_enabled:flags.3?true admin:flags.4?true deactivated:flags.5?true id:int title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel = Chat;
|
||||
chatForbidden#7328bdb id:int title:string = Chat;
|
||||
channel#450b7115 flags:# creator:flags.0?true left:flags.2?true editor:flags.3?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true democracy:flags.10?true signatures:flags.11?true min:flags.12?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string admin_rights:flags.14?ChannelAdminRights banned_rights:flags.15?ChannelBannedRights participants_count:flags.17?int = Chat;
|
||||
channel#c88974ac flags:# creator:flags.0?true left:flags.2?true editor:flags.3?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true democracy:flags.10?true signatures:flags.11?true min:flags.12?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string admin_rights:flags.14?ChannelAdminRights banned_rights:flags.15?ChannelBannedRights participants_count:flags.17?int = Chat;
|
||||
channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
|
||||
|
||||
chatFull#2e02a614 id:int participants:ChatParticipants chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> = ChatFull;
|
||||
@ -156,6 +157,8 @@ messageActionPhoneCall#80e11a7f flags:# call_id:long reason:flags.0?PhoneCallDis
|
||||
messageActionScreenshotTaken#4792929b = MessageAction;
|
||||
messageActionCustomAction#fae69f56 message:string = MessageAction;
|
||||
messageActionBotAllowed#abe9affe domain:string = MessageAction;
|
||||
messageActionSecureValuesSentMe#1b287353 values:Vector<SecureValue> credentials:SecureCredentialsEncrypted = MessageAction;
|
||||
messageActionSecureValuesSent#d95c6154 types:Vector<SecureValueType> = MessageAction;
|
||||
|
||||
dialog#e4def5db flags:# pinned:flags.2?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage = Dialog;
|
||||
|
||||
@ -445,7 +448,7 @@ documentAttributeFilename#15590068 file_name:string = DocumentAttribute;
|
||||
documentAttributeHasStickers#9801d2f7 = DocumentAttribute;
|
||||
|
||||
messages.stickersNotModified#f1749a22 = messages.Stickers;
|
||||
messages.stickers#8a8ecd32 hash:string stickers:Vector<Document> = messages.Stickers;
|
||||
messages.stickers#e4599bbd hash:int stickers:Vector<Document> = messages.Stickers;
|
||||
|
||||
stickerPack#12b299d4 emoticon:string documents:Vector<long> = StickerPack;
|
||||
|
||||
@ -468,12 +471,12 @@ authorization#7bf2e6f6 hash:long flags:int device_model:string platform:string s
|
||||
|
||||
account.authorizations#1250abde authorizations:Vector<Authorization> = account.Authorizations;
|
||||
|
||||
account.noPassword#96dabc18 new_salt:bytes email_unconfirmed_pattern:string = account.Password;
|
||||
account.password#7c18141c current_salt:bytes new_salt:bytes hint:string has_recovery:Bool email_unconfirmed_pattern:string = account.Password;
|
||||
account.noPassword#5ea182f6 new_salt:bytes new_secure_salt:bytes secure_random:bytes email_unconfirmed_pattern:string = account.Password;
|
||||
account.password#d06c5fc3 current_salt:bytes new_salt:bytes new_secure_salt:bytes secure_random:bytes hint:string has_recovery:Bool email_unconfirmed_pattern:string = account.Password;
|
||||
|
||||
account.passwordSettings#b7b72ab3 email:string = account.PasswordSettings;
|
||||
account.passwordSettings#7bd9c3f1 email:string secure_salt:bytes secure_secret:bytes secure_secret_id:long = account.PasswordSettings;
|
||||
|
||||
account.passwordInputSettings#86916deb flags:# new_salt:flags.0?bytes new_password_hash:flags.0?bytes hint:flags.0?string email:flags.1?string = account.PasswordInputSettings;
|
||||
account.passwordInputSettings#21ffa60d flags:# new_salt:flags.0?bytes new_password_hash:flags.0?bytes hint:flags.0?string email:flags.1?string new_secure_salt:flags.2?bytes new_secure_secret:flags.2?bytes new_secure_secret_id:flags.2?long = account.PasswordInputSettings;
|
||||
|
||||
auth.passwordRecovery#137948a5 email_pattern:string = auth.PasswordRecovery;
|
||||
|
||||
@ -839,6 +842,40 @@ messages.foundStickerSets#5108d648 hash:int sets:Vector<StickerSetCovered> = mes
|
||||
|
||||
fileHash#6242c773 offset:int limit:int hash:bytes = FileHash;
|
||||
|
||||
inputSecureFileUploaded#3334b0f0 id:long parts:int md5_checksum:string file_hash:bytes secret:bytes = InputSecureFile;
|
||||
inputSecureFile#5367e5be id:long access_hash:long = InputSecureFile;
|
||||
|
||||
secureFileEmpty#64199744 = SecureFile;
|
||||
secureFile#e0277a62 id:long access_hash:long size:int dc_id:int date:int file_hash:bytes secret:bytes = SecureFile;
|
||||
|
||||
secureData#8aeabec3 data:bytes data_hash:bytes secret:bytes = SecureData;
|
||||
|
||||
securePlainPhone#7d6099dd phone:string = SecurePlainData;
|
||||
securePlainEmail#21ec5a5f email:string = SecurePlainData;
|
||||
|
||||
secureValueTypePersonalDetails#9d2a81e3 = SecureValueType;
|
||||
secureValueTypePassport#3dac6a00 = SecureValueType;
|
||||
secureValueTypeDriverLicense#6e425c4 = SecureValueType;
|
||||
secureValueTypeIdentityCard#a0d0744b = SecureValueType;
|
||||
secureValueTypeAddress#cbe31e26 = SecureValueType;
|
||||
secureValueTypeUtilityBill#fc36954e = SecureValueType;
|
||||
secureValueTypeBankStatement#89137c0d = SecureValueType;
|
||||
secureValueTypeRentalAgreement#8b883488 = SecureValueType;
|
||||
secureValueTypePhone#b320aadb = SecureValueType;
|
||||
secureValueTypeEmail#8e3ca7ee = SecureValueType;
|
||||
|
||||
secureValue#ec4134c8 flags:# type:SecureValueType data:flags.0?SecureData files:flags.1?Vector<SecureFile> plain_data:flags.2?SecurePlainData selfie:flags.3?SecureFile hash:bytes = SecureValue;
|
||||
|
||||
inputSecureValue#c0da30f0 flags:# type:SecureValueType data:flags.0?SecureData files:flags.1?Vector<InputSecureFile> plain_data:flags.2?SecurePlainData selfie:flags.3?InputSecureFile = InputSecureValue;
|
||||
|
||||
secureValueHash#ed1ecdb0 type:SecureValueType hash:bytes = SecureValueHash;
|
||||
|
||||
secureCredentialsEncrypted#33f0ea47 data:bytes hash:bytes secret:bytes = SecureCredentialsEncrypted;
|
||||
|
||||
account.authorizationForm#b9d3d1f0 flags:# selfie_required:flags.1?true required_types:Vector<SecureValueType> values:Vector<SecureValue> users:Vector<User> privacy_policy_url:flags.0?string = account.AuthorizationForm;
|
||||
|
||||
account.sentEmailCode#28b1633b email_pattern:string = account.SentEmailCode;
|
||||
|
||||
---functions---
|
||||
|
||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||
@ -895,6 +932,15 @@ account.getTmpPassword#4a82327e password_hash:bytes period:int = account.TmpPass
|
||||
account.getWebAuthorizations#182e6d6f = account.WebAuthorizations;
|
||||
account.resetWebAuthorization#2d01b9ef hash:long = Bool;
|
||||
account.resetWebAuthorizations#682d2594 = Bool;
|
||||
account.getSecureValue#73665bc2 types:Vector<SecureValueType> = Vector<SecureValue>;
|
||||
account.saveSecureValue#899fe31d value:InputSecureValue secure_secret_id:long = SecureValue;
|
||||
account.deleteSecureValue#b880bc4b types:Vector<SecureValueType> = Bool;
|
||||
account.getAuthorizationForm#b86ba8e1 bot_id:int scope:string public_key:string = account.AuthorizationForm;
|
||||
account.acceptAuthorization#e7027c94 bot_id:int scope:string public_key:string value_hashes:Vector<SecureValueHash> credentials:SecureCredentialsEncrypted = Bool;
|
||||
account.sendVerifyPhoneCode#823380b4 flags:# allow_flashcall:flags.0?true phone_number:string current_number:flags.0?Bool = auth.SentCode;
|
||||
account.verifyPhone#4dd3a7f6 phone_number:string phone_code_hash:string phone_code:string = Bool;
|
||||
account.sendVerifyEmailCode#7011509f email:string = account.SentEmailCode;
|
||||
account.verifyEmail#ecba39db email:string code:string = Bool;
|
||||
|
||||
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
|
||||
@ -950,7 +996,7 @@ messages.sendEncryptedService#32d439a4 peer:InputEncryptedChat random_id:long da
|
||||
messages.receivedQueue#55a5bb66 max_qts:int = Vector<long>;
|
||||
messages.reportEncryptedSpam#4b0c8c0f peer:InputEncryptedChat = Bool;
|
||||
messages.readMessageContents#36a73f77 id:Vector<int> = messages.AffectedMessages;
|
||||
messages.getStickers#85cb5182 flags:# exclude_featured:flags.0?true emoticon:string hash:string = messages.Stickers;
|
||||
messages.getStickers#43d4f2c emoticon:string hash:int = messages.Stickers;
|
||||
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
|
||||
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
|
||||
messages.exportChatInvite#7d885289 chat_id:int = ExportedChatInvite;
|
||||
|
Binary file not shown.
@ -517,8 +517,7 @@ int32 AnimationsManager::get_saved_animations_hash() const {
|
||||
CHECK(animation != nullptr);
|
||||
auto file_view = td_->file_manager_->get_file_view(animation_id);
|
||||
CHECK(file_view.has_remote_location());
|
||||
CHECK(!file_view.remote_location().is_encrypted());
|
||||
CHECK(!file_view.remote_location().is_web());
|
||||
CHECK(file_view.remote_location().is_document());
|
||||
auto id = static_cast<uint64>(file_view.remote_location().get_id());
|
||||
numbers.push_back(static_cast<uint32>(id >> 32));
|
||||
numbers.push_back(static_cast<uint32>(id & 0xFFFFFFFF));
|
||||
@ -598,14 +597,14 @@ bool AnimationsManager::add_saved_animation_impl(FileId animation_id, Promise<Un
|
||||
promise.set_error(Status::Error(7, "Can save only sent animations"));
|
||||
return false;
|
||||
}
|
||||
if (file_view.remote_location().is_encrypted()) {
|
||||
promise.set_error(Status::Error(7, "Can't save encrypted animations"));
|
||||
return false;
|
||||
}
|
||||
if (file_view.remote_location().is_web()) {
|
||||
promise.set_error(Status::Error(7, "Can't save web animations"));
|
||||
return false;
|
||||
}
|
||||
if (!file_view.remote_location().is_document()) {
|
||||
promise.set_error(Status::Error(7, "Can't save encrypted animations"));
|
||||
return false;
|
||||
}
|
||||
|
||||
auto it = std::find(saved_animation_ids_.begin(), saved_animation_ids_.end(), animation_id);
|
||||
if (it == saved_animation_ids_.end()) {
|
||||
@ -654,7 +653,7 @@ void AnimationsManager::remove_saved_animation(const tl_object_ptr<td_api::Input
|
||||
// TODO invokeAfter
|
||||
auto file_view = td_->file_manager_->get_file_view(file_id);
|
||||
CHECK(file_view.has_remote_location());
|
||||
CHECK(!file_view.remote_location().is_encrypted());
|
||||
CHECK(file_view.remote_location().is_document());
|
||||
CHECK(!file_view.remote_location().is_web());
|
||||
td_->create_handler<SaveGifQuery>(std::move(promise))->send(file_view.remote_location().as_input_document(), true);
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/crypto.h"
|
||||
#include "td/utils/format.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/ScopeGuard.h"
|
||||
#include "td/utils/Time.h"
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/Status.h"
|
||||
#include "td/utils/Time.h"
|
||||
|
||||
namespace td {
|
||||
class SendCodeHelper {
|
||||
|
@ -6,6 +6,8 @@
|
||||
//
|
||||
#include "td/telegram/AuthManager.h"
|
||||
|
||||
#include "td/utils/format.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/tl_helpers.h"
|
||||
|
||||
namespace td {
|
||||
|
@ -2310,6 +2310,9 @@ class ContactsManager::UploadProfilePhotoCallback : public FileManager::UploadCa
|
||||
void on_upload_encrypted_ok(FileId file_id, tl_object_ptr<telegram_api::InputEncryptedFile> input_file) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void on_upload_secure_ok(FileId file_id, tl_object_ptr<telegram_api::InputSecureFile> input_file) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void on_upload_error(FileId file_id, Status error) override {
|
||||
send_closure_later(G()->contacts_manager(), &ContactsManager::on_upload_profile_photo_error, file_id,
|
||||
std::move(error));
|
||||
@ -5284,7 +5287,7 @@ ContactsManager::User *ContactsManager::get_user_force(UserId user_id) {
|
||||
auto user = telegram_api::make_object<telegram_api::user>(
|
||||
flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
|
||||
false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
|
||||
false /*ignored*/, 777000, 1, "Telegram", string(), string(), "42777", std::move(profile_photo), nullptr, 0,
|
||||
false /*ignored*/, 777000, 1, "Telegram", "Updates", string(), "42777", std::move(profile_photo), nullptr, 0,
|
||||
string(), string(), string());
|
||||
on_get_user(std::move(user));
|
||||
u = get_user(user_id);
|
||||
|
@ -43,6 +43,7 @@ class FileManager;
|
||||
class MtprotoHeader;
|
||||
class MessagesManager;
|
||||
class NetQueryDispatcher;
|
||||
class PasswordManager;
|
||||
class SecretChatsManager;
|
||||
class StateManager;
|
||||
class StickersManager;
|
||||
@ -158,6 +159,12 @@ class Global : public ActorContext {
|
||||
void set_messages_manager(ActorId<MessagesManager> messages_manager) {
|
||||
messages_manager_ = messages_manager;
|
||||
}
|
||||
ActorId<PasswordManager> password_manager() const {
|
||||
return password_manager_;
|
||||
}
|
||||
void set_password_manager(ActorId<PasswordManager> password_manager) {
|
||||
password_manager_ = password_manager;
|
||||
}
|
||||
ActorId<SecretChatsManager> secret_chats_manager() const {
|
||||
return secret_chats_manager_;
|
||||
}
|
||||
@ -291,6 +298,7 @@ class Global : public ActorContext {
|
||||
ActorId<ContactsManager> contacts_manager_;
|
||||
ActorId<FileManager> file_manager_;
|
||||
ActorId<MessagesManager> messages_manager_;
|
||||
ActorId<PasswordManager> password_manager_;
|
||||
ActorId<SecretChatsManager> secret_chats_manager_;
|
||||
ActorId<CallManager> call_manager_;
|
||||
ActorId<StickersManager> stickers_manager_;
|
||||
|
@ -5,6 +5,7 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/telegram/InlineQueriesManager.h"
|
||||
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/td_api.hpp"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "td/telegram/ReplyMarkup.hpp"
|
||||
#include "td/telegram/SecretChatActor.h"
|
||||
#include "td/telegram/SecretChatsManager.h"
|
||||
#include "td/telegram/SecureValue.hpp"
|
||||
#include "td/telegram/SequenceDispatcher.h"
|
||||
#include "td/telegram/StickersManager.h"
|
||||
#include "td/telegram/StickersManager.hpp"
|
||||
@ -3327,6 +3328,9 @@ class MessagesManager::UploadMediaCallback : public FileManager::UploadCallback
|
||||
send_closure_later(G()->messages_manager(), &MessagesManager::on_upload_media, file_id, nullptr,
|
||||
std::move(input_file));
|
||||
}
|
||||
void on_upload_secure_ok(FileId file_id, tl_object_ptr<telegram_api::InputSecureFile> input_file) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void on_upload_error(FileId file_id, Status error) override {
|
||||
send_closure_later(G()->messages_manager(), &MessagesManager::on_upload_media_error, file_id, std::move(error));
|
||||
}
|
||||
@ -3340,6 +3344,9 @@ class MessagesManager::UploadThumbnailCallback : public FileManager::UploadCallb
|
||||
void on_upload_encrypted_ok(FileId file_id, tl_object_ptr<telegram_api::InputEncryptedFile> input_file) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void on_upload_secure_ok(FileId file_id, tl_object_ptr<telegram_api::InputSecureFile> input_file) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void on_upload_error(FileId file_id, Status error) override {
|
||||
send_closure_later(G()->messages_manager(), &MessagesManager::on_upload_thumbnail, file_id, nullptr);
|
||||
}
|
||||
@ -3354,6 +3361,9 @@ class MessagesManager::UploadDialogPhotoCallback : public FileManager::UploadCal
|
||||
void on_upload_encrypted_ok(FileId file_id, tl_object_ptr<telegram_api::InputEncryptedFile> input_file) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void on_upload_secure_ok(FileId file_id, tl_object_ptr<telegram_api::InputSecureFile> input_file) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void on_upload_error(FileId file_id, Status error) override {
|
||||
send_closure_later(G()->messages_manager(), &MessagesManager::on_upload_dialog_photo_error, file_id,
|
||||
std::move(error));
|
||||
@ -3595,6 +3605,17 @@ static void store(const MessageContent *content, StorerT &storer) {
|
||||
store(m->domain_name, storer);
|
||||
break;
|
||||
}
|
||||
case MessagePassportDataSent::ID: {
|
||||
auto m = static_cast<const MessagePassportDataSent *>(content);
|
||||
store(m->types, storer);
|
||||
break;
|
||||
}
|
||||
case MessagePassportDataReceived::ID: {
|
||||
auto m = static_cast<const MessagePassportDataReceived *>(content);
|
||||
store(m->values, storer);
|
||||
store(m->credentials, storer);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -3901,6 +3922,19 @@ static void parse(unique_ptr<MessageContent> &content, ParserT &parser) {
|
||||
content = std::move(m);
|
||||
break;
|
||||
}
|
||||
case MessagePassportDataSent::ID: {
|
||||
auto m = make_unique<MessagePassportDataSent>();
|
||||
parse(m->types, parser);
|
||||
content = std::move(m);
|
||||
break;
|
||||
}
|
||||
case MessagePassportDataReceived::ID: {
|
||||
auto m = make_unique<MessagePassportDataReceived>();
|
||||
parse(m->values, parser);
|
||||
parse(m->credentials, parser);
|
||||
content = std::move(m);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -4834,6 +4868,8 @@ int32 MessagesManager::get_message_content_index_mask(const MessageContent *cont
|
||||
case MessageExpiredVideo::ID:
|
||||
case MessageCustomServiceAction::ID:
|
||||
case MessageWebsiteConnected::ID:
|
||||
case MessagePassportDataSent::ID:
|
||||
case MessagePassportDataReceived::ID:
|
||||
return 0;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -5688,6 +5724,8 @@ bool MessagesManager::need_cancel_user_dialog_action(int32 action_id, int32 mess
|
||||
case MessageContactRegistered::ID:
|
||||
case MessageCustomServiceAction::ID:
|
||||
case MessageWebsiteConnected::ID:
|
||||
case MessagePassportDataSent::ID:
|
||||
case MessagePassportDataReceived::ID:
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -7351,6 +7389,8 @@ bool MessagesManager::is_secret_message_content(int32 ttl, int32 content_type) {
|
||||
case MessageContactRegistered::ID:
|
||||
case MessageCustomServiceAction::ID:
|
||||
case MessageWebsiteConnected::ID:
|
||||
case MessagePassportDataSent::ID:
|
||||
case MessagePassportDataReceived::ID:
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -7399,6 +7439,8 @@ bool MessagesManager::is_service_message_content(int32 content_type) {
|
||||
case MessageContactRegistered::ID:
|
||||
case MessageCustomServiceAction::ID:
|
||||
case MessageWebsiteConnected::ID:
|
||||
case MessagePassportDataSent::ID:
|
||||
case MessagePassportDataReceived::ID:
|
||||
return true;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -7447,6 +7489,8 @@ bool MessagesManager::can_have_message_content_caption(int32 content_type) {
|
||||
case MessageExpiredVideo::ID:
|
||||
case MessageCustomServiceAction::ID:
|
||||
case MessageWebsiteConnected::ID:
|
||||
case MessagePassportDataSent::ID:
|
||||
case MessagePassportDataReceived::ID:
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -7520,6 +7564,8 @@ string MessagesManager::get_search_text(const Message *m) {
|
||||
case MessageExpiredVideo::ID:
|
||||
case MessageCustomServiceAction::ID:
|
||||
case MessageWebsiteConnected::ID:
|
||||
case MessagePassportDataSent::ID:
|
||||
case MessagePassportDataReceived::ID:
|
||||
return "";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -7568,6 +7614,8 @@ bool MessagesManager::is_allowed_media_group_content(int32 content_type) {
|
||||
case MessageContactRegistered::ID:
|
||||
case MessageCustomServiceAction::ID:
|
||||
case MessageWebsiteConnected::ID:
|
||||
case MessagePassportDataSent::ID:
|
||||
case MessagePassportDataReceived::ID:
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -8897,6 +8945,16 @@ tl_object_ptr<td_api::MessageContent> MessagesManager::get_message_content_objec
|
||||
const MessageWebsiteConnected *m = static_cast<const MessageWebsiteConnected *>(content);
|
||||
return make_tl_object<td_api::messageWebsiteConnected>(m->domain_name);
|
||||
}
|
||||
case MessagePassportDataSent::ID: {
|
||||
const MessagePassportDataSent *m = static_cast<const MessagePassportDataSent *>(content);
|
||||
return make_tl_object<td_api::messagePassportDataSent>(get_passport_data_types_object(m->types));
|
||||
}
|
||||
case MessagePassportDataReceived::ID: {
|
||||
const MessagePassportDataReceived *m = static_cast<const MessagePassportDataReceived *>(content);
|
||||
return make_tl_object<td_api::messagePassportDataReceived>(
|
||||
get_encrypted_passport_data_object(td_->file_manager_.get(), m->values),
|
||||
get_encrypted_credentials_object(m->credentials));
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
@ -14497,6 +14555,8 @@ SecretInputMedia MessagesManager::get_secret_input_media(const MessageContent *c
|
||||
case MessageExpiredVideo::ID:
|
||||
case MessageCustomServiceAction::ID:
|
||||
case MessageWebsiteConnected::ID:
|
||||
case MessagePassportDataSent::ID:
|
||||
case MessagePassportDataReceived::ID:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -14668,6 +14728,8 @@ tl_object_ptr<telegram_api::InputMedia> MessagesManager::get_input_media(
|
||||
case MessageExpiredVideo::ID:
|
||||
case MessageCustomServiceAction::ID:
|
||||
case MessageWebsiteConnected::ID:
|
||||
case MessagePassportDataSent::ID:
|
||||
case MessagePassportDataReceived::ID:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -14736,6 +14798,8 @@ void MessagesManager::delete_message_content_thumbnail(MessageContent *content)
|
||||
case MessageExpiredVideo::ID:
|
||||
case MessageCustomServiceAction::ID:
|
||||
case MessageWebsiteConnected::ID:
|
||||
case MessagePassportDataSent::ID:
|
||||
case MessagePassportDataReceived::ID:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -15023,6 +15087,8 @@ Status MessagesManager::can_send_message_content(DialogId dialog_id, const Messa
|
||||
case MessageExpiredVideo::ID:
|
||||
case MessageCustomServiceAction::ID:
|
||||
case MessageWebsiteConnected::ID:
|
||||
case MessagePassportDataSent::ID:
|
||||
case MessagePassportDataReceived::ID:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return Status::OK();
|
||||
@ -15452,6 +15518,10 @@ void MessagesManager::add_message_dependencies(Dependencies &dependencies, Dialo
|
||||
break;
|
||||
case MessageWebsiteConnected::ID:
|
||||
break;
|
||||
case MessagePassportDataSent::ID:
|
||||
break;
|
||||
case MessagePassportDataReceived::ID:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
@ -16144,7 +16214,7 @@ void MessagesManager::do_send_message(DialogId dialog_id, Message *m, vector<int
|
||||
auto layer = td_->contacts_manager_->get_secret_chat_layer(dialog_id.get_secret_chat_id());
|
||||
auto secret_input_media = get_secret_input_media(content, nullptr, BufferSlice(), layer);
|
||||
if (secret_input_media.empty()) {
|
||||
CHECK(file_view.is_encrypted());
|
||||
CHECK(file_view.is_encrypted_secret());
|
||||
CHECK(file_id.is_valid());
|
||||
being_uploaded_files_[file_id] = {FullMessageId(dialog_id, m->message_id), thumbnail_file_id};
|
||||
LOG(INFO) << "Ask to upload encrypted file " << file_id;
|
||||
@ -16947,6 +17017,8 @@ bool MessagesManager::can_edit_message(DialogId dialog_id, const Message *m, boo
|
||||
case MessageExpiredVideo::ID:
|
||||
case MessageCustomServiceAction::ID:
|
||||
case MessageWebsiteConnected::ID:
|
||||
case MessagePassportDataSent::ID:
|
||||
case MessagePassportDataReceived::ID:
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -18730,6 +18802,8 @@ FullMessageId MessagesManager::on_send_message_success(int64 random_id, MessageI
|
||||
case MessageExpiredVideo::ID:
|
||||
case MessageCustomServiceAction::ID:
|
||||
case MessageWebsiteConnected::ID:
|
||||
case MessagePassportDataSent::ID:
|
||||
case MessagePassportDataReceived::ID:
|
||||
LOG(ERROR) << "Receive new file " << new_file_id << " in a sent message of the type " << content_type;
|
||||
break;
|
||||
default:
|
||||
@ -21124,7 +21198,7 @@ unique_ptr<MessageContent> MessagesManager::dup_message_content(DialogId dialog_
|
||||
bool to_secret = dialog_id.get_type() == DialogType::SecretChat;
|
||||
auto fix_file_id = [dialog_id, to_secret, file_manager = td_->file_manager_.get()](FileId file_id) {
|
||||
auto file_view = file_manager->get_file_view(file_id);
|
||||
if (to_secret && !file_view.is_encrypted()) {
|
||||
if (to_secret && !file_view.is_encrypted_secret()) {
|
||||
auto download_file_id = file_manager->dup_file_id(file_id);
|
||||
file_id = file_manager
|
||||
->register_generate(FileType::Encrypted, FileLocationSource::FromServer, "",
|
||||
@ -21302,6 +21376,8 @@ unique_ptr<MessageContent> MessagesManager::dup_message_content(DialogId dialog_
|
||||
case MessageExpiredVideo::ID:
|
||||
case MessageCustomServiceAction::ID:
|
||||
case MessageWebsiteConnected::ID:
|
||||
case MessagePassportDataSent::ID:
|
||||
case MessagePassportDataReceived::ID:
|
||||
return nullptr;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -21468,6 +21544,18 @@ unique_ptr<MessageContent> MessagesManager::get_message_action_content(
|
||||
auto bot_allowed = move_tl_object_as<telegram_api::messageActionBotAllowed>(action);
|
||||
return make_unique<MessageWebsiteConnected>(std::move(bot_allowed->domain_));
|
||||
}
|
||||
case telegram_api::messageActionSecureValuesSent::ID: {
|
||||
LOG_IF(ERROR, td_->auth_manager_->is_bot()) << "Receive MessageActionSecureValuesSent";
|
||||
auto secure_values = move_tl_object_as<telegram_api::messageActionSecureValuesSent>(action);
|
||||
return make_unique<MessagePassportDataSent>(get_secure_value_types(std::move(secure_values->types_)));
|
||||
}
|
||||
case telegram_api::messageActionSecureValuesSentMe::ID: {
|
||||
LOG_IF(ERROR, !td_->auth_manager_->is_bot()) << "Receive MessageActionSecureValuesSentMe";
|
||||
auto secure_values = move_tl_object_as<telegram_api::messageActionSecureValuesSentMe>(action);
|
||||
return make_unique<MessagePassportDataReceived>(
|
||||
get_encrypted_secure_values(td_->file_manager_.get(), std::move(secure_values->values_)),
|
||||
get_secure_credentials(std::move(secure_values->credentials_)));
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -22985,6 +23073,26 @@ bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_me
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MessagePassportDataSent::ID: {
|
||||
auto old_ = static_cast<const MessagePassportDataSent *>(old_content.get());
|
||||
auto new_ = static_cast<const MessagePassportDataSent *>(new_content.get());
|
||||
if (old_->types != new_->types) {
|
||||
need_update = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MessagePassportDataReceived::ID: {
|
||||
auto old_ = static_cast<const MessagePassportDataReceived *>(old_content.get());
|
||||
auto new_ = static_cast<const MessagePassportDataReceived *>(new_content.get());
|
||||
if (old_->values != new_->values) {
|
||||
// FIXME merge files?
|
||||
need_update = true;
|
||||
}
|
||||
if (old_->credentials != new_->credentials) {
|
||||
need_update = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MessageUnsupported::ID:
|
||||
break;
|
||||
default:
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "td/telegram/ReplyMarkup.h"
|
||||
#include "td/telegram/SecretChatId.h"
|
||||
#include "td/telegram/SecretInputMedia.h"
|
||||
#include "td/telegram/SecureValue.h"
|
||||
#include "td/telegram/UserId.h"
|
||||
#include "td/telegram/WebPageId.h"
|
||||
|
||||
@ -626,6 +627,36 @@ class MessageWebsiteConnected : public MessageContent {
|
||||
}
|
||||
};
|
||||
|
||||
class MessagePassportDataSent : public MessageContent {
|
||||
public:
|
||||
vector<SecureValueType> types;
|
||||
|
||||
MessagePassportDataSent() = default;
|
||||
explicit MessagePassportDataSent(vector<SecureValueType> &&types) : types(std::move(types)) {
|
||||
}
|
||||
|
||||
static const int32 ID = 38;
|
||||
int32 get_id() const override {
|
||||
return ID;
|
||||
}
|
||||
};
|
||||
|
||||
class MessagePassportDataReceived : public MessageContent {
|
||||
public:
|
||||
vector<EncryptedSecureValue> values;
|
||||
SecureCredentials credentials;
|
||||
|
||||
MessagePassportDataReceived() = default;
|
||||
MessagePassportDataReceived(vector<EncryptedSecureValue> &&values, SecureCredentials &&credentials)
|
||||
: values(std::move(values)), credentials(std::move(credentials)) {
|
||||
}
|
||||
|
||||
static const int32 ID = 39;
|
||||
int32 get_id() const override {
|
||||
return ID;
|
||||
}
|
||||
};
|
||||
|
||||
class InputMessageText {
|
||||
public:
|
||||
FormattedText text;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "td/utils/crypto.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/Random.h"
|
||||
#include "td/utils/Slice.h"
|
||||
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h" // TODO: this file is already included. Why?
|
||||
@ -44,6 +45,7 @@ void PasswordManager::set_password(string current_password, string new_password,
|
||||
|
||||
update_settings.current_password = std::move(current_password);
|
||||
update_settings.update_password = true;
|
||||
//update_settings.update_secure_secret = true;
|
||||
update_settings.new_password = std::move(new_password);
|
||||
update_settings.new_hint = std::move(new_hint);
|
||||
|
||||
@ -64,6 +66,52 @@ void PasswordManager::set_recovery_email_address(string password, string new_rec
|
||||
update_password_settings(std::move(update_settings), std::move(promise));
|
||||
}
|
||||
|
||||
void PasswordManager::get_secure_secret(string password, optional<int64> hash,
|
||||
Promise<secure_storage::Secret> promise) {
|
||||
return do_get_secure_secret(true, std::move(password), std::move(hash), std::move(promise));
|
||||
}
|
||||
|
||||
void PasswordManager::do_get_secure_secret(bool recursive, string password, optional<int64> hash,
|
||||
Promise<secure_storage::Secret> promise) {
|
||||
if (secret_ && (!hash || secret_.value().get_hash() == hash.value())) {
|
||||
return promise.set_value(secret_.value().clone());
|
||||
}
|
||||
get_full_state(
|
||||
password, PromiseCreator::lambda([password, recursive, hash = std::move(hash), promise = std::move(promise),
|
||||
actor_id = actor_id(this)](Result<PasswordFullState> r_state) mutable {
|
||||
if (r_state.is_error()) {
|
||||
return promise.set_error(r_state.move_as_error());
|
||||
}
|
||||
auto state = r_state.move_as_ok();
|
||||
if (!state.state.has_password) {
|
||||
return promise.set_error(Status::Error(400, "2fa is off"));
|
||||
}
|
||||
if (state.private_state.secret) {
|
||||
send_closure(actor_id, &PasswordManager::cache_secret, state.private_state.secret.value().clone());
|
||||
return promise.set_value(std::move(state.private_state.secret.value()));
|
||||
}
|
||||
if (!recursive) {
|
||||
return promise.set_error(Status::Error(400, "Failed to get secure secret"));
|
||||
}
|
||||
|
||||
auto new_promise =
|
||||
PromiseCreator::lambda([recursive, password, hash = std::move(hash), promise = std::move(promise),
|
||||
actor_id = actor_id](Result<bool> r_ok) mutable {
|
||||
if (r_ok.is_error()) {
|
||||
return promise.set_error(r_ok.move_as_error());
|
||||
}
|
||||
send_closure(actor_id, &PasswordManager::do_get_secure_secret, false, std::move(password),
|
||||
std::move(hash), std::move(promise));
|
||||
});
|
||||
|
||||
UpdateSettings update_settings;
|
||||
update_settings.current_password = password;
|
||||
update_settings.update_secure_secret = true;
|
||||
send_closure(actor_id, &PasswordManager::do_update_password_settings, std::move(update_settings),
|
||||
std::move(state), std::move(new_promise));
|
||||
}));
|
||||
}
|
||||
|
||||
void PasswordManager::get_temp_password_state(Promise<TempState> promise) /*const*/ {
|
||||
promise.set_value(temp_password_state_.as_td_api());
|
||||
}
|
||||
@ -135,20 +183,61 @@ void PasswordManager::on_finish_create_temp_password(Result<TempPasswordState> r
|
||||
create_temp_password_promise_.set_value(temp_password_state_.as_td_api());
|
||||
}
|
||||
|
||||
void PasswordManager::get_recovery_email_address(string password,
|
||||
Promise<tl_object_ptr<td_api::recoveryEmailAddress>> promise) {
|
||||
void PasswordManager::get_full_state(string password, Promise<PasswordFullState> promise) {
|
||||
do_get_state(PromiseCreator::lambda([password = std::move(password), promise = std::move(promise),
|
||||
actor_id = actor_id(this)](Result<PasswordState> r_state) mutable {
|
||||
if (r_state.is_error()) {
|
||||
return promise.set_error(r_state.move_as_error());
|
||||
}
|
||||
send_closure(actor_id, &PasswordManager::do_get_recovery_email_address, std::move(password), r_state.move_as_ok(),
|
||||
send_closure(actor_id, &PasswordManager::do_get_full_state, std::move(password), r_state.move_as_ok(),
|
||||
std::move(promise));
|
||||
}));
|
||||
}
|
||||
|
||||
void PasswordManager::request_password_recovery(Promise<tl_object_ptr<td_api::passwordRecoveryInfo>> promise) {
|
||||
send_with_promise(G()->net_query_creator().create(create_storer(telegram_api::auth_requestPasswordRecovery())),
|
||||
void PasswordManager::do_get_full_state(string password, PasswordState state, Promise<PasswordFullState> promise) {
|
||||
auto current_salt = state.current_salt;
|
||||
send_with_promise(G()->net_query_creator().create(create_storer(
|
||||
telegram_api::account_getPasswordSettings(calc_password_hash(password, current_salt)))),
|
||||
PromiseCreator::lambda([promise = std::move(promise), state = std::move(state),
|
||||
password](Result<NetQueryPtr> r_query) mutable {
|
||||
promise.set_result([&]() -> Result<PasswordFullState> {
|
||||
TRY_RESULT(query, std::move(r_query));
|
||||
TRY_RESULT(result, fetch_result<telegram_api::account_getPasswordSettings>(std::move(query)));
|
||||
PasswordPrivateState private_state;
|
||||
private_state.email = result->email_;
|
||||
|
||||
namespace ss = secure_storage;
|
||||
auto r_secret = [&]() -> Result<ss::Secret> {
|
||||
TRY_RESULT(encrypted_secret, ss::EncryptedSecret::create(result->secure_secret_.as_slice()));
|
||||
return encrypted_secret.decrypt(PSLICE() << result->secure_salt_.as_slice() << password
|
||||
<< result->secure_salt_.as_slice());
|
||||
}();
|
||||
|
||||
LOG_IF(ERROR, r_secret.is_error()) << r_secret.error();
|
||||
LOG_IF(ERROR, r_secret.is_ok()) << "HAS SECRET";
|
||||
private_state.secret = std::move(r_secret);
|
||||
return PasswordFullState{std::move(state), std::move(private_state)};
|
||||
}());
|
||||
}));
|
||||
}
|
||||
|
||||
void PasswordManager::get_recovery_email_address(string password,
|
||||
Promise<tl_object_ptr<td_api::recoveryEmailAddress>> promise) {
|
||||
get_full_state(
|
||||
password,
|
||||
PromiseCreator::lambda([password, promise = std::move(promise)](Result<PasswordFullState> r_state) mutable {
|
||||
if (r_state.is_error()) {
|
||||
return promise.set_error(r_state.move_as_error());
|
||||
}
|
||||
auto state = r_state.move_as_ok();
|
||||
return promise.set_value(make_tl_object<td_api::recoveryEmailAddress>(state.private_state.email));
|
||||
}));
|
||||
}
|
||||
|
||||
void PasswordManager::request_password_recovery(
|
||||
Promise<tl_object_ptr<td_api::emailAddressAuthenticationCodeInfo>> promise) {
|
||||
send_with_promise(
|
||||
G()->net_query_creator().create(create_storer(telegram_api::auth_requestPasswordRecovery())),
|
||||
PromiseCreator::lambda([promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
|
||||
if (r_query.is_error()) {
|
||||
return promise.set_error(r_query.move_as_error());
|
||||
@ -158,7 +247,7 @@ void PasswordManager::request_password_recovery(Promise<tl_object_ptr<td_api::pa
|
||||
return promise.set_error(r_result.move_as_error());
|
||||
}
|
||||
auto result = r_result.move_as_ok();
|
||||
return promise.set_value(make_tl_object<td_api::passwordRecoveryInfo>(result->email_pattern_));
|
||||
return promise.set_value(make_tl_object<td_api::emailAddressAuthenticationCodeInfo>(result->email_pattern_));
|
||||
}));
|
||||
}
|
||||
|
||||
@ -177,23 +266,6 @@ void PasswordManager::recover_password(string code, Promise<State> promise) {
|
||||
}));
|
||||
}
|
||||
|
||||
void PasswordManager::do_get_recovery_email_address(string password, PasswordState state,
|
||||
Promise<tl_object_ptr<td_api::recoveryEmailAddress>> promise) {
|
||||
send_with_promise(G()->net_query_creator().create(create_storer(
|
||||
telegram_api::account_getPasswordSettings(calc_password_hash(password, state.current_salt)))),
|
||||
PromiseCreator::lambda([promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
|
||||
if (r_query.is_error()) {
|
||||
return promise.set_error(r_query.move_as_error());
|
||||
}
|
||||
auto r_result = fetch_result<telegram_api::account_getPasswordSettings>(r_query.move_as_ok());
|
||||
if (r_result.is_error()) {
|
||||
return promise.set_error(r_result.move_as_error());
|
||||
}
|
||||
auto result = r_result.move_as_ok();
|
||||
return promise.set_value(make_tl_object<td_api::recoveryEmailAddress>(result->email_));
|
||||
}));
|
||||
}
|
||||
|
||||
void PasswordManager::update_password_settings(UpdateSettings update_settings, Promise<State> promise) {
|
||||
auto result_promise = PromiseCreator::lambda(
|
||||
[actor_id = actor_id(this), promise = std::move(promise)](Result<bool> r_update_settings) mutable {
|
||||
@ -208,9 +280,11 @@ void PasswordManager::update_password_settings(UpdateSettings update_settings, P
|
||||
send_closure(actor_id, &PasswordManager::get_state, std::move(promise));
|
||||
});
|
||||
|
||||
do_get_state(
|
||||
auto password = update_settings.current_password;
|
||||
get_full_state(
|
||||
std::move(password),
|
||||
PromiseCreator::lambda([=, actor_id = actor_id(this), result_promise = std::move(result_promise),
|
||||
update_settings = std::move(update_settings)](Result<PasswordState> r_state) mutable {
|
||||
update_settings = std::move(update_settings)](Result<PasswordFullState> r_state) mutable {
|
||||
if (r_state.is_error()) {
|
||||
result_promise.set_error(r_state.move_as_error());
|
||||
return;
|
||||
@ -220,24 +294,60 @@ void PasswordManager::update_password_settings(UpdateSettings update_settings, P
|
||||
}));
|
||||
}
|
||||
|
||||
void PasswordManager::do_update_password_settings(UpdateSettings update_settings, PasswordState state,
|
||||
namespace {
|
||||
BufferSlice create_salt(Slice server_salt) {
|
||||
BufferSlice new_salt(server_salt.size() + 32);
|
||||
new_salt.as_slice().copy_from(server_salt);
|
||||
Random::secure_bytes(new_salt.as_slice().remove_prefix(server_salt.size()));
|
||||
return new_salt;
|
||||
}
|
||||
} // namespace
|
||||
void PasswordManager::do_update_password_settings(UpdateSettings update_settings, PasswordFullState full_state,
|
||||
Promise<bool> promise) {
|
||||
auto state = std::move(full_state.state);
|
||||
auto private_state = std::move(full_state.private_state);
|
||||
auto new_settings = make_tl_object<telegram_api::account_passwordInputSettings>();
|
||||
if (update_settings.update_password) {
|
||||
new_settings->flags_ |= telegram_api::account_passwordInputSettings::NEW_PASSWORD_HASH_MASK;
|
||||
new_settings->flags_ |= telegram_api::account_passwordInputSettings::NEW_SALT_MASK;
|
||||
new_settings->flags_ |= telegram_api::account_passwordInputSettings::HINT_MASK;
|
||||
if (!update_settings.new_password.empty()) {
|
||||
BufferSlice new_salt(state.new_salt.size() * 2);
|
||||
new_salt.as_slice().copy_from(state.new_salt);
|
||||
Random::secure_bytes(new_salt.as_slice().remove_prefix(state.new_salt.size()));
|
||||
auto new_salt = create_salt(state.new_salt);
|
||||
|
||||
new_settings->new_salt_ = std::move(new_salt);
|
||||
new_settings->new_password_hash_ =
|
||||
calc_password_hash(update_settings.new_password, new_settings->new_salt_.as_slice().str());
|
||||
new_settings->hint_ = std::move(update_settings.new_hint);
|
||||
if (private_state.secret) {
|
||||
update_settings.update_secure_secret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!state.has_password || (update_settings.update_password && update_settings.new_password.empty())) {
|
||||
update_settings.update_secure_secret = false;
|
||||
}
|
||||
|
||||
if (update_settings.update_secure_secret) {
|
||||
new_settings->flags_ |= telegram_api::account_passwordInputSettings::NEW_SECURE_SECRET_ID_MASK;
|
||||
new_settings->flags_ |= telegram_api::account_passwordInputSettings::NEW_SECURE_SALT_MASK;
|
||||
new_settings->flags_ |= telegram_api::account_passwordInputSettings::NEW_SECURE_SECRET_MASK;
|
||||
auto secret = [&]() {
|
||||
if (private_state.secret) {
|
||||
return std::move(private_state.secret.value());
|
||||
}
|
||||
return secure_storage::Secret::create_new();
|
||||
}();
|
||||
auto new_secure_salt = create_salt(state.new_secure_salt);
|
||||
auto encrypted_secret = secret.encrypt(
|
||||
PSLICE() << new_secure_salt.as_slice()
|
||||
<< (update_settings.update_password ? update_settings.new_password : update_settings.current_password)
|
||||
<< new_secure_salt.as_slice());
|
||||
|
||||
new_settings->new_secure_salt_ = std::move(new_secure_salt);
|
||||
new_settings->new_secure_secret_ = BufferSlice(encrypted_secret.as_slice());
|
||||
new_settings->new_secure_secret_id_ = secret.get_hash();
|
||||
}
|
||||
if (update_settings.update_recovery_email_address) {
|
||||
new_settings->flags_ |= telegram_api::account_passwordInputSettings::EMAIL_MASK;
|
||||
new_settings->email_ = std::move(update_settings.recovery_email_address);
|
||||
@ -297,6 +407,8 @@ void PasswordManager::do_get_state(Promise<PasswordState> promise) {
|
||||
state.password_hint = "";
|
||||
state.current_salt = "";
|
||||
state.new_salt = no_password->new_salt_.as_slice().str();
|
||||
state.new_secure_salt = no_password->new_secure_salt_.as_slice().str();
|
||||
state.secure_random = no_password->secure_random_.as_slice().str();
|
||||
state.has_recovery_email_address = false;
|
||||
state.unconfirmed_recovery_email_address_pattern = no_password->email_unconfirmed_pattern_;
|
||||
} else if (result->get_id() == telegram_api::account_password::ID) {
|
||||
@ -305,6 +417,8 @@ void PasswordManager::do_get_state(Promise<PasswordState> promise) {
|
||||
state.password_hint = password->hint_;
|
||||
state.current_salt = password->current_salt_.as_slice().str();
|
||||
state.new_salt = password->new_salt_.as_slice().str();
|
||||
state.new_secure_salt = password->new_secure_salt_.as_slice().str();
|
||||
state.secure_random = password->secure_random_.as_slice().str();
|
||||
state.has_recovery_email_address = password->has_recovery_;
|
||||
state.unconfirmed_recovery_email_address_pattern = password->email_unconfirmed_pattern_;
|
||||
} else {
|
||||
@ -313,6 +427,10 @@ void PasswordManager::do_get_state(Promise<PasswordState> promise) {
|
||||
promise.set_value(std::move(state));
|
||||
}));
|
||||
}
|
||||
void PasswordManager::cache_secret(secure_storage::Secret secret) {
|
||||
LOG(ERROR) << "CACHE";
|
||||
secret_ = std::move(secret);
|
||||
}
|
||||
|
||||
void PasswordManager::on_result(NetQueryPtr query) {
|
||||
auto token = get_link_token();
|
||||
|
@ -7,9 +7,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "td/telegram/net/NetQuery.h"
|
||||
#include "td/telegram/SecureStorage.h"
|
||||
|
||||
#include "td/utils/Container.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/optional.h"
|
||||
#include "td/utils/Status.h"
|
||||
#include "td/utils/tl_helpers.h"
|
||||
|
||||
@ -54,9 +56,11 @@ class PasswordManager : public NetQueryCallback {
|
||||
void set_recovery_email_address(string password, string new_recovery_email_address, Promise<State> promise);
|
||||
void get_recovery_email_address(string password, Promise<tl_object_ptr<td_api::recoveryEmailAddress>> promise);
|
||||
|
||||
void request_password_recovery(Promise<tl_object_ptr<td_api::passwordRecoveryInfo>> promise);
|
||||
void request_password_recovery(Promise<tl_object_ptr<td_api::emailAddressAuthenticationCodeInfo>> promise);
|
||||
void recover_password(string code, Promise<State> promise);
|
||||
|
||||
void get_secure_secret(string password, optional<int64> hash, Promise<secure_storage::Secret> promise);
|
||||
|
||||
void get_temp_password_state(Promise<TempState> promise) /*const*/;
|
||||
void create_temp_password(string password, int32 timeout, Promise<TempState> promise);
|
||||
void drop_temp_password();
|
||||
@ -75,12 +79,25 @@ class PasswordManager : public NetQueryCallback {
|
||||
string current_salt;
|
||||
string new_salt;
|
||||
|
||||
string new_secure_salt;
|
||||
string secure_random;
|
||||
|
||||
State as_td_api() const {
|
||||
return td_api::make_object<td_api::passwordState>(has_password, password_hint, has_recovery_email_address,
|
||||
unconfirmed_recovery_email_address_pattern);
|
||||
}
|
||||
};
|
||||
|
||||
struct PasswordPrivateState {
|
||||
string email;
|
||||
optional<secure_storage::Secret> secret;
|
||||
};
|
||||
|
||||
struct PasswordFullState {
|
||||
PasswordState state;
|
||||
PasswordPrivateState private_state;
|
||||
};
|
||||
|
||||
struct UpdateSettings {
|
||||
string current_password;
|
||||
|
||||
@ -88,18 +105,23 @@ class PasswordManager : public NetQueryCallback {
|
||||
string new_password;
|
||||
string new_hint;
|
||||
|
||||
bool update_secure_secret = false;
|
||||
|
||||
bool update_recovery_email_address = false;
|
||||
string recovery_email_address;
|
||||
};
|
||||
|
||||
optional<secure_storage::Secret> secret_;
|
||||
TempPasswordState temp_password_state_;
|
||||
Promise<TempState> create_temp_password_promise_;
|
||||
|
||||
void update_password_settings(UpdateSettings update_settings, Promise<State> promise);
|
||||
void do_update_password_settings(UpdateSettings update_settings, PasswordState state, Promise<bool> promise);
|
||||
void do_update_password_settings(UpdateSettings update_settings, PasswordFullState full_state, Promise<bool> promise);
|
||||
void do_get_state(Promise<PasswordState> promise);
|
||||
void do_get_recovery_email_address(string password, PasswordState state,
|
||||
Promise<tl_object_ptr<td_api::recoveryEmailAddress>> promise);
|
||||
void get_full_state(string password, Promise<PasswordFullState> promise);
|
||||
void do_get_secure_secret(bool recursive, string passwod, optional<int64>, Promise<secure_storage::Secret> promise);
|
||||
void do_get_full_state(string password, PasswordState state, Promise<PasswordFullState> promise);
|
||||
void cache_secret(secure_storage::Secret secret);
|
||||
|
||||
void do_create_temp_password(string password, int32 timeout, PasswordState &&password_state,
|
||||
Promise<TempPasswordState> promise);
|
||||
|
@ -503,7 +503,7 @@ bool photo_has_input_media(FileManager *file_manager, const Photo &photo, bool i
|
||||
auto file_id = photo.photos.back().file_id;
|
||||
auto file_view = file_manager->get_file_view(file_id);
|
||||
if (is_secret) {
|
||||
if (file_view.encryption_key().empty() || !file_view.has_remote_location()) {
|
||||
if (!file_view.is_encrypted_secret() || !file_view.has_remote_location()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5,10 +5,24 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/telegram/SecureStorage.h"
|
||||
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/Random.h"
|
||||
|
||||
namespace td {
|
||||
namespace secure_storage {
|
||||
|
||||
// Helpers
|
||||
Result<ValueHash> ValueHash::create(Slice data) {
|
||||
UInt256 hash;
|
||||
if (data.size() != ::td::as_slice(hash).size()) {
|
||||
return Status::Error("Wrong hash size");
|
||||
}
|
||||
::td::as_slice(hash).copy_from(data);
|
||||
return ValueHash{hash};
|
||||
}
|
||||
|
||||
AesCbcState calc_aes_cbc_state(Slice seed) {
|
||||
UInt<512> hash;
|
||||
auto hash_slice = as_slice(hash);
|
||||
@ -24,7 +38,7 @@ template <class F>
|
||||
Status data_view_for_each(DataView &data, F &&f) {
|
||||
const int64 step = 128 << 10;
|
||||
for (int64 i = 0, size = data.size(); i < size; i += step) {
|
||||
TRY_RESULT(bytes, data.pread(i, std::min(step, size - i)));
|
||||
TRY_RESULT(bytes, data.pread(i, min(step, size - i)));
|
||||
TRY_STATUS(f(std::move(bytes)));
|
||||
}
|
||||
return Status::OK();
|
||||
@ -42,6 +56,12 @@ Result<ValueHash> calc_value_hash(DataView &data_view) {
|
||||
return ValueHash{res};
|
||||
}
|
||||
|
||||
ValueHash calc_value_hash(Slice data) {
|
||||
UInt256 res;
|
||||
sha256(data, as_slice(res));
|
||||
return ValueHash{res};
|
||||
}
|
||||
|
||||
BufferSlice gen_random_prefix(int64 data_size) {
|
||||
BufferSlice buff(narrow_cast<size_t>(((32 + 15 + data_size) & -16) - data_size));
|
||||
Random::secure_bytes(buff.as_slice());
|
||||
@ -53,7 +73,7 @@ BufferSlice gen_random_prefix(int64 data_size) {
|
||||
FileDataView::FileDataView(FileFd &fd, int64 size) : fd_(fd), size_(size) {
|
||||
}
|
||||
|
||||
int64 FileDataView::size() {
|
||||
int64 FileDataView::size() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
@ -68,7 +88,7 @@ Result<BufferSlice> FileDataView::pread(int64 offset, int64 size) {
|
||||
|
||||
BufferSliceDataView::BufferSliceDataView(BufferSlice buffer_slice) : buffer_slice_(std::move(buffer_slice)) {
|
||||
}
|
||||
int64 BufferSliceDataView::size() {
|
||||
int64 BufferSliceDataView::size() const {
|
||||
return narrow_cast<int64>(buffer_slice_.size());
|
||||
}
|
||||
Result<BufferSlice> BufferSliceDataView::pread(int64 offset, int64 size) {
|
||||
@ -81,7 +101,7 @@ Result<BufferSlice> BufferSliceDataView::pread(int64 offset, int64 size) {
|
||||
|
||||
ConcatDataView::ConcatDataView(DataView &left, DataView &right) : left_(left), right_(right) {
|
||||
}
|
||||
int64 ConcatDataView::size() {
|
||||
int64 ConcatDataView::size() const {
|
||||
return left_.size() + right_.size();
|
||||
}
|
||||
Result<BufferSlice> ConcatDataView::pread(int64 offset, int64 size) {
|
||||
@ -91,8 +111,8 @@ Result<BufferSlice> ConcatDataView::pread(int64 offset, int64 size) {
|
||||
}
|
||||
|
||||
auto substr = [](DataView &slice, int64 offset, int64 size) -> Result<BufferSlice> {
|
||||
auto l = std::max(int64{0}, offset);
|
||||
auto r = std::min(slice.size(), offset + size);
|
||||
auto l = max(int64{0}, offset);
|
||||
auto r = min(slice.size(), offset + size);
|
||||
if (l >= r) {
|
||||
return BufferSlice();
|
||||
}
|
||||
@ -125,11 +145,11 @@ Slice Password::as_slice() const {
|
||||
// Secret
|
||||
namespace {
|
||||
uint8 secret_checksum(Slice secret) {
|
||||
uint8 sum = 0;
|
||||
uint32 sum = 0;
|
||||
for (uint8 c : secret) {
|
||||
sum += c;
|
||||
}
|
||||
return static_cast<uint8>(239 - sum);
|
||||
return static_cast<uint8>((255 + 239 - sum % 255) % 255);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -137,12 +157,17 @@ Result<Secret> Secret::create(Slice secret) {
|
||||
if (secret.size() != 32) {
|
||||
return Status::Error("wrong secret size");
|
||||
}
|
||||
if (secret_checksum(secret) != 0) {
|
||||
return Status::Error("Wrong cheksum");
|
||||
uint32 checksum = secret_checksum(secret);
|
||||
if (checksum != 0) {
|
||||
return Status::Error(PSLICE() << "Wrong cheksum " << checksum);
|
||||
}
|
||||
UInt256 res;
|
||||
td::as_slice(res).copy_from(secret);
|
||||
return Secret{res};
|
||||
|
||||
UInt256 secret_sha256;
|
||||
sha256(secret, ::td::as_slice(secret_sha256));
|
||||
auto hash = as<int64>(secret_sha256.raw);
|
||||
return Secret{res, hash};
|
||||
}
|
||||
|
||||
Secret Secret::create_new() {
|
||||
@ -150,7 +175,8 @@ Secret Secret::create_new() {
|
||||
auto secret_slice = td::as_slice(secret);
|
||||
Random::secure_bytes(secret_slice);
|
||||
auto checksum_diff = secret_checksum(secret_slice);
|
||||
secret_slice.ubegin()[0] += checksum_diff;
|
||||
uint8 new_byte = (static_cast<uint32>(secret_slice.ubegin()[0]) + checksum_diff) % 255;
|
||||
secret_slice.ubegin()[0] = new_byte;
|
||||
return create(secret_slice).move_as_ok();
|
||||
}
|
||||
|
||||
@ -159,6 +185,14 @@ Slice Secret::as_slice() const {
|
||||
return as_slice(secret_);
|
||||
}
|
||||
|
||||
int64 Secret::get_hash() const {
|
||||
return hash_;
|
||||
}
|
||||
|
||||
Secret Secret::clone() const {
|
||||
return {secret_, hash_};
|
||||
}
|
||||
|
||||
EncryptedSecret Secret::encrypt(Slice key) {
|
||||
auto aes_cbc_state = calc_aes_cbc_state(key);
|
||||
UInt256 res;
|
||||
@ -166,7 +200,7 @@ EncryptedSecret Secret::encrypt(Slice key) {
|
||||
return EncryptedSecret::create(td::as_slice(res)).move_as_ok();
|
||||
}
|
||||
|
||||
Secret::Secret(UInt256 secret) : secret_(secret) {
|
||||
Secret::Secret(UInt256 secret, int64 hash) : secret_(secret), hash_(hash) {
|
||||
}
|
||||
|
||||
//EncryptedSecret
|
||||
@ -207,7 +241,7 @@ Result<BufferSlice> Decryptor::append(BufferSlice data) {
|
||||
sha256_update(data.as_slice(), &sha256_state_);
|
||||
if (!skipped_prefix_) {
|
||||
to_skip_ = data.as_slice().ubegin()[0];
|
||||
size_t to_skip = std::min(to_skip_, data.size());
|
||||
size_t to_skip = min(to_skip_, data.size());
|
||||
skipped_prefix_ = true;
|
||||
data = data.from_slice(data.as_slice().remove_prefix(to_skip));
|
||||
}
|
||||
@ -230,7 +264,7 @@ Encryptor::Encryptor(AesCbcState aes_cbc_state, DataView &data_view)
|
||||
: aes_cbc_state_(std::move(aes_cbc_state)), data_view_(data_view) {
|
||||
}
|
||||
|
||||
int64 Encryptor::size() {
|
||||
int64 Encryptor::size() const {
|
||||
return data_view_.size();
|
||||
}
|
||||
|
||||
@ -266,7 +300,8 @@ Result<BufferSlice> decrypt_value(const Secret &secret, const ValueHash &hash, S
|
||||
TRY_RESULT(decrypted_value, decryptor.append(BufferSlice(data)));
|
||||
TRY_RESULT(got_hash, decryptor.finish());
|
||||
if (got_hash.as_slice() != hash.as_slice()) {
|
||||
return Status::Error("Hash mismatch");
|
||||
return Status::Error(PSLICE() << "Hash mismatch " << format::as_hex_dump<4>(got_hash.as_slice()) << " "
|
||||
<< format::as_hex_dump<4>(hash.as_slice()));
|
||||
}
|
||||
return std::move(decrypted_value);
|
||||
}
|
||||
|
@ -4,32 +4,21 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/utils/Random.h"
|
||||
#pragma once
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/crypto.h"
|
||||
#include "td/utils/format.h"
|
||||
#include "td/utils/int_types.h"
|
||||
#include "td/utils/Status.h"
|
||||
#include "td/utils/optional.h"
|
||||
#include "td/utils/port/FileFd.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
|
||||
namespace td {
|
||||
// secureValueSendingStatePending = SecureValueSendingState;
|
||||
// secureValueSendingStateFailed = SecureValueSendingState;
|
||||
//
|
||||
// secureValue key:string sending_state:SecureValueSendingState unencrypted_text:string data:string files:vector<File> = SecureValue;
|
||||
//
|
||||
// inputSecureValue key:string unencrypted_text:string data:string files:vector<InputFile> = InputSecureValue;
|
||||
//
|
||||
// updateSecureValue value:SecureValue = Update;
|
||||
//
|
||||
// setSecureValue password:string value:InputSecureValue = SecureValue;
|
||||
// getSecureValue password:string key:string = SecureValue;
|
||||
//
|
||||
|
||||
// Types
|
||||
// Password
|
||||
// Secret - 32 bytes with sum == 239
|
||||
// Secret - 32 bytes with sum % 255 == 239
|
||||
// EncryptedSecret - encrypted secret
|
||||
// ValueHash - 32 bytes, sha256 from value
|
||||
//
|
||||
@ -64,8 +53,9 @@ namespace secure_storage {
|
||||
// Helpers
|
||||
class ValueHash {
|
||||
public:
|
||||
ValueHash(UInt256 hash) : hash_(hash) {
|
||||
explicit ValueHash(UInt256 hash) : hash_(hash) {
|
||||
}
|
||||
static Result<ValueHash> create(Slice data);
|
||||
Slice as_slice() const {
|
||||
return td::as_slice(hash_);
|
||||
}
|
||||
@ -76,7 +66,7 @@ class ValueHash {
|
||||
|
||||
class DataView {
|
||||
public:
|
||||
virtual int64 size() = 0;
|
||||
virtual int64 size() const = 0;
|
||||
virtual Result<BufferSlice> pread(int64 offset, int64 size) = 0;
|
||||
virtual ~DataView() = default;
|
||||
};
|
||||
@ -85,7 +75,7 @@ class FileDataView : public DataView {
|
||||
public:
|
||||
FileDataView(FileFd &fd, int64 size);
|
||||
|
||||
int64 size() override;
|
||||
int64 size() const override;
|
||||
Result<BufferSlice> pread(int64 offset, int64 size) override;
|
||||
|
||||
private:
|
||||
@ -95,8 +85,8 @@ class FileDataView : public DataView {
|
||||
|
||||
class BufferSliceDataView : public DataView {
|
||||
public:
|
||||
BufferSliceDataView(BufferSlice buffer_slice);
|
||||
int64 size() override;
|
||||
explicit BufferSliceDataView(BufferSlice buffer_slice);
|
||||
int64 size() const override;
|
||||
Result<BufferSlice> pread(int64 offset, int64 size) override;
|
||||
|
||||
private:
|
||||
@ -106,7 +96,7 @@ class BufferSliceDataView : public DataView {
|
||||
class ConcatDataView : public DataView {
|
||||
public:
|
||||
ConcatDataView(DataView &left, DataView &right);
|
||||
int64 size() override;
|
||||
int64 size() const override;
|
||||
Result<BufferSlice> pread(int64 offset, int64 size) override;
|
||||
|
||||
private:
|
||||
@ -116,11 +106,12 @@ class ConcatDataView : public DataView {
|
||||
|
||||
AesCbcState calc_aes_cbc_state(Slice seed);
|
||||
Result<ValueHash> calc_value_hash(DataView &data_view);
|
||||
ValueHash calc_value_hash(Slice data);
|
||||
BufferSlice gen_random_prefix(int64 data_size);
|
||||
|
||||
class Password {
|
||||
public:
|
||||
Password(std::string password);
|
||||
explicit Password(std::string password);
|
||||
Slice as_slice() const;
|
||||
|
||||
private:
|
||||
@ -137,9 +128,13 @@ class Secret {
|
||||
Slice as_slice() const;
|
||||
EncryptedSecret encrypt(Slice key);
|
||||
|
||||
int64 get_hash() const;
|
||||
Secret clone() const;
|
||||
|
||||
private:
|
||||
Secret(UInt256 secret);
|
||||
Secret(UInt256 secret, int64 hash);
|
||||
UInt256 secret_;
|
||||
int64 hash_;
|
||||
};
|
||||
|
||||
class EncryptedSecret {
|
||||
@ -149,14 +144,14 @@ class EncryptedSecret {
|
||||
Slice as_slice() const;
|
||||
|
||||
private:
|
||||
EncryptedSecret(UInt256 encrypted_secret);
|
||||
explicit EncryptedSecret(UInt256 encrypted_secret);
|
||||
UInt256 encrypted_secret_;
|
||||
};
|
||||
|
||||
// Decryption
|
||||
class Decryptor {
|
||||
public:
|
||||
Decryptor(AesCbcState aes_cbc_state);
|
||||
explicit Decryptor(AesCbcState aes_cbc_state);
|
||||
Result<BufferSlice> append(BufferSlice data);
|
||||
Result<ValueHash> finish();
|
||||
|
||||
@ -171,7 +166,7 @@ class Decryptor {
|
||||
class Encryptor : public DataView {
|
||||
public:
|
||||
Encryptor(AesCbcState aes_cbc_state, DataView &data_view);
|
||||
int64 size() override;
|
||||
int64 size() const override;
|
||||
Result<BufferSlice> pread(int64 offset, int64 size) override;
|
||||
|
||||
private:
|
||||
|
448
td/telegram/SecureValue.cpp
Normal file
448
td/telegram/SecureValue.cpp
Normal file
@ -0,0 +1,448 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/telegram/SecureValue.h"
|
||||
|
||||
#include "td/telegram/files/FileManager.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
|
||||
#include "td/utils/misc.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
SecureValueType get_secure_value_type(tl_object_ptr<telegram_api::SecureValueType> &&secure_value_type) {
|
||||
CHECK(secure_value_type != nullptr);
|
||||
switch (secure_value_type->get_id()) {
|
||||
case telegram_api::secureValueTypePersonalDetails::ID:
|
||||
return SecureValueType::PersonalDetails;
|
||||
case telegram_api::secureValueTypePassport::ID:
|
||||
return SecureValueType::Passport;
|
||||
case telegram_api::secureValueTypeDriverLicense::ID:
|
||||
return SecureValueType::DriverLicense;
|
||||
case telegram_api::secureValueTypeIdentityCard::ID:
|
||||
return SecureValueType::IdentityCard;
|
||||
case telegram_api::secureValueTypeAddress::ID:
|
||||
return SecureValueType::Address;
|
||||
case telegram_api::secureValueTypeUtilityBill::ID:
|
||||
return SecureValueType::UtilityBill;
|
||||
case telegram_api::secureValueTypeBankStatement::ID:
|
||||
return SecureValueType::BankStatement;
|
||||
case telegram_api::secureValueTypeRentalAgreement::ID:
|
||||
return SecureValueType::RentalAgreement;
|
||||
case telegram_api::secureValueTypePhone::ID:
|
||||
return SecureValueType::PhoneNumber;
|
||||
case telegram_api::secureValueTypeEmail::ID:
|
||||
return SecureValueType::EmailAddress;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return SecureValueType::None;
|
||||
}
|
||||
}
|
||||
|
||||
SecureValueType get_secure_value_type_td_api(tl_object_ptr<td_api::PassportDataType> &&passport_data_type) {
|
||||
CHECK(passport_data_type != nullptr);
|
||||
switch (passport_data_type->get_id()) {
|
||||
case td_api::passportDataTypePersonalDetails::ID:
|
||||
return SecureValueType::PersonalDetails;
|
||||
case td_api::passportDataTypePassport::ID:
|
||||
return SecureValueType::Passport;
|
||||
case td_api::passportDataTypeDriverLicense::ID:
|
||||
return SecureValueType::DriverLicense;
|
||||
case td_api::passportDataTypeIdentityCard::ID:
|
||||
return SecureValueType::IdentityCard;
|
||||
case td_api::passportDataTypeAddress::ID:
|
||||
return SecureValueType::Address;
|
||||
case td_api::passportDataTypeUtilityBill::ID:
|
||||
return SecureValueType::UtilityBill;
|
||||
case td_api::passportDataTypeBankStatement::ID:
|
||||
return SecureValueType::BankStatement;
|
||||
case td_api::passportDataTypeRentalAgreement::ID:
|
||||
return SecureValueType::RentalAgreement;
|
||||
case td_api::passportDataTypePhoneNumber::ID:
|
||||
return SecureValueType::PhoneNumber;
|
||||
case td_api::passportDataTypeEmailAddress::ID:
|
||||
return SecureValueType::EmailAddress;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return SecureValueType::None;
|
||||
}
|
||||
}
|
||||
|
||||
vector<SecureValueType> get_secure_value_types(
|
||||
vector<tl_object_ptr<telegram_api::SecureValueType>> &&secure_value_types) {
|
||||
return transform(std::move(secure_value_types), get_secure_value_type);
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::PassportDataType> get_passport_data_type_object(SecureValueType type) {
|
||||
switch (type) {
|
||||
case SecureValueType::PersonalDetails:
|
||||
return td_api::make_object<td_api::passportDataTypePersonalDetails>();
|
||||
case SecureValueType::Passport:
|
||||
return td_api::make_object<td_api::passportDataTypePassport>();
|
||||
case SecureValueType::DriverLicense:
|
||||
return td_api::make_object<td_api::passportDataTypeDriverLicense>();
|
||||
case SecureValueType::IdentityCard:
|
||||
return td_api::make_object<td_api::passportDataTypeIdentityCard>();
|
||||
case SecureValueType::Address:
|
||||
return td_api::make_object<td_api::passportDataTypeAddress>();
|
||||
case SecureValueType::UtilityBill:
|
||||
return td_api::make_object<td_api::passportDataTypeUtilityBill>();
|
||||
case SecureValueType::BankStatement:
|
||||
return td_api::make_object<td_api::passportDataTypeBankStatement>();
|
||||
case SecureValueType::RentalAgreement:
|
||||
return td_api::make_object<td_api::passportDataTypeRentalAgreement>();
|
||||
case SecureValueType::PhoneNumber:
|
||||
return td_api::make_object<td_api::passportDataTypePhoneNumber>();
|
||||
case SecureValueType::EmailAddress:
|
||||
return td_api::make_object<td_api::passportDataTypeEmailAddress>();
|
||||
case SecureValueType::None:
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
td_api::object_ptr<telegram_api::SecureValueType> get_secure_value_type_telegram_object(SecureValueType type) {
|
||||
switch (type) {
|
||||
case SecureValueType::PersonalDetails:
|
||||
return telegram_api::make_object<telegram_api::secureValueTypePersonalDetails>();
|
||||
case SecureValueType::Passport:
|
||||
return telegram_api::make_object<telegram_api::secureValueTypePassport>();
|
||||
case SecureValueType::DriverLicense:
|
||||
return telegram_api::make_object<telegram_api::secureValueTypeDriverLicense>();
|
||||
case SecureValueType::IdentityCard:
|
||||
return telegram_api::make_object<telegram_api::secureValueTypeIdentityCard>();
|
||||
case SecureValueType::Address:
|
||||
return telegram_api::make_object<telegram_api::secureValueTypeAddress>();
|
||||
case SecureValueType::UtilityBill:
|
||||
return telegram_api::make_object<telegram_api::secureValueTypeUtilityBill>();
|
||||
case SecureValueType::BankStatement:
|
||||
return telegram_api::make_object<telegram_api::secureValueTypeBankStatement>();
|
||||
case SecureValueType::RentalAgreement:
|
||||
return telegram_api::make_object<telegram_api::secureValueTypeRentalAgreement>();
|
||||
case SecureValueType::PhoneNumber:
|
||||
return telegram_api::make_object<telegram_api::secureValueTypePhone>();
|
||||
case SecureValueType::EmailAddress:
|
||||
return telegram_api::make_object<telegram_api::secureValueTypeEmail>();
|
||||
case SecureValueType::None:
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
vector<td_api::object_ptr<td_api::PassportDataType>> get_passport_data_types_object(
|
||||
const vector<SecureValueType> &types) {
|
||||
return transform(types, get_passport_data_type_object);
|
||||
}
|
||||
|
||||
bool operator==(const SecureFile &lhs, const SecureFile &rhs) {
|
||||
return lhs.file_id == rhs.file_id && lhs.file_hash == rhs.file_hash && lhs.encrypted_secret == rhs.encrypted_secret;
|
||||
}
|
||||
|
||||
bool operator!=(const SecureFile &lhs, const SecureFile &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
SecureFile get_secure_file(FileManager *file_manager, tl_object_ptr<telegram_api::SecureFile> &&secure_file_ptr) {
|
||||
CHECK(secure_file_ptr != nullptr);
|
||||
SecureFile result;
|
||||
switch (secure_file_ptr->get_id()) {
|
||||
case telegram_api::secureFileEmpty::ID:
|
||||
break;
|
||||
case telegram_api::secureFile::ID: {
|
||||
auto secure_file = telegram_api::move_object_as<telegram_api::secureFile>(secure_file_ptr);
|
||||
auto dc_id = secure_file->dc_id_;
|
||||
if (!DcId::is_valid(dc_id)) {
|
||||
LOG(ERROR) << "Wrong dc_id = " << dc_id;
|
||||
break;
|
||||
}
|
||||
result.file_id =
|
||||
file_manager->register_remote(FullRemoteFileLocation(FileType::SecureRaw, secure_file->id_,
|
||||
secure_file->access_hash_, DcId::internal(dc_id)),
|
||||
FileLocationSource::FromServer, {}, 0, 0, "");
|
||||
result.encrypted_secret = secure_file->secret_.as_slice().str();
|
||||
result.file_hash = secure_file->file_hash_.as_slice().str();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<SecureFile> get_secure_files(FileManager *file_manager,
|
||||
vector<tl_object_ptr<telegram_api::SecureFile>> &&secure_files) {
|
||||
vector<SecureFile> results;
|
||||
results.reserve(secure_files.size());
|
||||
for (auto &secure_file : secure_files) {
|
||||
auto result = get_secure_file(file_manager, std::move(secure_file));
|
||||
if (result.file_id.is_valid()) {
|
||||
results.push_back(std::move(result));
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
telegram_api::object_ptr<telegram_api::InputSecureFile> get_input_secure_file_object(FileManager *file_manager,
|
||||
const SecureFile &file) {
|
||||
//TODO:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::file> get_encrypted_file_object(FileManager *file_manager, const SecureFile &file) {
|
||||
return file_manager->get_file_object(file.file_id);
|
||||
}
|
||||
|
||||
vector<td_api::object_ptr<td_api::file>> get_encrypted_files_object(FileManager *file_manager,
|
||||
const vector<SecureFile> &files) {
|
||||
return transform(files,
|
||||
[file_manager](const SecureFile &file) { return get_encrypted_file_object(file_manager, file); });
|
||||
}
|
||||
|
||||
vector<telegram_api::object_ptr<telegram_api::InputSecureFile>> get_input_secure_files_object(
|
||||
FileManager *file_manager, const vector<SecureFile> &file) {
|
||||
//TODO:
|
||||
return {};
|
||||
}
|
||||
|
||||
bool operator==(const SecureData &lhs, const SecureData &rhs) {
|
||||
return lhs.data == rhs.data && lhs.hash == rhs.hash && lhs.encrypted_secret == rhs.encrypted_secret;
|
||||
}
|
||||
|
||||
bool operator!=(const SecureData &lhs, const SecureData &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
SecureData get_secure_data(tl_object_ptr<telegram_api::secureData> &&secure_data) {
|
||||
CHECK(secure_data != nullptr);
|
||||
SecureData result;
|
||||
result.data = secure_data->data_.as_slice().str();
|
||||
result.hash = secure_data->data_hash_.as_slice().str();
|
||||
result.encrypted_secret = secure_data->secret_.as_slice().str();
|
||||
return result;
|
||||
}
|
||||
|
||||
telegram_api::object_ptr<telegram_api::secureData> get_secure_data_object(const SecureData &data) {
|
||||
return telegram_api::make_object<telegram_api::secureData>(BufferSlice(data.data), BufferSlice(data.hash),
|
||||
BufferSlice(data.encrypted_secret));
|
||||
}
|
||||
|
||||
bool operator==(const EncryptedSecureValue &lhs, const EncryptedSecureValue &rhs) {
|
||||
return lhs.type == rhs.type && lhs.data == rhs.data && lhs.files == rhs.files && lhs.selfie == rhs.selfie;
|
||||
}
|
||||
|
||||
bool operator!=(const EncryptedSecureValue &lhs, const EncryptedSecureValue &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
EncryptedSecureValue get_encrypted_secure_value(FileManager *file_manager,
|
||||
tl_object_ptr<telegram_api::secureValue> &&secure_value) {
|
||||
EncryptedSecureValue result;
|
||||
CHECK(secure_value != nullptr);
|
||||
result.type = get_secure_value_type(std::move(secure_value->type_));
|
||||
if (secure_value->plain_data_ != nullptr) {
|
||||
switch (secure_value->plain_data_->get_id()) {
|
||||
case telegram_api::securePlainPhone::ID:
|
||||
result.data.data =
|
||||
std::move(static_cast<telegram_api::securePlainPhone *>(secure_value->plain_data_.get())->phone_);
|
||||
break;
|
||||
case telegram_api::securePlainEmail::ID:
|
||||
result.data.data =
|
||||
std::move(static_cast<telegram_api::securePlainEmail *>(secure_value->plain_data_.get())->email_);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if (secure_value->data_ != nullptr) {
|
||||
result.data = get_secure_data(std::move(secure_value->data_));
|
||||
}
|
||||
result.files = get_secure_files(file_manager, std::move(secure_value->files_));
|
||||
if (secure_value->selfie_ != nullptr) {
|
||||
result.selfie = get_secure_file(file_manager, std::move(secure_value->selfie_));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<EncryptedSecureValue> get_encrypted_secure_values(
|
||||
FileManager *file_manager, vector<tl_object_ptr<telegram_api::secureValue>> &&secure_values) {
|
||||
return transform(std::move(secure_values), [file_manager](tl_object_ptr<telegram_api::secureValue> &&secure_value) {
|
||||
return get_encrypted_secure_value(file_manager, std::move(secure_value));
|
||||
});
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::encryptedPassportData> get_encrypted_passport_data_object(
|
||||
FileManager *file_manager, const EncryptedSecureValue &value) {
|
||||
bool is_plain = value.data.hash.empty();
|
||||
return td_api::make_object<td_api::encryptedPassportData>(
|
||||
get_passport_data_type_object(value.type), is_plain ? string() : value.data.data,
|
||||
get_encrypted_files_object(file_manager, value.files), is_plain ? value.data.data : string());
|
||||
}
|
||||
|
||||
telegram_api::object_ptr<telegram_api::inputSecureValue> get_input_secure_value_object(
|
||||
FileManager *file_manager, const EncryptedSecureValue &value) {
|
||||
bool is_plain = value.type == SecureValueType::PhoneNumber || value.type == SecureValueType::EmailAddress;
|
||||
bool has_selfie = value.selfie.file_id.is_valid();
|
||||
int32 flags = 0;
|
||||
tl_object_ptr<telegram_api::SecurePlainData> plain_data;
|
||||
if (is_plain) {
|
||||
if (value.type == SecureValueType::PhoneNumber) {
|
||||
plain_data = make_tl_object<telegram_api::securePlainPhone>(value.data.data);
|
||||
} else {
|
||||
plain_data = make_tl_object<telegram_api::securePlainEmail>(value.data.data);
|
||||
}
|
||||
flags |= telegram_api::inputSecureValue::PLAIN_DATA_MASK;
|
||||
} else {
|
||||
flags |= telegram_api::inputSecureValue::DATA_MASK;
|
||||
}
|
||||
if (!value.files.empty()) {
|
||||
flags |= telegram_api::inputSecureValue::FILES_MASK;
|
||||
}
|
||||
if (has_selfie) {
|
||||
flags |= telegram_api::inputSecureValue::SELFIE_MASK;
|
||||
}
|
||||
return telegram_api::make_object<telegram_api::inputSecureValue>(
|
||||
0, get_secure_value_type_telegram_object(value.type), is_plain ? nullptr : get_secure_data_object(value.data),
|
||||
get_input_secure_files_object(file_manager, value.files), std::move(plain_data),
|
||||
has_selfie ? get_input_secure_file_object(file_manager, value.selfie) : nullptr);
|
||||
}
|
||||
|
||||
vector<td_api::object_ptr<td_api::encryptedPassportData>> get_encrypted_passport_data_object(
|
||||
FileManager *file_manager, const vector<EncryptedSecureValue> &values) {
|
||||
return transform(values, [file_manager](const EncryptedSecureValue &value) {
|
||||
return get_encrypted_passport_data_object(file_manager, value);
|
||||
});
|
||||
}
|
||||
|
||||
bool operator==(const SecureCredentials &lhs, const SecureCredentials &rhs) {
|
||||
return lhs.data == rhs.data && lhs.hash == rhs.hash && lhs.encrypted_secret == rhs.encrypted_secret;
|
||||
}
|
||||
|
||||
bool operator!=(const SecureCredentials &lhs, const SecureCredentials &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
SecureCredentials get_secure_credentials(tl_object_ptr<telegram_api::secureCredentialsEncrypted> &&credentials) {
|
||||
CHECK(credentials != nullptr);
|
||||
SecureCredentials result;
|
||||
result.data = credentials->data_.as_slice().str();
|
||||
result.hash = credentials->hash_.as_slice().str();
|
||||
result.encrypted_secret = credentials->secret_.as_slice().str();
|
||||
return result;
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::encryptedCredentials> get_encrypted_credentials_object(
|
||||
const SecureCredentials &credentials) {
|
||||
return td_api::make_object<td_api::encryptedCredentials>(credentials.data, credentials.hash,
|
||||
credentials.encrypted_secret);
|
||||
}
|
||||
|
||||
Result<SecureValue> get_secure_value(td_api::object_ptr<td_api::inputPassportData> &&input_passport_data) {
|
||||
if (input_passport_data == nullptr) {
|
||||
return Status::Error(400, "InputPassportData must not be empty");
|
||||
}
|
||||
|
||||
SecureValue res;
|
||||
res.type = get_secure_value_type_td_api(std::move(input_passport_data->type_));
|
||||
res.data = std::move(input_passport_data->data_);
|
||||
// res.files = TODO
|
||||
return res;
|
||||
}
|
||||
|
||||
Result<FileId> decrypt_secure_file(FileManager *file_manager, const secure_storage::Secret &secret,
|
||||
const SecureFile &secure_file) {
|
||||
return Status::Error("TODO");
|
||||
}
|
||||
|
||||
Result<vector<FileId>> decrypt_secure_files(FileManager *file_manager, const secure_storage::Secret &secret,
|
||||
const vector<SecureFile> &secure_files) {
|
||||
vector<FileId> res;
|
||||
res.reserve(secure_files.size());
|
||||
for (auto &file : secure_files) {
|
||||
TRY_RESULT(decrypted_file, decrypt_secure_file(file_manager, secret, file));
|
||||
res.push_back(decrypted_file);
|
||||
}
|
||||
|
||||
return std::move(res);
|
||||
}
|
||||
Result<string> decrypt_secure_data(const secure_storage::Secret &master_secret, const SecureData &secure_data) {
|
||||
TRY_RESULT(hash, secure_storage::ValueHash::create(secure_data.hash));
|
||||
TRY_RESULT(encrypted_secret, secure_storage::EncryptedSecret::create(secure_data.encrypted_secret));
|
||||
TRY_RESULT(secret, encrypted_secret.decrypt(PSLICE() << master_secret.as_slice() << hash.as_slice()));
|
||||
TRY_RESULT(value, secure_storage::decrypt_value(secret, hash, secure_data.data));
|
||||
return value.as_slice().str();
|
||||
}
|
||||
|
||||
Result<SecureValue> decrypt_encrypted_secure_value(FileManager *file_manager, const secure_storage::Secret &secret,
|
||||
const EncryptedSecureValue &encrypted_secure_value) {
|
||||
SecureValue res;
|
||||
res.type = encrypted_secure_value.type;
|
||||
switch (encrypted_secure_value.type) {
|
||||
case SecureValueType::EmailAddress:
|
||||
case SecureValueType::PhoneNumber:
|
||||
res.data = encrypted_secure_value.data.data;
|
||||
break;
|
||||
default: {
|
||||
TRY_RESULT(data, decrypt_secure_data(secret, encrypted_secure_value.data));
|
||||
res.data = std::move(data);
|
||||
// TODO
|
||||
//TRY_RESULT(files, decrypt_secure_files(file_manager, secret, encrypted_secure_value.files));
|
||||
//res.files = std::move(files);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return std::move(res);
|
||||
}
|
||||
|
||||
SecureFile encrypt_secure_file(FileManager *file_manager, const secure_storage::Secret &master_secret, FileId file,
|
||||
string &to_hash) {
|
||||
//TODO:
|
||||
return SecureFile{};
|
||||
}
|
||||
vector<SecureFile> encrypt_secure_files(FileManager *file_manager, const secure_storage::Secret &master_secret,
|
||||
vector<FileId> files, string &to_hash) {
|
||||
return transform(files,
|
||||
[&](auto file_id) { return encrypt_secure_file(file_manager, master_secret, file_id, to_hash); });
|
||||
}
|
||||
SecureData encrypt_secure_data(const secure_storage::Secret &master_secret, Slice data, string &to_hash) {
|
||||
namespace ss = secure_storage;
|
||||
auto secret = ss::Secret::create_new();
|
||||
auto encrypted = ss::encrypt_value(secret, data).move_as_ok();
|
||||
SecureData res;
|
||||
res.encrypted_secret =
|
||||
secret.encrypt(PSLICE() << master_secret.as_slice() << encrypted.hash.as_slice()).as_slice().str();
|
||||
res.data = encrypted.data.as_slice().str();
|
||||
res.hash = encrypted.hash.as_slice().str();
|
||||
to_hash.append(res.hash);
|
||||
to_hash.append(secret.as_slice().str());
|
||||
return res;
|
||||
}
|
||||
EncryptedSecureValue encrypt_secure_value(FileManager *file_manager, const secure_storage::Secret &master_secret,
|
||||
const SecureValue &secure_value) {
|
||||
namespace ss = secure_storage;
|
||||
EncryptedSecureValue res;
|
||||
res.type = secure_value.type;
|
||||
switch (res.type) {
|
||||
case SecureValueType::EmailAddress:
|
||||
case SecureValueType::PhoneNumber:
|
||||
res.data = SecureData{secure_value.data, "", ""};
|
||||
res.hash = ss::calc_value_hash(secure_value.data).as_slice().str();
|
||||
break;
|
||||
default: {
|
||||
string to_hash;
|
||||
res.data = encrypt_secure_data(master_secret, secure_value.data, to_hash);
|
||||
// TODO
|
||||
//res.files = encrypt_secure_files(file_manager, master_secret, secure_value.files, to_hash);
|
||||
res.hash = ss::calc_value_hash(to_hash).as_slice().str();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace td
|
149
td/telegram/SecureValue.h
Normal file
149
td/telegram/SecureValue.h
Normal file
@ -0,0 +1,149 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
|
||||
#include "td/telegram/files/FileId.h"
|
||||
#include "td/telegram/SecureStorage.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
class FileManager;
|
||||
|
||||
enum class SecureValueType {
|
||||
None,
|
||||
PersonalDetails,
|
||||
Passport,
|
||||
DriverLicense,
|
||||
IdentityCard,
|
||||
Address,
|
||||
UtilityBill,
|
||||
BankStatement,
|
||||
RentalAgreement,
|
||||
PhoneNumber,
|
||||
EmailAddress
|
||||
};
|
||||
|
||||
SecureValueType get_secure_value_type(tl_object_ptr<telegram_api::SecureValueType> &&secure_value_type);
|
||||
SecureValueType get_secure_value_type_td_api(tl_object_ptr<td_api::PassportDataType> &&passport_data_type);
|
||||
|
||||
vector<SecureValueType> get_secure_value_types(
|
||||
vector<tl_object_ptr<telegram_api::SecureValueType>> &&secure_value_types);
|
||||
|
||||
td_api::object_ptr<td_api::PassportDataType> get_passport_data_type_object(SecureValueType type);
|
||||
td_api::object_ptr<telegram_api::SecureValueType> get_secure_value_type_telegram_object(SecureValueType type);
|
||||
|
||||
vector<td_api::object_ptr<td_api::PassportDataType>> get_passport_data_types_object(
|
||||
const vector<SecureValueType> &types);
|
||||
|
||||
struct SecureFile {
|
||||
FileId file_id;
|
||||
string file_hash;
|
||||
string encrypted_secret;
|
||||
};
|
||||
|
||||
bool operator==(const SecureFile &lhs, const SecureFile &rhs);
|
||||
bool operator!=(const SecureFile &lhs, const SecureFile &rhs);
|
||||
|
||||
SecureFile get_secure_file(FileManager *file_manager, tl_object_ptr<telegram_api::SecureFile> &&secure_file_ptr);
|
||||
|
||||
vector<SecureFile> get_secure_files(FileManager *file_manager,
|
||||
vector<tl_object_ptr<telegram_api::SecureFile>> &&secure_files);
|
||||
|
||||
telegram_api::object_ptr<telegram_api::InputSecureFile> get_input_secure_file_object(FileManager *file_manager,
|
||||
const SecureFile &file);
|
||||
|
||||
td_api::object_ptr<td_api::file> get_encrypted_file_object(FileManager *file_manager, const SecureFile &file);
|
||||
|
||||
vector<td_api::object_ptr<td_api::file>> get_encrypted_files_object(FileManager *file_manager,
|
||||
const vector<SecureFile> &files);
|
||||
|
||||
vector<telegram_api::object_ptr<telegram_api::InputSecureFile>> get_input_secure_files_object(
|
||||
FileManager *file_manager, const vector<SecureFile> &file);
|
||||
|
||||
struct SecureData {
|
||||
string data;
|
||||
string hash;
|
||||
string encrypted_secret;
|
||||
};
|
||||
|
||||
bool operator==(const SecureData &lhs, const SecureData &rhs);
|
||||
bool operator!=(const SecureData &lhs, const SecureData &rhs);
|
||||
|
||||
SecureData get_secure_data(tl_object_ptr<telegram_api::secureData> &&secure_data);
|
||||
|
||||
telegram_api::object_ptr<telegram_api::secureData> get_secure_data_object(const SecureData &data);
|
||||
|
||||
struct EncryptedSecureValue {
|
||||
SecureValueType type = SecureValueType::None;
|
||||
SecureData data;
|
||||
vector<SecureFile> files;
|
||||
SecureFile selfie;
|
||||
string hash; // memory only
|
||||
};
|
||||
|
||||
bool operator==(const EncryptedSecureValue &lhs, const EncryptedSecureValue &rhs);
|
||||
bool operator!=(const EncryptedSecureValue &lhs, const EncryptedSecureValue &rhs);
|
||||
|
||||
EncryptedSecureValue get_encrypted_secure_value(FileManager *file_manager,
|
||||
tl_object_ptr<telegram_api::secureValue> &&secure_value);
|
||||
|
||||
vector<EncryptedSecureValue> get_encrypted_secure_values(
|
||||
FileManager *file_manager, vector<tl_object_ptr<telegram_api::secureValue>> &&secure_values);
|
||||
|
||||
td_api::object_ptr<td_api::encryptedPassportData> get_encrypted_passport_data_object(FileManager *file_manager,
|
||||
const EncryptedSecureValue &value);
|
||||
telegram_api::object_ptr<telegram_api::inputSecureValue> get_input_secure_value_object(
|
||||
FileManager *file_manager, const EncryptedSecureValue &value);
|
||||
|
||||
vector<td_api::object_ptr<td_api::encryptedPassportData>> get_encrypted_passport_data_object(
|
||||
FileManager *file_manager, const vector<EncryptedSecureValue> &values);
|
||||
|
||||
struct SecureCredentials {
|
||||
string data;
|
||||
string hash;
|
||||
string encrypted_secret;
|
||||
};
|
||||
|
||||
bool operator==(const SecureCredentials &lhs, const SecureCredentials &rhs);
|
||||
bool operator!=(const SecureCredentials &lhs, const SecureCredentials &rhs);
|
||||
|
||||
SecureCredentials get_secure_credentials(tl_object_ptr<telegram_api::secureCredentialsEncrypted> &&credentials);
|
||||
|
||||
td_api::object_ptr<td_api::encryptedCredentials> get_encrypted_credentials_object(const SecureCredentials &credentials);
|
||||
|
||||
class SecureValue {
|
||||
public:
|
||||
SecureValueType type;
|
||||
string data;
|
||||
vector<FileId> files;
|
||||
};
|
||||
|
||||
Result<SecureValue> get_secure_value(td_api::object_ptr<td_api::inputPassportData> &&input_passport_data);
|
||||
|
||||
Result<FileId> decrypt_secure_file(FileManager *file_manager, const secure_storage::Secret &secret,
|
||||
const SecureFile &secure_file);
|
||||
Result<vector<FileId>> decrypt_secure_files(FileManager *file_manager, const secure_storage::Secret &secret,
|
||||
const vector<SecureFile> &secure_file);
|
||||
Result<string> decrypt_secure_data(const secure_storage::Secret &secret, const SecureData &secure_data);
|
||||
Result<SecureValue> decrypt_encrypted_secure_value(FileManager *file_manager, const secure_storage::Secret &secret,
|
||||
const EncryptedSecureValue &encrypted_secure_value);
|
||||
|
||||
SecureFile encrypt_secure_file(FileManager *file_manager, const secure_storage::Secret &master_secret, FileId file,
|
||||
string &to_hash);
|
||||
vector<SecureFile> encrypt_secure_files(FileManager *file_manager, const secure_storage::Secret &master_secret,
|
||||
vector<FileId> files, string &to_hash);
|
||||
SecureData encrypt_secure_data(const secure_storage::Secret &master_secret, Slice data, string &to_hash);
|
||||
EncryptedSecureValue encrypt_secure_value(FileManager *file_manager, const secure_storage::Secret &master_secret,
|
||||
const SecureValue &secure_value);
|
||||
|
||||
} // namespace td
|
107
td/telegram/SecureValue.hpp
Normal file
107
td/telegram/SecureValue.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/telegram/SecureValue.h"
|
||||
|
||||
#include "td/telegram/files/FileId.hpp"
|
||||
|
||||
#include "td/utils/tl_helpers.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
template <class StorerT>
|
||||
void store(SecureFile file, StorerT &storer) {
|
||||
store(file.file_id, storer);
|
||||
store(file.file_hash, storer);
|
||||
store(file.encrypted_secret, storer);
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void parse(SecureFile &file, ParserT &parser) {
|
||||
parse(file.file_id, parser);
|
||||
parse(file.file_hash, parser);
|
||||
parse(file.encrypted_secret, parser);
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void store(const SecureData &data, StorerT &storer) {
|
||||
store(data.data, storer);
|
||||
store(data.hash, storer);
|
||||
store(data.encrypted_secret, storer);
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void parse(SecureData &data, ParserT &parser) {
|
||||
parse(data.data, parser);
|
||||
parse(data.hash, parser);
|
||||
parse(data.encrypted_secret, parser);
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void store(const SecureCredentials &credentials, StorerT &storer) {
|
||||
store(credentials.data, storer);
|
||||
store(credentials.hash, storer);
|
||||
store(credentials.encrypted_secret, storer);
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void parse(SecureCredentials &credentials, ParserT &parser) {
|
||||
parse(credentials.data, parser);
|
||||
parse(credentials.hash, parser);
|
||||
parse(credentials.encrypted_secret, parser);
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void store(const EncryptedSecureValue &value, StorerT &storer) {
|
||||
bool has_data_hash = !value.data.hash.empty();
|
||||
bool has_files = !value.files.empty();
|
||||
bool has_selfie = value.selfie.file_id.is_valid();
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(has_data_hash);
|
||||
STORE_FLAG(has_files);
|
||||
STORE_FLAG(has_selfie);
|
||||
END_STORE_FLAGS();
|
||||
store(value.type, storer);
|
||||
if (has_data_hash) {
|
||||
store(value.data, storer);
|
||||
} else {
|
||||
store(value.data.data, storer);
|
||||
}
|
||||
if (has_files) {
|
||||
store(value.files, storer);
|
||||
}
|
||||
if (has_selfie) {
|
||||
store(value.selfie, storer);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void parse(EncryptedSecureValue &value, ParserT &parser) {
|
||||
bool has_data_hash;
|
||||
bool has_files;
|
||||
bool has_selfie;
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(has_data_hash);
|
||||
PARSE_FLAG(has_files);
|
||||
PARSE_FLAG(has_selfie);
|
||||
END_PARSE_FLAGS();
|
||||
parse(value.type, parser);
|
||||
if (has_data_hash) {
|
||||
parse(value.data, parser);
|
||||
} else {
|
||||
parse(value.data.data, parser);
|
||||
}
|
||||
if (has_files) {
|
||||
parse(value.files, parser);
|
||||
}
|
||||
if (has_selfie) {
|
||||
parse(value.selfie, parser);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace td
|
@ -79,9 +79,7 @@ class SearchStickersQuery : public Td::ResultHandler {
|
||||
public:
|
||||
void send(string emoji) {
|
||||
emoji_ = std::move(emoji);
|
||||
int32 flags = 0;
|
||||
send_query(G()->net_query_creator().create(
|
||||
create_storer(telegram_api::messages_getStickers(flags, false /*ignored*/, emoji_, ""))));
|
||||
send_query(G()->net_query_creator().create(create_storer(telegram_api::messages_getStickers(emoji_, 0))));
|
||||
}
|
||||
|
||||
void on_result(uint64 id, BufferSlice packet) override {
|
||||
@ -781,6 +779,10 @@ class StickersManager::UploadStickerFileCallback : public FileManager::UploadCal
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void on_upload_secure_ok(FileId file_id, tl_object_ptr<telegram_api::InputSecureFile> input_file) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void on_upload_error(FileId file_id, Status error) override {
|
||||
send_closure_later(G()->stickers_manager(), &StickersManager::on_upload_sticker_file_error, file_id,
|
||||
std::move(error));
|
||||
@ -1283,11 +1285,11 @@ bool StickersManager::has_input_media(FileId sticker_file_id, bool is_secret) co
|
||||
CHECK(sticker != nullptr);
|
||||
auto file_view = td_->file_manager_->get_file_view(sticker_file_id);
|
||||
if (is_secret) {
|
||||
if (file_view.is_encrypted()) {
|
||||
if (file_view.is_encrypted_secret()) {
|
||||
if (file_view.has_remote_location() && !sticker->message_thumbnail.file_id.is_valid()) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
} else if (!file_view.is_encrypted()) {
|
||||
if (sticker->set_id != 0) {
|
||||
// stickers within a set can be sent by id and access_hash
|
||||
return true;
|
||||
@ -1311,7 +1313,7 @@ SecretInputMedia StickersManager::get_secret_input_media(FileId sticker_file_id,
|
||||
const Sticker *sticker = get_sticker(sticker_file_id);
|
||||
CHECK(sticker != nullptr);
|
||||
auto file_view = td_->file_manager_->get_file_view(sticker_file_id);
|
||||
if (file_view.is_encrypted()) {
|
||||
if (file_view.is_encrypted_secret()) {
|
||||
if (file_view.has_remote_location()) {
|
||||
input_file = file_view.remote_location().as_input_encrypted_file();
|
||||
}
|
||||
@ -1321,11 +1323,13 @@ SecretInputMedia StickersManager::get_secret_input_media(FileId sticker_file_id,
|
||||
if (sticker->message_thumbnail.file_id.is_valid() && thumbnail.empty()) {
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
} else if (!file_view.is_encrypted()) {
|
||||
if (sticker->set_id == 0) {
|
||||
// stickers without set can't be sent by id and access_hash
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
|
||||
vector<tl_object_ptr<secret_api::DocumentAttribute>> attributes;
|
||||
@ -1347,7 +1351,7 @@ SecretInputMedia StickersManager::get_secret_input_media(FileId sticker_file_id,
|
||||
make_tl_object<secret_api::documentAttributeImageSize>(sticker->dimensions.width, sticker->dimensions.height));
|
||||
}
|
||||
|
||||
if (file_view.is_encrypted()) {
|
||||
if (file_view.is_encrypted_secret()) {
|
||||
auto &encryption_key = file_view.encryption_key();
|
||||
return SecretInputMedia{std::move(input_file),
|
||||
make_tl_object<secret_api::decryptedMessageMediaDocument>(
|
||||
@ -1356,6 +1360,7 @@ SecretInputMedia StickersManager::get_secret_input_media(FileId sticker_file_id,
|
||||
narrow_cast<int32>(file_view.size()), BufferSlice(encryption_key.key_slice()),
|
||||
BufferSlice(encryption_key.iv_slice()), std::move(attributes), "")};
|
||||
} else {
|
||||
CHECK(!file_view.is_encrypted());
|
||||
auto &remote_location = file_view.remote_location();
|
||||
CHECK(!remote_location.is_web()); // web stickers shouldn't have set_id
|
||||
return SecretInputMedia{nullptr,
|
||||
@ -2829,7 +2834,7 @@ vector<int64> StickersManager::get_attached_sticker_sets(FileId file_id, Promise
|
||||
promise.set_error(Status::Error(5, "File not found"));
|
||||
return {};
|
||||
}
|
||||
if (!file_view.has_remote_location() || file_view.remote_location().is_encrypted() ||
|
||||
if (!file_view.has_remote_location() || !file_view.remote_location().is_document() ||
|
||||
file_view.remote_location().is_web()) {
|
||||
promise.set_value(Unit());
|
||||
return {};
|
||||
@ -2979,8 +2984,7 @@ Result<std::tuple<FileId, bool, bool>> StickersManager::prepare_input_file(
|
||||
bool is_url = false;
|
||||
bool is_local = false;
|
||||
if (file_view.has_remote_location()) {
|
||||
CHECK(!file_view.remote_location().is_encrypted());
|
||||
CHECK(!file_view.remote_location().is_photo());
|
||||
CHECK(file_view.remote_location().is_document());
|
||||
} else {
|
||||
if (file_view.has_url()) {
|
||||
is_url = true;
|
||||
@ -3347,7 +3351,7 @@ void StickersManager::set_sticker_position_in_set(const tl_object_ptr<td_api::In
|
||||
|
||||
auto file_id = r_file_id.move_as_ok();
|
||||
auto file_view = td_->file_manager_->get_file_view(file_id);
|
||||
if (!file_view.has_remote_location() || file_view.remote_location().is_encrypted() ||
|
||||
if (!file_view.has_remote_location() || !file_view.remote_location().is_document() ||
|
||||
file_view.remote_location().is_web()) {
|
||||
return promise.set_error(Status::Error(7, "Wrong sticker file specified"));
|
||||
}
|
||||
@ -3365,7 +3369,7 @@ void StickersManager::remove_sticker_from_set(const tl_object_ptr<td_api::InputF
|
||||
|
||||
auto file_id = r_file_id.move_as_ok();
|
||||
auto file_view = td_->file_manager_->get_file_view(file_id);
|
||||
if (!file_view.has_remote_location() || file_view.remote_location().is_encrypted() ||
|
||||
if (!file_view.has_remote_location() || !file_view.remote_location().is_document() ||
|
||||
file_view.remote_location().is_web()) {
|
||||
return promise.set_error(Status::Error(7, "Wrong sticker file specified"));
|
||||
}
|
||||
@ -3390,14 +3394,14 @@ vector<FileId> StickersManager::get_attached_sticker_file_ids(const vector<int32
|
||||
LOG(WARNING) << "Sticker " << file_id << " has no remote location";
|
||||
continue;
|
||||
}
|
||||
if (file_view.remote_location().is_encrypted()) {
|
||||
LOG(WARNING) << "Sticker " << file_id << " is encrypted";
|
||||
continue;
|
||||
}
|
||||
if (file_view.remote_location().is_web()) {
|
||||
LOG(WARNING) << "Sticker " << file_id << " is web";
|
||||
continue;
|
||||
}
|
||||
if (!file_view.remote_location().is_document()) {
|
||||
LOG(WARNING) << "Sticker " << file_id << " is encrypted";
|
||||
continue;
|
||||
}
|
||||
result.push_back(file_id);
|
||||
|
||||
if (!td_->auth_manager_->is_bot()) {
|
||||
@ -3594,7 +3598,7 @@ int32 StickersManager::get_recent_stickers_hash(const vector<FileId> &sticker_id
|
||||
CHECK(sticker != nullptr);
|
||||
auto file_view = td_->file_manager_->get_file_view(sticker_id);
|
||||
CHECK(file_view.has_remote_location());
|
||||
CHECK(!file_view.remote_location().is_encrypted());
|
||||
CHECK(file_view.remote_location().is_document());
|
||||
CHECK(!file_view.remote_location().is_web());
|
||||
auto id = static_cast<uint64>(file_view.remote_location().get_id());
|
||||
numbers.push_back(static_cast<uint32>(id >> 32));
|
||||
@ -3678,14 +3682,14 @@ bool StickersManager::add_recent_sticker_impl(bool is_attached, FileId sticker_i
|
||||
promise.set_error(Status::Error(7, "Can save only sent stickers"));
|
||||
return false;
|
||||
}
|
||||
if (file_view.remote_location().is_encrypted()) {
|
||||
promise.set_error(Status::Error(7, "Can't save encrypted stickers"));
|
||||
return false;
|
||||
}
|
||||
if (file_view.remote_location().is_web()) {
|
||||
promise.set_error(Status::Error(7, "Can't save web stickers"));
|
||||
return false;
|
||||
}
|
||||
if (!file_view.remote_location().is_document()) {
|
||||
promise.set_error(Status::Error(7, "Can't save encrypted stickers"));
|
||||
return false;
|
||||
}
|
||||
|
||||
need_update_recent_stickers_[is_attached] = true;
|
||||
|
||||
@ -3737,7 +3741,7 @@ void StickersManager::remove_recent_sticker(bool is_attached, const tl_object_pt
|
||||
// TODO invokeAfter
|
||||
auto file_view = td_->file_manager_->get_file_view(file_id);
|
||||
CHECK(file_view.has_remote_location());
|
||||
CHECK(!file_view.remote_location().is_encrypted());
|
||||
CHECK(file_view.remote_location().is_document());
|
||||
CHECK(!file_view.remote_location().is_web());
|
||||
td_->create_handler<SaveRecentStickerQuery>(std::move(promise))
|
||||
->send(is_attached, file_view.remote_location().as_input_document(), true);
|
||||
@ -4023,15 +4027,15 @@ bool StickersManager::add_favorite_sticker_impl(FileId sticker_id, Promise<Unit>
|
||||
|
||||
auto file_view = td_->file_manager_->get_file_view(sticker_id);
|
||||
if (!file_view.has_remote_location()) {
|
||||
promise.set_error(Status::Error(7, "Can fave only sent stickers"));
|
||||
return false;
|
||||
}
|
||||
if (file_view.remote_location().is_encrypted()) {
|
||||
promise.set_error(Status::Error(7, "Can't fave encrypted stickers"));
|
||||
promise.set_error(Status::Error(7, "Can add to favorites only sent stickers"));
|
||||
return false;
|
||||
}
|
||||
if (file_view.remote_location().is_web()) {
|
||||
promise.set_error(Status::Error(7, "Can't fave web stickers"));
|
||||
promise.set_error(Status::Error(7, "Can't add to favorites web stickers"));
|
||||
return false;
|
||||
}
|
||||
if (!file_view.remote_location().is_document()) {
|
||||
promise.set_error(Status::Error(7, "Can't add to favorites encrypted stickers"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -4082,7 +4086,7 @@ void StickersManager::remove_favorite_sticker(const tl_object_ptr<td_api::InputF
|
||||
// TODO invokeAfter
|
||||
auto file_view = td_->file_manager_->get_file_view(file_id);
|
||||
CHECK(file_view.has_remote_location());
|
||||
CHECK(!file_view.remote_location().is_encrypted());
|
||||
CHECK(file_view.remote_location().is_document());
|
||||
CHECK(!file_view.remote_location().is_web());
|
||||
td_->create_handler<FaveStickerQuery>(std::move(promise))
|
||||
->send(file_view.remote_location().as_input_document(), true);
|
||||
@ -4140,7 +4144,7 @@ vector<string> StickersManager::get_sticker_emojis(const tl_object_ptr<td_api::I
|
||||
promise.set_value(Unit());
|
||||
return {};
|
||||
}
|
||||
if (file_view.remote_location().is_encrypted()) {
|
||||
if (!file_view.remote_location().is_document()) {
|
||||
promise.set_value(Unit());
|
||||
return {};
|
||||
}
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "td/telegram/PasswordManager.h"
|
||||
#include "td/telegram/Photo.h"
|
||||
#include "td/telegram/PrivacyManager.h"
|
||||
#include "td/telegram/SecureValue.h"
|
||||
#include "td/telegram/SecretChatId.h"
|
||||
#include "td/telegram/SecretChatsManager.h"
|
||||
#include "td/telegram/StateManager.h"
|
||||
@ -61,6 +62,7 @@
|
||||
|
||||
#include "td/telegram/td_api.hpp"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
#include "td/telegram/telegram_api.hpp"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
@ -71,9 +73,11 @@
|
||||
#include "td/utils/format.h"
|
||||
#include "td/utils/MimeType.h"
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/optional.h"
|
||||
#include "td/utils/PathView.h"
|
||||
#include "td/utils/port/path.h"
|
||||
#include "td/utils/Random.h"
|
||||
#include "td/utils/overloaded.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/Status.h"
|
||||
#include "td/utils/Timer.h"
|
||||
@ -3796,6 +3800,134 @@ class GetTermsOfServiceRequest : public RequestActor<string> {
|
||||
}
|
||||
};
|
||||
|
||||
class GetSecureValue : public NetQueryCallback {
|
||||
public:
|
||||
GetSecureValue(std::string password, SecureValueType type, Promise<SecureValue> promise)
|
||||
: password_(std::move(password)), type_(type), promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
private:
|
||||
string password_;
|
||||
SecureValueType type_;
|
||||
Promise<SecureValue> promise_;
|
||||
optional<EncryptedSecureValue> encrypted_secure_value_;
|
||||
optional<secure_storage::Secret> secret_;
|
||||
|
||||
void on_error(Status status) {
|
||||
promise_.set_error(std::move(status));
|
||||
stop();
|
||||
}
|
||||
|
||||
void on_secret(Result<secure_storage::Secret> r_secret, bool dummy) {
|
||||
LOG_IF(ERROR, r_secret.is_error()) << r_secret.error();
|
||||
LOG_IF(ERROR, r_secret.is_ok()) << r_secret.ok().get_hash();
|
||||
if (r_secret.is_error()) {
|
||||
return on_error(r_secret.move_as_error());
|
||||
}
|
||||
secret_ = r_secret.move_as_ok();
|
||||
loop();
|
||||
}
|
||||
|
||||
void loop() override {
|
||||
if (!encrypted_secure_value_ || !secret_) {
|
||||
return;
|
||||
}
|
||||
promise_.set_result(decrypt_encrypted_secure_value(G()->td().get_actor_unsafe()->file_manager_.get(), *secret_,
|
||||
*encrypted_secure_value_));
|
||||
stop();
|
||||
}
|
||||
void start_up() override {
|
||||
std::vector<telegram_api::object_ptr<telegram_api::SecureValueType>> vec;
|
||||
vec.push_back(get_secure_value_type_telegram_object(type_));
|
||||
|
||||
auto query = G()->net_query_creator().create(create_storer(telegram_api::account_getSecureValue(std::move(vec))));
|
||||
|
||||
G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this));
|
||||
|
||||
send_closure(G()->password_manager(), &PasswordManager::get_secure_secret, password_, optional<int64>(),
|
||||
PromiseCreator::lambda([actor_id = actor_id(this)](Result<secure_storage::Secret> r_secret) {
|
||||
send_closure(actor_id, &GetSecureValue::on_secret, std::move(r_secret), true);
|
||||
}));
|
||||
}
|
||||
|
||||
void on_result(NetQueryPtr query) override {
|
||||
auto r_result = fetch_result<telegram_api::account_getSecureValue>(std::move(query));
|
||||
if (r_result.is_error()) {
|
||||
return on_error(r_result.move_as_error());
|
||||
}
|
||||
auto result = r_result.move_as_ok();
|
||||
if (result.size() != 1) {
|
||||
return on_error(Status::Error(PSLICE() << "Expected vector of size 1 got " << result.size()));
|
||||
}
|
||||
LOG(ERROR) << to_string(result[0]);
|
||||
encrypted_secure_value_ =
|
||||
get_encrypted_secure_value(G()->td().get_actor_unsafe()->file_manager_.get(), std::move(result[0]));
|
||||
loop();
|
||||
}
|
||||
};
|
||||
|
||||
class SetSecureValue : public NetQueryCallback {
|
||||
public:
|
||||
SetSecureValue(string password, SecureValue secure_value, Promise<Unit> promise)
|
||||
: password_(std::move(password)), secure_value_(std::move(secure_value)), promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
private:
|
||||
string password_;
|
||||
SecureValue secure_value_;
|
||||
Promise<Unit> promise_;
|
||||
optional<secure_storage::Secret> secret_;
|
||||
|
||||
enum class State { WaitSecret, WaitSetValue } state_ = State::WaitSecret;
|
||||
|
||||
void on_error(Status status) {
|
||||
promise_.set_error(std::move(status));
|
||||
stop();
|
||||
}
|
||||
|
||||
void on_secret(Result<secure_storage::Secret> r_secret, bool x) {
|
||||
LOG_IF(ERROR, r_secret.is_error()) << r_secret.error();
|
||||
LOG_IF(ERROR, r_secret.is_ok()) << r_secret.ok().get_hash();
|
||||
if (r_secret.is_error()) {
|
||||
return on_error(r_secret.move_as_error());
|
||||
}
|
||||
secret_ = r_secret.move_as_ok();
|
||||
loop();
|
||||
}
|
||||
|
||||
void start_up() override {
|
||||
send_closure(G()->password_manager(), &PasswordManager::get_secure_secret, password_, optional<int64>(),
|
||||
PromiseCreator::lambda([actor_id = actor_id(this)](Result<secure_storage::Secret> r_secret) {
|
||||
send_closure(actor_id, &SetSecureValue::on_secret, std::move(r_secret), true);
|
||||
}));
|
||||
}
|
||||
|
||||
void loop() override {
|
||||
if (state_ == State::WaitSecret) {
|
||||
if (!secret_) {
|
||||
return;
|
||||
}
|
||||
auto *file_manager = G()->td().get_actor_unsafe()->file_manager_.get();
|
||||
auto save_secure_value = telegram_api::account_saveSecureValue(
|
||||
get_input_secure_value_object(file_manager, encrypt_secure_value(file_manager, *secret_, secure_value_)),
|
||||
secret_.value().get_hash());
|
||||
LOG(ERROR) << to_string(save_secure_value);
|
||||
auto query = G()->net_query_creator().create(create_storer(save_secure_value));
|
||||
|
||||
G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this));
|
||||
state_ = State::WaitSetValue;
|
||||
}
|
||||
}
|
||||
void on_result(NetQueryPtr query) override {
|
||||
auto r_result = fetch_result<telegram_api::account_saveSecureValue>(std::move(query));
|
||||
if (r_result.is_error()) {
|
||||
return on_error(r_result.move_as_error());
|
||||
}
|
||||
auto result = r_result.move_as_ok();
|
||||
LOG(ERROR) << to_string(result);
|
||||
}
|
||||
};
|
||||
|
||||
/** Td **/
|
||||
Td::Td(std::unique_ptr<TdCallback> callback) : callback_(std::move(callback)) {
|
||||
}
|
||||
@ -4400,6 +4532,11 @@ class Td::UploadFileCallback : public FileManager::UploadCallback {
|
||||
send_closure(G()->file_manager(), &FileManager::upload, file_id, nullptr, 0, 0);
|
||||
}
|
||||
|
||||
void on_upload_secure_ok(FileId file_id, tl_object_ptr<telegram_api::InputSecureFile> input_file) override {
|
||||
// cancel file upload of the file to allow next upload with the same file to succeed
|
||||
send_closure(G()->file_manager(), &FileManager::upload, file_id, nullptr, 0, 0);
|
||||
}
|
||||
|
||||
void on_upload_error(FileId file_id, Status error) override {
|
||||
}
|
||||
};
|
||||
@ -4544,6 +4681,7 @@ Status Td::init(DbKey key) {
|
||||
device_token_manager_ = create_actor<DeviceTokenManager>("DeviceTokenManager", create_reference());
|
||||
hashtag_hints_ = create_actor<HashtagHints>("HashtagHints", "text", create_reference());
|
||||
password_manager_ = create_actor<PasswordManager>("PasswordManager", create_reference());
|
||||
G()->set_password_manager(password_manager_.get());
|
||||
privacy_manager_ = create_actor<PrivacyManager>("PrivacyManager", create_reference());
|
||||
secret_chats_manager_ = create_actor<SecretChatsManager>("SecretChatsManager", create_reference());
|
||||
G()->set_secret_chats_manager(secret_chats_manager_.get());
|
||||
@ -5847,7 +5985,7 @@ void Td::on_request(uint64 id, td_api::createCall &request) {
|
||||
});
|
||||
|
||||
if (!request.protocol_) {
|
||||
return query_promise.set_error(Status::Error(5, "CallProtocol must not be empty"));
|
||||
return query_promise.set_error(Status::Error(5, "Call protocol must not be empty"));
|
||||
}
|
||||
|
||||
UserId user_id(request.user_id_);
|
||||
@ -6809,6 +6947,96 @@ void Td::on_request(uint64 id, const td_api::deleteSavedCredentials &request) {
|
||||
CREATE_NO_ARGS_REQUEST(DeleteSavedCredentialsRequest);
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::getPassportData &request) {
|
||||
CHECK_AUTH();
|
||||
CHECK_IS_USER();
|
||||
CLEAN_INPUT_STRING(request.password_);
|
||||
if (request.type_ == nullptr) {
|
||||
return send_error_raw(id, 400, "Type must not be empty");
|
||||
}
|
||||
create_actor<GetSecureValue>("GetSecureValue", std::move(request.password_),
|
||||
get_secure_value_type_td_api(std::move(request.type_)),
|
||||
PromiseCreator::lambda([](Result<SecureValue> r_value) {
|
||||
LOG_IF(ERROR, r_value.is_error()) << r_value.error();
|
||||
LOG_IF(ERROR, r_value.is_ok()) << r_value.ok().data;
|
||||
}))
|
||||
.release();
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::setPassportData &request) {
|
||||
CHECK_AUTH();
|
||||
CHECK_IS_USER();
|
||||
CLEAN_INPUT_STRING(request.password_);
|
||||
auto r_secure_value = get_secure_value(std::move(request.value_));
|
||||
if (r_secure_value.is_error()) {
|
||||
return send_closure(actor_id(this), &Td::send_error, id, r_secure_value.move_as_error());
|
||||
}
|
||||
create_actor<SetSecureValue>(
|
||||
"SetSecureValue", std::move(request.password_), r_secure_value.move_as_ok(),
|
||||
PromiseCreator::lambda([](Result<Unit> result) { LOG_IF(ERROR, result.is_error()) << result.error(); }))
|
||||
.release();
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::deletePassportData &request) {
|
||||
CHECK_AUTH();
|
||||
CHECK_IS_USER();
|
||||
LOG(FATAL) << "TODO";
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::sendPhoneNumberVerificationCode &request) {
|
||||
CHECK_AUTH();
|
||||
CHECK_IS_USER();
|
||||
CLEAN_INPUT_STRING(request.phone_number_);
|
||||
LOG(FATAL) << "TODO";
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::resendPhoneNumberVerificationCode &request) {
|
||||
CHECK_AUTH();
|
||||
CHECK_IS_USER();
|
||||
LOG(FATAL) << "TODO";
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::checkPhoneNumberVerificationCode &request) {
|
||||
CHECK_AUTH();
|
||||
CHECK_IS_USER();
|
||||
CLEAN_INPUT_STRING(request.code_);
|
||||
LOG(FATAL) << "TODO";
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::sendEmailAddressVerificationCode &request) {
|
||||
CHECK_AUTH();
|
||||
CHECK_IS_USER();
|
||||
CLEAN_INPUT_STRING(request.email_address_);
|
||||
LOG(FATAL) << "TODO";
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::resendEmailAddressVerificationCode &request) {
|
||||
CHECK_AUTH();
|
||||
CHECK_IS_USER();
|
||||
LOG(FATAL) << "TODO";
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::checkEmailAddressVerificationCode &request) {
|
||||
CHECK_AUTH();
|
||||
CHECK_IS_USER();
|
||||
CLEAN_INPUT_STRING(request.code_);
|
||||
LOG(FATAL) << "TODO";
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::getPassportAuthorizationForm &request) {
|
||||
CHECK_AUTH();
|
||||
CHECK_IS_USER();
|
||||
CLEAN_INPUT_STRING(request.public_key_);
|
||||
CLEAN_INPUT_STRING(request.scope_);
|
||||
LOG(FATAL) << "TODO";
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::sendPassportAuthorizationForm &request) {
|
||||
CHECK_AUTH();
|
||||
CHECK_IS_USER();
|
||||
LOG(FATAL) << "TODO";
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::getSupportUser &request) {
|
||||
CHECK_AUTH();
|
||||
CHECK_IS_USER();
|
||||
|
@ -747,6 +747,28 @@ class Td final : public NetQueryCallback {
|
||||
|
||||
void on_request(uint64 id, const td_api::deleteSavedCredentials &request);
|
||||
|
||||
void on_request(uint64 id, td_api::getPassportData &request);
|
||||
|
||||
void on_request(uint64 id, td_api::setPassportData &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::deletePassportData &request);
|
||||
|
||||
void on_request(uint64 id, td_api::sendPhoneNumberVerificationCode &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::resendPhoneNumberVerificationCode &request);
|
||||
|
||||
void on_request(uint64 id, td_api::checkPhoneNumberVerificationCode &request);
|
||||
|
||||
void on_request(uint64 id, td_api::sendEmailAddressVerificationCode &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::resendEmailAddressVerificationCode &request);
|
||||
|
||||
void on_request(uint64 id, td_api::checkEmailAddressVerificationCode &request);
|
||||
|
||||
void on_request(uint64 id, td_api::getPassportAuthorizationForm &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::sendPassportAuthorizationForm &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::getSupportUser &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::getWallpapers &request);
|
||||
|
@ -487,6 +487,8 @@ bool UpdatesManager::is_acceptable_message(const telegram_api::Message *message_
|
||||
case telegram_api::messageActionPaymentSent::ID:
|
||||
case telegram_api::messageActionPaymentSentMe::ID:
|
||||
case telegram_api::messageActionScreenshotTaken::ID:
|
||||
case telegram_api::messageActionSecureValuesSent::ID:
|
||||
case telegram_api::messageActionSecureValuesSentMe::ID:
|
||||
break;
|
||||
case telegram_api::messageActionChatCreate::ID: {
|
||||
auto chat_create = static_cast<const telegram_api::messageActionChatCreate *>(action);
|
||||
|
@ -934,6 +934,35 @@ class CliClient final : public Actor {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static tl_object_ptr<td_api::PassportDataType> as_passport_data_type(string passport_data_type) {
|
||||
if (passport_data_type == "address" || passport_data_type == "a") {
|
||||
return make_tl_object<td_api::passportDataTypeAddress>();
|
||||
}
|
||||
if (passport_data_type == "email" || passport_data_type == "e") {
|
||||
return make_tl_object<td_api::passportDataTypeEmailAddress>();
|
||||
}
|
||||
if (passport_data_type == "phone" || passport_data_type == "p") {
|
||||
return make_tl_object<td_api::passportDataTypePhoneNumber>();
|
||||
}
|
||||
return make_tl_object<td_api::passportDataTypePassport>();
|
||||
}
|
||||
static tl_object_ptr<td_api::inputPassportData> as_input_passport_data(string passport_data_type) {
|
||||
return nullptr;
|
||||
/* TODO
|
||||
vector<td_api::object_ptr<td_api::InputFile>> files;
|
||||
if (passport_data_type == "address" || passport_data_type == "a") {
|
||||
return make_tl_object<td_api::inputPassportDataAddress>("cucumber lives here", std::move(files));
|
||||
}
|
||||
if (passport_data_type == "email" || passport_data_type == "e") {
|
||||
return make_tl_object<td_api::inputPassportDataEmailAddress>("{todo}");
|
||||
}
|
||||
if (passport_data_type == "phone" || passport_data_type == "p") {
|
||||
return make_tl_object<td_api::inputPassportDataPhoneNumber>("{todo}");
|
||||
}
|
||||
return make_tl_object<td_api::inputPassportDataIdentity>("I am cucumber", std::move(files));
|
||||
*/
|
||||
}
|
||||
|
||||
static td_api::object_ptr<td_api::Object> execute(tl_object_ptr<td_api::Function> f) {
|
||||
LOG(INFO) << "Execute request: " << to_string(f);
|
||||
auto res = ClientActor::execute(std::move(f));
|
||||
@ -1049,6 +1078,16 @@ class CliClient final : public Actor {
|
||||
send_request(make_tl_object<td_api::getTemporaryPasswordState>());
|
||||
} else if (op == "ctp" || op == "CreateTemporaryPassword") {
|
||||
send_request(make_tl_object<td_api::createTemporaryPassword>(args, 60 * 6));
|
||||
} else if (op == "gpd") {
|
||||
string password;
|
||||
string passport_data_type;
|
||||
std::tie(password, passport_data_type) = split(args);
|
||||
send_request(make_tl_object<td_api::getPassportData>(as_passport_data_type(passport_data_type), password));
|
||||
} else if (op == "spd") {
|
||||
string password;
|
||||
string passport_data_type;
|
||||
std::tie(password, passport_data_type) = split(args);
|
||||
send_request(make_tl_object<td_api::setPassportData>(as_input_passport_data(passport_data_type), password));
|
||||
} else if (op == "pdu" || op == "processDcUpdate") {
|
||||
string dc_id;
|
||||
string ip_port;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "td/utils/ScopeGuard.h"
|
||||
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
namespace td {
|
||||
void FileLoader::set_resource_manager(ActorShared<ResourceManager> resource_manager) {
|
||||
@ -176,7 +177,7 @@ Status FileLoader::do_loop() {
|
||||
} else {
|
||||
send_closure(delay_dispatcher_, &DelayDispatcher::send_with_callback_and_delay, std::move(query),
|
||||
std::move(callback), next_delay_);
|
||||
next_delay_ = std::max(next_delay_ * 0.8, 0.003);
|
||||
next_delay_ = max(next_delay_ * 0.8, 0.003);
|
||||
}
|
||||
}
|
||||
return Status::OK();
|
||||
|
@ -141,7 +141,7 @@ Result<string> search_file(CSlice dir, CSlice name, int64 expected_size) {
|
||||
const char *file_type_name[file_type_size] = {"thumbnails", "profile_photos", "photos", "voice",
|
||||
"videos", "documents", "secret", "temp",
|
||||
"stickers", "music", "animations", "secret_thumbnails",
|
||||
"wallpapers", "video_notes"};
|
||||
"wallpapers", "video_notes", "passport_temp", "passport"};
|
||||
|
||||
string get_file_base_dir(const FileDirType &file_dir_type) {
|
||||
switch (file_dir_type) {
|
||||
|
@ -45,6 +45,8 @@ enum class FileType : int8 {
|
||||
EncryptedThumbnail,
|
||||
Wallpaper,
|
||||
VideoNote,
|
||||
SecureRaw,
|
||||
Secure,
|
||||
Size,
|
||||
None
|
||||
};
|
||||
@ -79,6 +81,10 @@ inline FileType from_td_api(const td_api::FileType &file_type) {
|
||||
return FileType::Wallpaper;
|
||||
case td_api::fileTypeVideoNote::ID:
|
||||
return FileType::VideoNote;
|
||||
case td_api::fileTypeSecure::ID:
|
||||
return FileType::Secure;
|
||||
case td_api::fileTypeSecureEncrypted::ID:
|
||||
return FileType::SecureRaw;
|
||||
case td_api::fileTypeNone::ID:
|
||||
return FileType::None;
|
||||
default:
|
||||
@ -117,6 +123,10 @@ inline tl_object_ptr<td_api::FileType> as_td_api(FileType file_type) {
|
||||
return make_tl_object<td_api::fileTypeWallpaper>();
|
||||
case FileType::VideoNote:
|
||||
return make_tl_object<td_api::fileTypeVideoNote>();
|
||||
case FileType::Secure:
|
||||
return make_tl_object<td_api::fileTypeSecure>();
|
||||
case FileType::SecureRaw:
|
||||
return make_tl_object<td_api::fileTypeSecureEncrypted>();
|
||||
case FileType::None:
|
||||
return make_tl_object<td_api::fileTypeNone>();
|
||||
default:
|
||||
@ -135,6 +145,8 @@ inline FileDirType get_file_dir_type(FileType file_type) {
|
||||
case FileType::Temp:
|
||||
case FileType::Wallpaper:
|
||||
case FileType::EncryptedThumbnail:
|
||||
case FileType::Secure:
|
||||
case FileType::SecureRaw:
|
||||
return FileDirType::Secure;
|
||||
default:
|
||||
return FileDirType::Common;
|
||||
@ -422,6 +434,8 @@ class FullRemoteFileLocation {
|
||||
case FileType::Animation:
|
||||
case FileType::Encrypted:
|
||||
case FileType::VideoNote:
|
||||
case FileType::SecureRaw:
|
||||
case FileType::Secure:
|
||||
return LocationType::Common;
|
||||
case FileType::None:
|
||||
case FileType::Size:
|
||||
@ -571,9 +585,21 @@ class FullRemoteFileLocation {
|
||||
bool is_common() const {
|
||||
return location_type() == LocationType::Common;
|
||||
}
|
||||
bool is_encrypted() const {
|
||||
bool is_encrypted_secret() const {
|
||||
return file_type_ == FileType::Encrypted;
|
||||
}
|
||||
bool is_encrypted_secure() const {
|
||||
return file_type_ == FileType::Secure;
|
||||
}
|
||||
bool is_encrypted_any() const {
|
||||
return is_encrypted_secret() || is_encrypted_secure();
|
||||
}
|
||||
bool is_secure() const {
|
||||
return file_type_ == FileType::SecureRaw || file_type_ == FileType::Secure;
|
||||
}
|
||||
bool is_document() const {
|
||||
return is_common() && !is_secure() && !is_encrypted_secret();
|
||||
}
|
||||
|
||||
tl_object_ptr<telegram_api::inputWebFileLocation> as_input_web_file_location() const {
|
||||
CHECK(is_web());
|
||||
@ -584,8 +610,10 @@ class FullRemoteFileLocation {
|
||||
case LocationType::Photo:
|
||||
return make_tl_object<telegram_api::inputFileLocation>(photo().volume_id_, photo().local_id_, photo().secret_);
|
||||
case LocationType::Common:
|
||||
if (is_encrypted()) {
|
||||
if (is_encrypted_secret()) {
|
||||
return make_tl_object<telegram_api::inputEncryptedFileLocation>(common().id_, common().access_hash_);
|
||||
} else if (is_secure()) {
|
||||
return make_tl_object<telegram_api::inputSecureFileLocation>(common().id_, common().access_hash_);
|
||||
} else {
|
||||
return make_tl_object<telegram_api::inputDocumentFileLocation>(common().id_, common().access_hash_, 0);
|
||||
}
|
||||
@ -599,7 +627,7 @@ class FullRemoteFileLocation {
|
||||
|
||||
tl_object_ptr<telegram_api::InputDocument> as_input_document() const {
|
||||
CHECK(is_common());
|
||||
LOG_IF(ERROR, is_encrypted()) << "Can't call as_input_document on an encrypted file";
|
||||
LOG_IF(ERROR, !is_document()) << "Can't call as_input_document on an encrypted file";
|
||||
return make_tl_object<telegram_api::inputDocument>(common().id_, common().access_hash_);
|
||||
}
|
||||
|
||||
@ -609,9 +637,13 @@ class FullRemoteFileLocation {
|
||||
}
|
||||
|
||||
tl_object_ptr<telegram_api::InputEncryptedFile> as_input_encrypted_file() const {
|
||||
CHECK(is_encrypted()) << "Can't call as_input_encrypted_file on a non-encrypted file";
|
||||
CHECK(is_encrypted_secret()) << "Can't call as_input_encrypted_file on a non-encrypted file";
|
||||
return make_tl_object<telegram_api::inputEncryptedFile>(common().id_, common().access_hash_);
|
||||
}
|
||||
tl_object_ptr<telegram_api::InputSecureFile> as_input_secure_file() const {
|
||||
CHECK(is_secure()) << "Can't call as_input_secure_file on a non-secure file";
|
||||
return make_tl_object<telegram_api::inputSecureFile>(common().id_, common().access_hash_);
|
||||
}
|
||||
|
||||
// TODO: this constructor is just for immediate unserialize
|
||||
FullRemoteFileLocation() = default;
|
||||
|
@ -1887,6 +1887,12 @@ tl_object_ptr<td_api::file> FileManager::get_file_object(FileId file_id, bool wi
|
||||
file_view.has_remote_location(), remote_size));
|
||||
}
|
||||
|
||||
vector<tl_object_ptr<td_api::file>> FileManager::get_files_object(const vector<FileId> &file_ids,
|
||||
bool with_main_file_id) {
|
||||
return transform(file_ids,
|
||||
[this, with_main_file_id](FileId file_id) { return get_file_object(file_id, with_main_file_id); });
|
||||
}
|
||||
|
||||
Result<FileId> FileManager::check_input_file_id(FileType type, Result<FileId> result, bool is_encrypted,
|
||||
bool allow_zero) {
|
||||
TRY_RESULT(file_id, std::move(result));
|
||||
@ -2122,7 +2128,7 @@ void FileManager::on_upload_ok(QueryId query_id, FileType file_type, const Parti
|
||||
FileView file_view(file_node);
|
||||
string file_name = get_file_name(file_type, file_view.suggested_name());
|
||||
|
||||
if (file_view.is_encrypted()) {
|
||||
if (file_view.is_encrypted_secret()) {
|
||||
tl_object_ptr<telegram_api::InputEncryptedFile> input_file;
|
||||
if (partial_remote.is_big_) {
|
||||
input_file = make_tl_object<telegram_api::inputEncryptedFileBigUploaded>(
|
||||
@ -2136,6 +2142,16 @@ void FileManager::on_upload_ok(QueryId query_id, FileType file_type, const Parti
|
||||
file_node->upload_pause_ = file_id;
|
||||
file_info->upload_callback_.reset();
|
||||
}
|
||||
} else if (file_view.is_secure()) {
|
||||
tl_object_ptr<telegram_api::InputSecureFile> input_file;
|
||||
input_file = make_tl_object<telegram_api::inputSecureFileUploaded>(
|
||||
partial_remote.file_id_, partial_remote.part_count_, "" /*md5*/, BufferSlice() /*file_hash*/,
|
||||
BufferSlice() /*encrypted_secret*/);
|
||||
if (file_info->upload_callback_) {
|
||||
file_info->upload_callback_->on_upload_secure_ok(file_id, std::move(input_file));
|
||||
file_node->upload_pause_ = file_id;
|
||||
file_info->upload_callback_.reset();
|
||||
}
|
||||
} else {
|
||||
tl_object_ptr<telegram_api::InputFile> input_file;
|
||||
if (partial_remote.is_big_) {
|
||||
|
@ -224,9 +224,21 @@ class FileView {
|
||||
}
|
||||
return FileType::Temp;
|
||||
}
|
||||
bool is_encrypted() const {
|
||||
bool is_encrypted_secret() const {
|
||||
return get_type() == FileType::Encrypted;
|
||||
}
|
||||
bool is_encrypted_secure() const {
|
||||
return get_type() == FileType::Secure;
|
||||
}
|
||||
bool is_secure() const {
|
||||
return get_type() == FileType::Secure || get_type() == FileType::SecureRaw;
|
||||
}
|
||||
bool is_encrypted_any() const {
|
||||
return is_encrypted_secret() || is_encrypted_secure();
|
||||
}
|
||||
bool is_encrypted() const {
|
||||
return is_encrypted_secret() || is_secure();
|
||||
}
|
||||
const FileEncryptionKey &encryption_key() const {
|
||||
return node_->encryption_key_;
|
||||
}
|
||||
@ -266,6 +278,7 @@ class FileManager : public FileLoadManager::Callback {
|
||||
// Also upload may be resumed after some other merges.
|
||||
virtual void on_upload_ok(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file) = 0;
|
||||
virtual void on_upload_encrypted_ok(FileId file_id, tl_object_ptr<telegram_api::InputEncryptedFile> input_file) = 0;
|
||||
virtual void on_upload_secure_ok(FileId file_id, tl_object_ptr<telegram_api::InputSecureFile> input_file) = 0;
|
||||
virtual void on_upload_error(FileId file_id, Status error) = 0;
|
||||
};
|
||||
|
||||
@ -326,6 +339,7 @@ class FileManager : public FileLoadManager::Callback {
|
||||
FileView get_file_view(FileId file_id) const;
|
||||
FileView get_sync_file_view(FileId file_id);
|
||||
tl_object_ptr<td_api::file> get_file_object(FileId file_id, bool with_main_file_id = true);
|
||||
vector<tl_object_ptr<td_api::file>> get_files_object(const vector<FileId> &file_ids, bool with_main_file_id = true);
|
||||
|
||||
Result<FileId> get_input_thumbnail_file_id(const tl_object_ptr<td_api::InputFile> &thumb_input_file,
|
||||
DialogId owner_dialog_id, bool is_encrypted) TD_WARN_UNUSED_RESULT;
|
||||
|
@ -40,7 +40,7 @@ void FileManager::store_file(FileId file_id, StorerT &storer, int32 ttl) const {
|
||||
bool has_expected_size =
|
||||
file_store_type == FileStoreType::Remote && file_view.size() == 0 && file_view.expected_size() != 0;
|
||||
if (file_store_type != FileStoreType::Empty) {
|
||||
has_encryption_key = !file_view.empty() && file_view.is_encrypted();
|
||||
has_encryption_key = !file_view.empty() && file_view.is_encrypted_secret();
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(has_encryption_key);
|
||||
STORE_FLAG(has_expected_size);
|
||||
|
@ -18,7 +18,7 @@ class HeaderStorer {
|
||||
}
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const {
|
||||
constexpr int32 LAYER = 76;
|
||||
constexpr int32 LAYER = 78;
|
||||
|
||||
using td::store;
|
||||
// invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <openssl/rand.h>
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <random>
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "td/utils/port/RwMutex.h"
|
||||
#include "td/utils/port/thread_local.h"
|
||||
#include "td/utils/Random.h"
|
||||
#include "td/utils/ScopeGuard.h"
|
||||
|
||||
#if TD_HAVE_OPENSSL
|
||||
#include <openssl/aes.h>
|
||||
@ -485,7 +486,6 @@ Result<BufferSlice> rsa_encrypt_pkcs1_oaep(Slice public_key, Slice data) {
|
||||
}
|
||||
BufferSlice res(outlen);
|
||||
if (EVP_PKEY_encrypt(ctx, res.as_slice().ubegin(), &outlen, data.ubegin(), data.size()) <= 0) {
|
||||
// ERR_print_errors_fp(stderr);
|
||||
return Status::Error("Cannot encrypt");
|
||||
}
|
||||
return std::move(res);
|
||||
|
@ -6,6 +6,7 @@
|
||||
//
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/filesystem.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/port/path.h"
|
||||
#include "td/utils/tests.h"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user