15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/webdata/token_service_table.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/os_crypt/os_crypt.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "components/webdata/common/web_database.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/statement.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebDatabaseTable::TypeKey GetKey() { 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We just need a unique constant. Use the address of a static that 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // COMDAT folding won't touch in an optimizing linker. 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static int table_key = 0; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return reinterpret_cast<void*>(&table_key); 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TokenServiceTable* TokenServiceTable::FromWebDatabase(WebDatabase* db) { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return static_cast<TokenServiceTable*>(db->GetTable(GetKey())); 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebDatabaseTable::TypeKey TokenServiceTable::GetTypeKey() const { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetKey(); 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 35effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool TokenServiceTable::CreateTablesIfNecessary() { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->DoesTableExist("token_service")) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute("CREATE TABLE token_service (" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "service VARCHAR PRIMARY KEY NOT NULL," 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "encrypted_token BLOB)")) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TokenServiceTable::IsSyncable() { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TokenServiceTable::MigrateToVersion(int version, 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* update_compatible_version) { 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TokenServiceTable::RemoveAllTokens() { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db_->GetUniqueStatement( 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "DELETE FROM token_service")); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s.Run(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool TokenServiceTable::RemoveTokenForService(const std::string& service) { 64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) sql::Statement s(db_->GetUniqueStatement( 65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "DELETE FROM token_service WHERE service = ?")); 66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) s.BindString(0, service); 67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return s.Run(); 69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TokenServiceTable::SetTokenForService(const std::string& service, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& token) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encrypted_token; 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool encrypted = OSCrypt::EncryptString(token, &encrypted_token); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!encrypted) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't bother with a cached statement since this will be a relatively 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // infrequent operation. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db_->GetUniqueStatement( 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INSERT OR REPLACE INTO token_service " 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "(service, encrypted_token) VALUES (?, ?)")); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindString(0, service); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindBlob(1, encrypted_token.data(), 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(encrypted_token.length())); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s.Run(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TokenServiceTable::GetAllTokens( 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<std::string, std::string>* tokens) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db_->GetUniqueStatement( 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT service, encrypted_token FROM token_service")); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!s.is_valid()) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (s.Step()) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encrypted_token; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string decrypted_token; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string service; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service = s.ColumnString(0); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool entry_ok = !service.empty() && 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.ColumnBlobAsString(1, &encrypted_token); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry_ok) { 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OSCrypt::DecryptString(encrypted_token, &decrypted_token); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*tokens)[service] = decrypted_token; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 116