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