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