summaryrefslogtreecommitdiffstats
path: root/chrome/browser/password_manager/password_store_mac_internal.h
blob: 9a01ea4c946d4eba44f8223d703d4f91f23a6929 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_STORE_MAC_INTERNAL_H_
#define CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_STORE_MAC_INTERNAL_H_

#include <Security/Security.h>

#include <string>
#include <vector>

#include "base/time.h"
#include "crypto/apple_keychain.h"

using crypto::AppleKeychain;

// Adapter that wraps a AppleKeychain and provides interaction in terms of
// PasswordForms instead of Keychain items.
class MacKeychainPasswordFormAdapter {
 public:
  // Creates an adapter for |keychain|. This class does not take ownership of
  // |keychain|, so the caller must make sure that the keychain outlives the
  // created object.
  explicit MacKeychainPasswordFormAdapter(const AppleKeychain* keychain);

  // Returns PasswordForms for each keychain entry that could be used to fill
  // |form|. Caller is responsible for deleting the returned forms.
  std::vector<content::PasswordForm*> PasswordsFillingForm(
      const content::PasswordForm& query_form);

  // Returns PasswordForms for each keychain entry that could be merged with
  // |form|. Differs from PasswordsFillingForm in that the username must match.
  // Caller is responsible for deleting the returned forms.
  std::vector<content::PasswordForm*> PasswordsMergeableWithForm(
      const content::PasswordForm& query_form);

  // Returns the PasswordForm for the Keychain entry that matches |form| on all
  // of the fields that uniquely identify a Keychain item, or NULL if there is
  // no such entry.
  // Caller is responsible for deleting the returned form.
  content::PasswordForm* PasswordExactlyMatchingForm(
      const content::PasswordForm& query_form);

  // Returns true if PasswordsMergeableWithForm would return any items. This is
  // a separate method because calling PasswordsMergeableWithForm and checking
  // the return count would require reading the passwords from the keychain,
  // thus potentially triggering authorizaiton UI, whereas this won't.
  bool HasPasswordsMergeableWithForm(
      const content::PasswordForm& query_form);

  // Returns all keychain items of types corresponding to password forms.
  std::vector<content::PasswordForm*> GetAllPasswordFormPasswords();

  // Creates a new keychain entry from |form|, or updates the password of an
  // existing keychain entry if there is a collision. Returns true if a keychain
  // entry was successfully added/updated.
  bool AddPassword(const content::PasswordForm& form);

  // Removes the keychain password matching |form| if any. Returns true if a
  // keychain item was found and successfully removed.
  bool RemovePassword(const content::PasswordForm& form);

  // Controls whether or not Chrome will restrict Keychain searches to items
  // that it created. Defaults to false.
  void SetFindsOnlyOwnedItems(bool finds_only_owned);

 private:
  // Returns PasswordForms constructed from the given Keychain items, calling
  // AppleKeychain::Free on all of the keychain items and clearing the vector.
  // Caller is responsible for deleting the returned forms.
  std::vector<content::PasswordForm*> ConvertKeychainItemsToForms(
      std::vector<SecKeychainItemRef>* items);

  // Searches |keychain| for the specific keychain entry that corresponds to the
  // given form, and returns it (or NULL if no match is found). The caller is
  // responsible for calling AppleKeychain::Free on on the returned item.
  SecKeychainItemRef KeychainItemForForm(
      const content::PasswordForm& form);

  // Returns the Keychain items matching the given signon_realm, scheme, and
  // optionally path and username (either of both can be NULL).
  // The caller is responsible for calling AppleKeychain::Free on the
  // returned items.
  std::vector<SecKeychainItemRef> MatchingKeychainItems(
      const std::string& signon_realm,
      content::PasswordForm::Scheme scheme,
      const char* path,
      const char* username);

  // Takes a PasswordForm's signon_realm and parses it into its component parts,
  // which are returned though the appropriate out parameters.
  // Returns true if it can be successfully parsed, in which case all out params
  // that are non-NULL will be set. If there is no port, port will be 0.
  // If the return value is false, the state of the out params is undefined.
  bool ExtractSignonRealmComponents(const std::string& signon_realm,
                                    std::string* server, int* port,
                                    bool* is_secure,
                                    std::string* security_domain);

  // Returns the Keychain SecAuthenticationType type corresponding to |scheme|.
  SecAuthenticationType AuthTypeForScheme(
      content::PasswordForm::Scheme scheme);

  // Changes the password for keychain_item to |password|; returns true if the
  // password was successfully changed.
  bool SetKeychainItemPassword(const SecKeychainItemRef& keychain_item,
                               const std::string& password);

  // Sets the creator code of keychain_item to creator_code; returns true if the
  // creator code was successfully set.
  bool SetKeychainItemCreatorCode(const SecKeychainItemRef& keychain_item,
                                  OSType creator_code);

  // Returns the creator code to be used for a Keychain search, depending on
  // whether this object was instructed to search only for items it created.
  // If searches should be restricted in this way, the application-specific
  // creator code will be returned. Otherwise, 0 will be returned, indicating
  // a search of all items, regardless of creator.
  OSType CreatorCodeForSearch();

  const AppleKeychain* keychain_;

  // If true, Keychain searches are restricted to items created by Chrome.
  bool finds_only_owned_;

  DISALLOW_COPY_AND_ASSIGN(MacKeychainPasswordFormAdapter);
};

namespace internal_keychain_helpers {

// Sets the fields of |form| based on the keychain data from |keychain_item|.
// Fields that can't be determined from |keychain_item| will be unchanged.
//
// IMPORTANT: This function can cause the OS to trigger UI (to allow access to
// the keychain item if we aren't trusted for the item), and block until the UI
// is dismissed.
//
// If excessive prompting for access to other applications' keychain items
// becomes an issue, the password storage API will need to be refactored to
// allow the password to be retrieved later (accessing other fields doesn't
// require authorization).
bool FillPasswordFormFromKeychainItem(const AppleKeychain& keychain,
                                      const SecKeychainItemRef& keychain_item,
                                      content::PasswordForm* form);

// Returns true if the two given forms match based on signon_reaml, scheme, and
// username_value, and are thus suitable for merging (see MergePasswordForms).
bool FormsMatchForMerge(const content::PasswordForm& form_a,
                        const content::PasswordForm& form_b);

// Populates merged_forms by combining the password data from keychain_forms and
// the metadata from database_forms, removing used entries from the two source
// lists.
//
// On return, database_forms and keychain_forms will have only unused
// entries; for database_forms that means entries for which no corresponding
// password can be found (and which aren't blacklist entries), and for
// keychain_forms its entries that weren't merged into at least one database
// form.
void MergePasswordForms(
    std::vector<content::PasswordForm*>* keychain_forms,
    std::vector<content::PasswordForm*>* database_forms,
    std::vector<content::PasswordForm*>* merged_forms);

// Fills in the passwords for as many of the forms in |database_forms| as
// possible using entries from |keychain| and returns them. On return,
// |database_forms| will contain only the forms for which no password was found.
std::vector<content::PasswordForm*> GetPasswordsForForms(
    const AppleKeychain& keychain,
    std::vector<content::PasswordForm*>* database_forms);

}  // internal_keychain_helpers

#endif  // CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_STORE_MAC_INTERNAL_H_