File: database.h

package info (click to toggle)
golang-github-google-certificate-transparency 0.0~git20160709.0.0f6e3d1~ds1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, buster
  • size: 5,676 kB
  • sloc: cpp: 35,278; python: 11,838; java: 1,911; sh: 1,885; makefile: 950; xml: 520; ansic: 225
file content (167 lines) | stat: -rw-r--r-- 5,168 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#ifndef CERT_TRANS_LOG_DATABASE_H_
#define CERT_TRANS_LOG_DATABASE_H_

#include <glog/logging.h>
#include <stdint.h>
#include <functional>
#include <memory>
#include <set>

#include "base/macros.h"
#include "log/logged_entry.h"
#include "proto/ct.pb.h"

namespace cert_trans {

// This is a database interface for the log server.
//
// Implementations of this interface MUST provide for the same
// certificate being sequenced multiple times in the tree.
//
// Although the log server implementation which uses this database
// interface should not allow duplicate entries to be created, this
// code base will also support running in a log mirroring mode, and
// since the RFC does not forbid the same certificate appearing
// multiple times in a log 3rd party logs may exhibit this behavour
// the mirror must permit it too.


class ReadOnlyDatabase {
 public:
  typedef std::function<void(const ct::SignedTreeHead&)> NotifySTHCallback;

  enum LookupResult {
    LOOKUP_OK,
    NOT_FOUND,
  };

  class Iterator {
   public:
    Iterator() = default;
    virtual ~Iterator() = default;

    // If there is an entry available, fill *entry and return true,
    // otherwise return false.
    virtual bool GetNextEntry(LoggedEntry* entry) = 0;

   private:
    DISALLOW_COPY_AND_ASSIGN(Iterator);
  };

  virtual ~ReadOnlyDatabase() = default;

  // Look up by hash. If the entry exists write the result. If the
  // entry is not logged return NOT_FOUND.
  virtual LookupResult LookupByHash(const std::string& hash,
                                    LoggedEntry* result) const = 0;

  // Look up by sequence number.
  virtual LookupResult LookupByIndex(int64_t sequence_number,
                                     LoggedEntry* result) const = 0;

  // Return the tree head with the freshest timestamp.
  virtual LookupResult LatestTreeHead(ct::SignedTreeHead* result) const = 0;

  // Scan the entries, starting with the given index.
  virtual std::unique_ptr<Iterator> ScanEntries(int64_t start_index) const = 0;

  // Return the number of entries of contiguous entries (what could be
  // put in a signed tree head). This can be greater than the tree
  // size returned by LatestTreeHead.
  virtual int64_t TreeSize() const = 0;

  // Add/remove a callback to be called when a new tree head is
  // available. The pointer is used as a key, so it should be the same
  // in matching add/remove calls.
  //
  // When adding a callback, if we have a current tree head, it will
  // be called right away with that tree head.
  //
  // As a sanity check, all callbacks must be removed before the
  // database instance is destroyed.
  virtual void AddNotifySTHCallback(const NotifySTHCallback* callback) = 0;
  virtual void RemoveNotifySTHCallback(const NotifySTHCallback* callback) = 0;

  virtual void InitializeNode(const std::string& node_id) = 0;
  virtual LookupResult NodeId(std::string* node_id) = 0;

 protected:
  ReadOnlyDatabase() = default;

 private:
  DISALLOW_COPY_AND_ASSIGN(ReadOnlyDatabase);
};


class Database : public ReadOnlyDatabase {
 public:
  enum WriteResult {
    OK,
    // Create failed, certificate hash is primary key and must exist.
    MISSING_CERTIFICATE_HASH,
    // Create failed, an entry with this hash already exists.
    DUPLICATE_CERTIFICATE_HASH,
    // Update failed, entry does not exist.
    ENTRY_NOT_FOUND,
    // Another entry has this sequence number already.
    SEQUENCE_NUMBER_ALREADY_IN_USE,
    // Timestamp is primary key, it must exist and be unique,
    DUPLICATE_TREE_HEAD_TIMESTAMP,
    MISSING_TREE_HEAD_TIMESTAMP,
  };

  virtual ~Database() = default;

  // Attempt to create a new entry with the status LOGGED.
  // Fail if an entry with this hash already exists.
  WriteResult CreateSequencedEntry(const LoggedEntry& logged) {
    CHECK(logged.has_sequence_number());
    CHECK_GE(logged.sequence_number(), 0);
    return CreateSequencedEntry_(logged);
  }

  // Attempt to write a tree head. Fails only if a tree head with this
  // timestamp already exists (i.e., |timestamp| is primary key). Does
  // not check that the timestamp is newer than previous entries.
  WriteResult WriteTreeHead(const ct::SignedTreeHead& sth) {
    if (!sth.has_timestamp())
      return MISSING_TREE_HEAD_TIMESTAMP;
    return WriteTreeHead_(sth);
  }

 protected:
  Database() = default;

  // See the inline methods with similar names defined above for more
  // documentation.
  virtual WriteResult CreateSequencedEntry_(const LoggedEntry& logged) = 0;
  virtual WriteResult WriteTreeHead_(const ct::SignedTreeHead& sth) = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(Database);
};


class DatabaseNotifierHelper {
 public:
  typedef std::function<void(const ct::SignedTreeHead&)> NotifySTHCallback;

  DatabaseNotifierHelper() = default;
  ~DatabaseNotifierHelper();

  void Add(const NotifySTHCallback* callback);
  void Remove(const NotifySTHCallback* callback);
  void Call(const ct::SignedTreeHead& sth) const;

 private:
  typedef std::set<const NotifySTHCallback*> Map;

  Map callbacks_;

  DISALLOW_COPY_AND_ASSIGN(DatabaseNotifierHelper);
};


}  // namespace cert_trans

#endif  // CERT_TRANS_LOG_DATABASE_H_