3 # Licensed to the Apache Software Foundation (ASF) under one or more
4 # contributor license agreements. See the NOTICE file distributed with
5 # this work for additional information regarding copyright ownership.
6 # The ASF licenses this file to You under the Apache License, Version 2.0
7 # (the "License"); you may not use this file except in compliance with
8 # the License. You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
24 def create_tables(db_name):
25 cxn = sqlite3.connect(db_name)
29 'CREATE TABLE loginfo('
30 + 'id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, '
32 + 'public_key TEXT, ' # path to PEM-encoded file
33 + 'distrusted INTEGER, ' # non-zero if not trusted
34 + 'min_valid_timestamp INTEGER, '
35 + 'max_valid_timestamp INTEGER, '
43 def record_id_arg(cur, args, required=False):
44 if len(args) < 1 or args[0][0] != '#' or len(args[0]) < 2:
46 print >> sys.stderr, 'A record id was not provided'
49 record_id = args.pop(0)[1:]
50 stmt = 'SELECT * FROM loginfo WHERE id = ?'
51 cur.execute(stmt, [record_id])
52 recs = list(cur.fetchall())
55 print >> sys.stderr, 'Record #%s was not found' % record_id
60 def log_id_arg(cur, args, required=True):
61 if len(args) < 1 or len(args[0]) != 64:
64 print >> sys.stderr, 'A log id was not provided'
66 log_id = args.pop(0).upper()
67 if len(re.compile(r'[A-Z0-9]').findall(log_id)) != len(log_id):
68 print >> sys.stderr, 'The log id is not formatted properly'
73 def public_key_arg(args):
75 print >> sys.stderr, 'A public key file was not provided'
78 if not os.path.exists(pubkey):
79 print >> sys.stderr, 'Public key file %s could not be read' % pubkey
86 print >> sys.stderr, 'A timestamp was not provided'
98 if bad_val or val < 1:
99 print >> sys.stderr, 'The timestamp "%s" is invalid' % t
105 def configure_public_key(cur, args):
106 record_id = record_id_arg(cur, args, False)
107 public_key = public_key_arg(args)
111 stmt = 'INSERT INTO loginfo (public_key) VALUES(?)'
112 cur.execute(stmt, [public_key])
114 stmt = 'UPDATE loginfo SET public_key = ? WHERE id = ?'
115 cur.execute(stmt, [public_key, record_id])
118 def configure_url(cur, args):
119 # can't specify more than one of record-id and log-id
121 record_id = record_id_arg(cur, args, False)
123 log_id = log_id_arg(cur, args, False)
129 stmt = 'UPDATE loginfo SET url = ? WHERE id = ?'
130 args = [url, record_id]
132 stmt = 'INSERT INTO loginfo (log_id, url) VALUES(?, ?)'
135 stmt = 'INSERT INTO loginfo (url) VALUES(?)'
138 cur.execute(stmt, args)
141 def forget_log(cur, args):
142 record_id = record_id_arg(cur, args, False)
145 log_id = log_id_arg(cur, args, True)
149 stmt = 'DELETE FROM loginfo WHERE id = ?'
152 stmt = 'DELETE FROM loginfo WHERE log_id = ?'
154 cur.execute(stmt, args)
157 def trust_distrust_log(cur, args):
158 # could take a record id or a log id
159 record_id = record_id_arg(cur, args, False)
163 log_id = log_id_arg(cur, args)
170 stmt = 'INSERT INTO loginfo (log_id, distrusted) VALUES(?, ?)'
171 cur.execute(stmt, [log_id, flag])
173 stmt = 'UPDATE loginfo SET distrusted = ? WHERE id = ?'
174 cur.execute(stmt, [flag, record_id])
177 def trust_log(cur, args):
178 trust_distrust_log(cur, args + [0])
181 def distrust_log(cur, args):
182 trust_distrust_log(cur, args + [1])
185 def time_range(cur, args):
186 # could take a record id or a log id
187 record_id = record_id_arg(cur, args, False)
191 log_id = log_id_arg(cur, args)
193 min_valid_time = time_arg(args)
194 max_valid_time = time_arg(args)
198 stmt = 'INSERT INTO loginfo ' + \
199 '(log_id, min_valid_timestamp, max_valid_timestamp) ' + \
201 cur.execute(stmt, [log_id, min_valid_time, max_valid_time])
203 stmt = 'UPDATE loginfo SET min_valid_timestamp = ?, ' + \
204 'max_valid_timestamp = ? WHERE id = ?'
205 cur.execute(stmt, [min_valid_time, max_valid_time, record_id])
214 stmt = 'SELECT * FROM loginfo'
217 for row in cur.fetchall():
221 obj.public_key = row[2]
222 obj.distrusted = row[3]
223 obj.min_valid_timestamp = row[4]
224 obj.max_valid_timestamp = row[5]
235 not_conf = '(not configured)'
238 str(rec.min_valid_timestamp) if rec.min_valid_timestamp else '-INF'
240 str(rec.max_valid_timestamp) if rec.max_valid_timestamp else '+INF'
242 print ' Record ' + str(rec.id) + \
243 (' (DISTRUSTED)' if rec.distrusted else '')
244 print ' Log id : ' + (rec.log_id if rec.log_id else not_conf)
245 print ' Public key file: ' + \
246 (rec.public_key if rec.public_key else not_conf)
247 print ' URL : ' + (rec.url if rec.url else not_conf)
248 print ' Time range : ' + mint + ' to ' + maxt
253 help = """Usage: %s /path/to/log-config-db command args
256 display config-db contents:
258 configure public key:
259 configure-public-key [log-id|record-id] /path/log-pub-key.pem
261 configure-url [log-id|record-id] http://www.example.com/path/
262 configure min and/or max valid timestamps:
263 valid-time-range log-id|record-id min-range max-range
264 mark log as trusted (default):
265 trust log-id|record-id
266 mark log as untrusted:
267 distrust log-id|record-id
268 remove log config from config-db:
269 forget log-id|record-id
271 log-id is a 64-character hex string representation of a log id
273 record-id references an existing entry and is in the form:
275 (displayable with the dump command)
277 print >> sys.stderr, help
289 cmds = {'configure-public-key': configure_public_key,
290 'configure-url': configure_url,
291 'distrust': distrust_log,
293 'forget': forget_log,
294 'valid-time-range': time_range,
298 cmds_requiring_db = ['dump', 'forget'] # db must already exist
303 if not os.path.exists(db_name):
304 if not cmd in cmds_requiring_db:
305 create_tables(db_name)
307 print >> sys.stderr, 'Database "%s" does not exist' % db_name
310 cxn = sqlite3.connect(db_name)
319 if __name__ == "__main__":