// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // Sync protocol datatype extension for password data. // If you change or add any fields in this file, update proto_visitors.h and // potentially proto_enum_conversions.{h, cc}. syntax = "proto2"; option go_package = "./sync_pb"; option java_multiple_files = true; option java_package = "org.chromium.components.sync.protocol"; option optimize_for = LITE_RUNTIME; package sync_pb; import "encryption.proto"; // These are the properties that get serialized into the |encrypted| field of // PasswordSpecifics. They correspond to fields in // password_manager::PasswordForm. // // Sync unique tag is calculated as // EscapePath(origin) + "|" + // EscapePath(username_element) + "|" + // EscapePath(username_value) + "|" + // EscapePath(password_element) + "|" + // EscapePath(signon_realm) // where '+' is the string concatenation operation. EscapePath escapes a partial // or complete file/pathname. This includes non-printable, non-7bit, and // (including space) the following characters ' "#%:<>?[\]^`{|}'. The space // character is encoded as '%20'. // A simple example of PasswordSpecificsData, as created by Chrome for a web // form that the user submitted. E.g. federated credentials or credentials for // Android apps may have different fields set. // PasswordSpecificsData { // action: "https://example.com/", // avatar_url: "", // blacklisted: false, // date_created: 13305119271948046, // date_last_used: 13305119270102691, // date_password_modified_windows_epoch_micros: 13305119271949070, // display_name: "", // federation_url: "", // notes: {}, // origin: "https://rsolomakhin.github.io/autofill/", // password_element: "password", // password_issues: {}, // password_value: "pwd", // scheme: 0, // signon_realm: "https://rsolomakhin.github.io/", // times_used: 0, // type: 0, // username_element: "username", // username_value: "Superman" // } // All the strings are encoded with UTF-8. URLs are encoded in Punycode. message PasswordIssues { message PasswordIssue { // Timestamp set by a client detecting the issue for the first time. // Number of microseconds since Windows epoch (1601). // This can be unset even if is_muted is set in a few cases in // storage (for a time mutes were written without setting this // field - fixed starting 2021-11-10). optional uint64 date_first_detection_windows_epoch_micros = 1; // Whether the issue was muted by user. optional bool is_muted = 2; // Whether the backend should notify the user about this issue. // Set to true if the user hasn't already seen a client notification for // this issue (e.g. a leak detection prompt in Chrome). The backend sending // notifications does not reset this field. All other sources can write this // in both `PasswordSpecificsData` and `PasswordSpecificsMetadata` and do // so. optional bool trigger_notification_from_backend_on_detection = 3; } optional PasswordIssue leaked_password_issue = 1; optional PasswordIssue reused_password_issue = 2; optional PasswordIssue weak_password_issue = 3; optional PasswordIssue phished_password_issue = 4; } message PasswordSpecificsData { // The different types of the saved credential. enum Scheme { // SCHEME_HTML, the credential represents either a parsed HTML form, or an // android credential or a password saved through Credential Management API // (https://w3c.github.io/webappsec/specs/credentialmanagement/). SCHEME_HTML = 0; // SCHEME_BASIC, basic access http authentication. SCHEME_BASIC = 1; // SCHEME_DIGEST, digest access authentication. SCHEME_DIGEST = 2; // SCHEME_OTHER, another proxy access authentication. SCHEME_OTHER = 3; // USERNAME_ONLY, partial credentials saved on Android that contain only // username and miss the password. USERNAME_ONLY = 4; } // See the enum above. optional int32 scheme = 1; // Signon realm stores information on where the saved password was stored, and // where it's supposed to be filled again. // // It can take various formats depending on the exact circumstances where it // was recorded. Note that the format is *not* guaranteed to be a valid URL or // URI: // // * For parsed web forms and normal passwords saved through Credential // Manager // API: ://[:]/ // // where // is one of "http" or "https" // is the host for which the password was stored // is the option port on the host // The signon realm is a valid URL in this case with an empty path. // Examples: // http://www.example.com/ // https://127.0.0.1/ // http://www.google.com:8080/ // http://192.168.1.254/ // https://accounts.google.com/ // // * For Android apps saved through Autofill with Google: // android://@/ // where // is the base64 encoded SHA512 of the app's public // certificate is the app's package name // Examples: // android://kCyQDzpaoAX2gs-1zdGPKNAeICb8LzRFOxa4NCq0jO8c8d_NFS_q-Y35bU3Nq3GmFV2lLurmNvIZa6YPYZwmWg==@com.pinterest/ // android://mNUCvTnoWBkzIhSSkVj-uzAdK42YagmCmyUtPoC6JPmYAN3wKpmTdIRsdJtz6pzNBye8XL7nBbEcx-y9CJeo9A==@com.twitter.android.lite/ // // * For federated credentials: // federation:/// // where // is the host for which the login information was stored // is the host of the federation provider that was // used to sign in // Examples: // federation://www.example.com/accounts.google.com // federation://uk.trustpilot.com/www.facebook.com // // * For proxy auth: // [:]/ // where // is the host of the proxy for which the password was // stored // is the port of the proxy // is a string provided by the proxy during authentication. // It can contain spaces. // Examples: // proxy2.eq.edu.au:80/MISldap // proxy.det.nsw.edu.au:8080/NSW Department of Education // 10.47.2.250:3128/Squid Proxy Server CPUT // default.go2https.com:443/(******Get password from vpnso.com/account/ // *****) // // * For HTTP basic auth: // ://[:]/ // where // is one of "http" or "https" // is the host for which the password was stored // is the option port on the host // is a string provided by the host during authentication. // It can contain spaces. // Examples: // http://192.168.1.1/Broadband Router // http://192.168.0.1/TP-LINK Wireless N Router WR841N // http://192.168.1.1/index.htm // https://www.edge.asic.gov.au/ASIC eBusiness optional string signon_realm = 2; // For parsed web forms and Credential Management API: // url-scheme://url-host[:url-port]/path // For Android: "android://@/" // For proxy/HTTP auth: url-scheme://url-host[:url-port]/path optional string origin = 3; // Only for web-parsed forms - the action target of the form: // url-scheme://url-host[:url-port]/path optional string action = 4; // Only for web-parsed forms - the name of the element containing username. optional string username_element = 5; // For all: the username. // For blacklisted forms: . optional string username_value = 6; // Only for web-parsed forms - the name of the element containing password. optional string password_element = 7; // For all: the password. // For federated logins and blacklisted forms: optional string password_value = 8; // Deprecated: http://crbug.com/413020 // True if the credential was saved for a HTTPS session with a valid SSL cert. // Ignored for Android apps. optional bool ssl_valid = 9 [deprecated = true]; // True for the last credential used for logging in on a given site. // Deprecated in M81. optional bool preferred = 10 [deprecated = true]; // Time when the credential was created. Amount of microseconds since 1601. optional int64 date_created = 11; // True, if user chose permanently not to save the credentials for the form. optional bool blacklisted = 12; // kFormSubmission(0), user manually filled the username and the password // in the form. // kGenerated(1), the credential was auto generated. // kApi(2), the credential was generated from Credential Management API. // kManuallyAdded(3), user manually created the password credential // via Settings. // kImported(4), the credential was imported using the import flow. // kReceivedViaSharing(5), the credential has been received via the password // sharing feature. optional int32 type = 13; // Number of times this login was used for logging in using an HTML form. // Chrome uses this field to distinguish log-in and sign-up forms. optional int32 times_used = 14; // A human readable name of the account holder. Set by CredentialManager API // and Android. optional string display_name = 15; // A URL of the avatar for the credential. Set by CredentialManager API and // Android. optional string avatar_url = 16; // A URL of the IdP used to verify the credential. Set by Credential Manager // API and Android. optional string federation_url = 17; // Time when the credential was last used. This covers *successful* logins to // the website, and explicit updates to the password. It does *not* cover if // the password just gets filled but not actually submitted, or if the login // failed. // Note that password consumers other than Chrome (e.g. Google Play Services) // might not update this at all. // Amount of microseconds since 1601, aka Windows epoch. optional int64 date_last_used = 18; // Set if an issue was detected that puts this password at risk. All the // clients are expected to clear the field when the password value is updated. // 'reused' part can be additionally reset when the analysis on the entire // password store is completed. optional PasswordIssues password_issues = 19; // Time when the |password_value| was last modified. For new credentials it // should be set to |date_created|. For subsequent updates the timestamp is // changed if and only if the new password value was saved. // Number of microseconds since Windows epoch (1601). optional int64 date_password_modified_windows_epoch_micros = 20; message Notes { message Note { // The display name must be unique within the scope of a password. optional string unique_display_name = 1; // The user-defined value of the note. optional string value = 2; // The creation time of the note. Number of microseconds since 1601. optional int64 date_created_windows_epoch_micros = 3; // Whether the value of the note is not displayed in plain text by // default. optional bool hide_by_default = 4; } repeated Note note = 1; } reserved 21; // Set of extra notes that the user attached to the password. The presence of // this field, even with an empty Notes message, becomes the authoritative // value for notes and would disregard whatever `encrypted_notes_backup` // contains. optional Notes notes = 22; // For credentials that have been shared by another user, this field captures // the sender email. It's empty for credentials that weren't received via // password sharing feature. optional string sender_email = 23; // Similar to `sender_email` but for the sender name. optional string sender_name = 24; // The timestamp when the password was received via sharing feature from // another user. optional int64 date_received_windows_epoch_micros = 25; // Whether the user has been already notified that they received this password // from another user via the password sharing feature. This is synced to avoid // showing the notification on multiple devices. optional bool sharing_notification_displayed = 26; // Similar to `sender_email` but for the url of the sender profile image. optional string sender_profile_image_url = 27; } // Contains the password specifics metadata which simplifies its lookup. message PasswordSpecificsMetadata { // The signon realm for the credential. For more details, see the // `signon_realm` field in PasswordSpecificsData. optional string url = 1; // True, if user chose permanently not to save the credentials for the form. // Introduced in M82. Copy from PasswordSpecificsData.blacklisted. optional bool blacklisted = 2; // Copy from PasswordSpecificsData.date_last_used. // Introduced in M112. optional int64 date_last_used_windows_epoch_micros = 3; // Copy from PasswordSpecificsData.password_issues. Introduced in M114. optional PasswordIssues password_issues = 4; // Copy from PasswordSpecificsData.type. Introduced in M119. optional int32 type = 13; } // Properties of password sync objects. message PasswordSpecifics { // The actual password data. Contains an encrypted PasswordSpecificsData // message. optional EncryptedData encrypted = 1; // An unsynced field for use internally on the client. This field should // never be set in any network-based communications because it contains // unencrypted material. optional PasswordSpecificsData client_only_encrypted_data = 2; // Password related metadata, which is sent to the server side. The field // should never be set for full encryption users. If encryption is enabled, // this field must be cleared. optional PasswordSpecificsMetadata unencrypted_metadata = 3; reserved 4; // An encrypted backup of the notes field inside the PasswordSpecificsData. // The Sync server preserves the contents of this field across commits from // legacy clients that don't set this field. It is the responsibility of Sync // clients to populate the contents of PasswordSpecificsData notes fields // using the contents of this field. This should be deprecated together with // the logic for preserving it on the server when clients without support for // the |notes| field are no longer allowed by the server (below support // version horizon). // // Encryption key considerations: // a) For commits, the client must use the same key for both encrypted blobs. // b) For handling getupdates, the two keys may NOT necessarily match the // encryption key used, as in theory the new blob could be "behind" if key // rotation took place. As of today, it is safe to assume that if // |encrypted| is decryptable by a client, then |encrypted_notes_backup| // must be decryptable too (i.e. the Nigori keybag should include older // versions of the key). But not the other way round. // // If both `encrypted_notes_backup` and the `notes` in `encrypted` are // populated, the one in notes is considered the authoritative value. optional EncryptedData encrypted_notes_backup = 5; }