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