nss_decryptor.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/importer/nss_decryptor.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector>
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/scoped_ptr.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "build/build_config.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/sqlite_utils.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(USE_NSS)
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <pk11pub.h>
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <pk11sdr.h>
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif  // defined(USE_NSS)
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/base64.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/password_form.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing webkit_glue::PasswordForm;
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This method is based on some Firefox code in
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   security/manager/ssl/src/nsSDR.cpp
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The license block is:
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* ***** BEGIN LICENSE BLOCK *****
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* Version: MPL 1.1/GPL 2.0/LGPL 2.1
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch*
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* The contents of this file are subject to the Mozilla Public License Version
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* 1.1 (the "License"); you may not use this file except in compliance with
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* the License. You may obtain a copy of the License at
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* http://www.mozilla.org/MPL/
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch*
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* Software distributed under the License is distributed on an "AS IS" basis,
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* for the specific language governing rights and limitations under the
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* License.
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch*
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* The Original Code is the Netscape security libraries.
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch*
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* The Initial Developer of the Original Code is
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* Netscape Communications Corporation.
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* Portions created by the Initial Developer are Copyright (C) 1994-2000
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* the Initial Developer. All Rights Reserved.
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch*
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* Contributor(s):
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch*
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* Alternatively, the contents of this file may be used under the terms of
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* either the GNU General Public License Version 2 or later (the "GPL"), or
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* in which case the provisions of the GPL or the LGPL are applicable instead
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* of those above. If you wish to allow use of your version of this file only
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* under the terms of either the GPL or the LGPL, and not to allow others to
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* use your version of this file under the terms of the MPL, indicate your
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* decision by deleting the provisions above and replace them with the notice
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* and other provisions required by the GPL or the LGPL. If you do not delete
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* the provisions above, a recipient may use your version of this file under
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* the terms of any one of the MPL, the GPL or the LGPL.
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch*
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch* ***** END LICENSE BLOCK ***** */
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstring16 NSSDecryptor::Decrypt(const std::string& crypt) const {
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Do nothing if NSS is not loaded.
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!is_nss_initialized_)
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return string16();
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The old style password is encoded in base64. They are identified
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // by a leading '~'. Otherwise, we should decrypt the text.
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string plain;
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (crypt[0] != '~') {
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string decoded_data;
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::Base64Decode(crypt, &decoded_data);
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PK11SlotInfo* slot = GetKeySlotForDB();
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SECStatus result = PK11_Authenticate(slot, PR_TRUE, NULL);
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (result != SECSuccess) {
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      FreeSlot(slot);
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return string16();
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SECItem request;
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    request.data = reinterpret_cast<unsigned char*>(
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        const_cast<char*>(decoded_data.data()));
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    request.len = static_cast<unsigned int>(decoded_data.size());
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SECItem reply;
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    reply.data = NULL;
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    reply.len = 0;
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(USE_NSS)
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    result = PK11SDR_DecryptWithSlot(slot, &request, &reply, NULL);
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    result = PK11SDR_Decrypt(&request, &reply, NULL);
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif  // defined(USE_NSS)
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (result == SECSuccess)
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      plain.assign(reinterpret_cast<char*>(reply.data), reply.len);
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SECITEM_FreeItem(&reply, PR_FALSE);
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FreeSlot(slot);
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Deletes the leading '~' before decoding.
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::Base64Decode(crypt.substr(1), &plain);
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return UTF8ToUTF16(plain);
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// There are three versions of password files. They store saved user
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// names and passwords.
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// References:
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// http://kb.mozillazine.org/Signons.txt
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// http://kb.mozillazine.org/Signons2.txt
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// http://kb.mozillazine.org/Signons3.txt
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid NSSDecryptor::ParseSignons(const std::string& content,
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                std::vector<PasswordForm>* forms) {
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  forms->clear();
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Splits the file content into lines.
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<std::string> lines;
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SplitString(content, '\n', &lines);
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The first line is the file version. We skip the unknown versions.
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (lines.empty())
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int version;
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (lines[0] == "#2c")
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    version = 1;
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else if (lines[0] == "#2d")
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    version = 2;
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else if (lines[0] == "#2e")
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    version = 3;
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL::Replacements rep;
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rep.ClearQuery();
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rep.ClearRef();
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rep.ClearUsername();
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rep.ClearPassword();
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Reads never-saved list. Domains are stored one per line.
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t i;
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (i = 1; i < lines.size() && lines[i].compare(".") != 0; ++i) {
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm form;
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.origin = GURL(lines[i]).ReplaceComponents(rep);
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.signon_realm = form.origin.GetOrigin().spec();
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.blacklisted_by_user = true;
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    forms->push_back(form);
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ++i;
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Reads saved passwords. The information is stored in blocks
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // seperated by lines that only contain a dot. We find a block
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // by the seperator and parse them one by one.
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (i < lines.size()) {
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_t begin = i;
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_t end = i + 1;
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    while (end < lines.size() && lines[end].compare(".") != 0)
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ++end;
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    i = end + 1;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // A block has at least five lines.
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (end - begin < 5)
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      continue;
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm form;
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The first line is the site URL.
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // For HTTP authentication logins, the URL may contain http realm,
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // which will be in bracket:
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    //   sitename:8080 (realm)
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GURL url;
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string realm;
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char kRealmBracketBegin[] = " (";
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char kRealmBracketEnd[] = ")";
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (lines[begin].find(kRealmBracketBegin) != std::string::npos) {
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // In this case, the scheme may not exsit. We assume that the
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // scheme is HTTP.
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (lines[begin].find("://") == std::string::npos)
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        lines[begin] = "http://" + lines[begin];
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      size_t start = lines[begin].find(kRealmBracketBegin);
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      url = GURL(lines[begin].substr(0, start));
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      start += std::string(kRealmBracketBegin).size();
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      size_t end = lines[begin].rfind(kRealmBracketEnd);
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      realm = lines[begin].substr(start, end - start);
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Don't have http realm. It is the URL that the following passwords
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // belong to.
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      url = GURL(lines[begin]);
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Skips this block if the URL is not valid.
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!url.is_valid())
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      continue;
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.origin = url.ReplaceComponents(rep);
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.signon_realm = form.origin.GetOrigin().spec();
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!realm.empty())
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      form.signon_realm += realm;
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.ssl_valid = form.origin.SchemeIsSecure();
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ++begin;
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // There may be multiple username/password pairs for this site.
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // In this case, they are saved in one block without a seperated
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // line (contains a dot).
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    while (begin + 4 < end) {
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // The user name.
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      form.username_element = UTF8ToUTF16(lines[begin++]);
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      form.username_value = Decrypt(lines[begin++]);
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // The element name has a leading '*'.
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (lines[begin].at(0) == '*') {
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        form.password_element = UTF8ToUTF16(lines[begin++].substr(1));
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        form.password_value = Decrypt(lines[begin++]);
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // Maybe the file is bad, we skip to next block.
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // The action attribute from the form element. This line exists
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // in versin 2 or above.
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (version >= 2) {
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (begin < end)
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          form.action = GURL(lines[begin]).ReplaceComponents(rep);
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ++begin;
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Version 3 has an extra line for further use.
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (version == 3) {
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ++begin;
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      forms->push_back(form);
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool NSSDecryptor::ReadAndParseSignons(const FilePath& sqlite_file,
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<webkit_glue::PasswordForm>* forms) {
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sqlite3* sqlite;
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sqlite_utils::OpenSqliteDb(sqlite_file, &sqlite) != SQLITE_OK)
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sqlite_utils::scoped_sqlite_db_ptr db(sqlite);
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SQLStatement s;
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* stmt = "SELECT hostname FROM moz_disabledHosts";
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (s.prepare(db.get(), stmt) != SQLITE_OK)
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL::Replacements rep;
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rep.ClearQuery();
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rep.ClearRef();
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rep.ClearUsername();
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rep.ClearPassword();
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Read domains for which passwords are never saved.
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (s.step() == SQLITE_ROW) {
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm form;
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.origin = GURL(s.column_string(0)).ReplaceComponents(rep);
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.signon_realm = form.origin.GetOrigin().spec();
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.blacklisted_by_user = true;
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    forms->push_back(form);
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SQLStatement s2;
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* stmt2 = "SELECT hostname, httpRealm, formSubmitURL, "
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      "usernameField, passwordField, encryptedUsername, "
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      "encryptedPassword FROM moz_logins";
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (s2.prepare(db.get(), stmt2) != SQLITE_OK)
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (s2.step() == SQLITE_ROW) {
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GURL url;
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string realm(s2.column_string(1));
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!realm.empty()) {
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // In this case, the scheme may not exsit. Assume HTTP.
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::string host(s2.column_string(0));
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (host.find("://") == std::string::npos)
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        host = "http://" + host;
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      url = GURL(host);
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      url = GURL(s2.column_string(0));
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Skip this row if the URL is not valid.
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!url.is_valid())
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      continue;
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm form;
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.origin = url.ReplaceComponents(rep);
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.signon_realm = form.origin.GetOrigin().spec();
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!realm.empty())
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      form.signon_realm += realm;
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.ssl_valid = form.origin.SchemeIsSecure();
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The user name, password and action.
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.username_element = UTF8ToUTF16(s2.column_string(3));
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.username_value = Decrypt(s2.column_string(5));
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.password_element = UTF8ToUTF16(s2.column_string(4));
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.password_value = Decrypt(s2.column_string(6));
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.action = GURL(s2.column_string(2)).ReplaceComponents(rep);
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    forms->push_back(form);
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
302