From: mdw Date: Tue, 4 Oct 2005 19:30:46 +0000 (+0000) Subject: Weird. tripe-keys got backdates somewhere. X-Git-Tag: 1.0.0pre8~115 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/commitdiff_plain/c77687d5eff1c7f236b3b9e416ba2cac6952b7a8 Weird. tripe-keys got backdates somewhere. --- diff --git a/doc/tripe-keys.8 b/doc/tripe-keys.8 index 9055c87f..92b1aef2 100644 --- a/doc/tripe-keys.8 +++ b/doc/tripe-keys.8 @@ -36,17 +36,21 @@ tripe-keys \- simple centralized key management for tripe .B tripe-keys .I operation .IP "Operations supported:" -.B "help" +.BI "help \fR[" command \fR] +.br +.B "setup" +.br +.B "upload" .br .BI "generate " tag .br .B "update" .br -.B "rebuild" +.B "newmaster" .br -.B "setup" +.B "rebuild" .br -.B "upload" +.B "clean" .SH "DESCRIPTION" The .B tripe-keys @@ -131,7 +135,7 @@ Print brief usage about to standard output and exit successfully. .SS "Subcommands" .TP -.BI help\fR[ command \fR] +.BI "help \fR[" command \fR] With no arguments, shows help, as for the .B \-\-help option. With an argument, shows help about that diff --git a/tripe-keys.in b/tripe-keys.in index 099f27e8..97378671 100644 --- a/tripe-keys.in +++ b/tripe-keys.in @@ -8,17 +8,20 @@ import os as OS import sys as SYS import sre as RX import getopt as O +import shutil as SH +import filecmp as FC from cStringIO import StringIO from errno import * from stat import * ### Useful regular expressions -r_comment = RX.compile(r'^\s*(#|$)') -r_keyval = RX.compile(r'^\s*([-\w]+)(?:\s+(?!=)|\s*=\s*)(|\S|\S.*\S)\s*$') -r_dollarsubst = RX.compile(r'\$\{([-\w]+)\}') -r_atsubst = RX.compile(r'@([-\w]+)@') -r_nonalpha = RX.compile(r'\W') +rx_comment = RX.compile(r'^\s*(#|$)') +rx_keyval = RX.compile(r'^\s*([-\w]+)(?:\s+(?!=)|\s*=\s*)(|\S|\S.*\S)\s*$') +rx_dollarsubst = RX.compile(r'\$\{([-\w]+)\}') +rx_atsubst = RX.compile(r'@([-\w]+)@') +rx_nonalpha = RX.compile(r'\W') +rx_seq = RX.compile(r'\') ### Utility functions @@ -47,7 +50,7 @@ def subst(s, rx, map): def rmtree(path): try: - st = OS.stat(path) + st = OS.lstat(path) except OSError, err: if err.errno == ENOENT: return @@ -102,16 +105,16 @@ def fingerprint(kf, ktag): class ConfigFileError (Exception): pass conf = {} -def conf_subst(s): return subst(s, r_dollarsubst, conf) +def conf_subst(s): return subst(s, rx_dollarsubst, conf) ## Read the file def conf_read(f): lno = 0 for line in file(f): lno += 1 - if r_comment.match(line): continue + if rx_comment.match(line): continue if line[-1] == '\n': line = line[:-1] - match = r_keyval.match(line) + match = rx_keyval.match(line) if not match: raise ConfigFileError, "%s:%d: bad line `%s'" % (f, lno, line) k, v = match.groups() @@ -119,10 +122,12 @@ def conf_read(f): ## Sift the wreckage def conf_defaults(): - for k, v in [('sig-url', '${base-url}tripe-keys.sig'), - ('repos-url', '${base-url}tripe-keys.tar.gz'), - ('sig-file', '${base-dir}tripe-keys.sig'), - ('repos-file', '${base-dir}tripe-keys.tar.gz'), + for k, v in [('repos-base', 'tripe-keys.tar.gz'), + ('sig-base', 'tripe-keys.sig-'), + ('repos-url', '${base-url}${repos-base}'), + ('sig-url', '${base-url}${sig-base}'), + ('sig-file', '${base-dir}${sig-base}'), + ('repos-file', '${base-dir}${repos-base}'), ('conf-file', '${base-dir}tripe-keys.conf'), ('kx', 'dh'), ('kx-param', lambda: {'dh': '-LS -b2048 -B256', @@ -189,25 +194,41 @@ Subcommands available: func, min, max, help = commands[c] print '%s %s' % (c, help) -def cmd_setup(args): - OS.mkdir('repos') - - ## Generate the master key +def master_keys(): + if not OS.path.exists('master'): + return + for k in C.KeyFile('master'): + if (k.type != 'tripe-keys-master' or + k.expiredp or + not k.tag.startswith('master-')): + continue #?? + yield k +def master_sequence(k): + return int(k.tag[7:]) +def max_master_sequence(): + seq = -1 + for k in master_keys(): + q = master_sequence(k) + if q > seq: seq = q + return seq +def seqsubst(x, q): + return rx_seq.sub(str(q), conf[x]) + +def cmd_newmaster(args): + seq = max_master_sequence() + 1 run('''key -kmaster add -a${sig-genalg} !${sig-param} - -e${sig-expire} -l -ttripe-keys-master ccsig - sig=${sig} hash=${sig-hash}''') - run('key -kmaster extract -f-secret repos/master.pub tripe-keys-master') + -e${sig-expire} -l -tmaster-%d tripe-keys-master + sig=${sig} hash=${sig-hash}''' % seq) + run('key -kmaster extract -f-secret repos/master.pub') - ## Generate the parameters key +def cmd_setup(args): + OS.mkdir('repos') run('''key -krepos/param add -a${kx}-param !${kx-param} -eforever -tparam tripe-${kx}-param cipher=${cipher} hash=${hash} mac=${mac} mgf=${mgf}''') - - ## Get fingerprints - print 'Setup OK: master key = %s' % \ - hexhyphens(fingerprint('repos/master.pub', 'tripe-keys-master')) + cmd_newmaster(args) def cmd_upload(args): @@ -216,30 +237,49 @@ def cmd_upload(args): mode = 0666 & ~umask for f in OS.listdir('repos'): ff = OS.path.join('repos', f) - if f.endswith('.old'): + if (f.startswith('master') or f.startswith('peer-')) \ + and f.endswith('.old'): OS.unlink(ff) continue - OS.chmod(OS.path.join('repos', f), mode) - - ## Build the configuration file - v = {'HK-MASTER': hexhyphens(fingerprint('repos/master.pub', - 'tripe-keys-master'))} - fin = file('tripe-keys.master') - fout = file(conf_subst('${conf-file}.new'), 'w') - for line in fin: - fout.write(subst(line, r_atsubst, v)) - fin.close(); fout.close() - - ## Make and sign the repository archive - run('tar chozf ${repos-file}.new repos') - run('''catsign -kmaster sign -abdC -ktripe-keys-master - -o${sig-file}.new ${repos-file}.new''') - - ## Commit the changes - for i in ['conf-file', 'repos-file', 'sig-file']: - base = conf[i] - new = '%s.new' % base - OS.rename(new, base) + OS.chmod(ff, mode) + + rmtree('tmp') + OS.mkdir('tmp') + OS.symlink('../repos', 'tmp/repos') + cwd = OS.getcwd() + try: + + ## Build the configuration file + seq = max_master_sequence() + v = {'MASTER-SEQUENCE': str(seq), + 'HK-MASTER': hexhyphens(fingerprint('repos/master.pub', + 'master-%d' % seq))} + fin = file('tripe-keys.master') + fout = file('tmp/tripe-keys.conf', 'w') + for line in fin: + fout.write(subst(line, rx_atsubst, v)) + fin.close(); fout.close() + SH.copyfile('tmp/tripe-keys.conf', conf_subst('${conf-file}.new')) + commit = [conf['repos-file'], conf['conf-file']] + + ## Make and sign the repository archive + OS.chdir('tmp') + run('tar chozf ${repos-file}.new .') + OS.chdir(cwd) + for k in master_keys(): + seq = master_sequence(k) + sigfile = seqsubst('sig-file', seq) + run('''catsign -kmaster sign -abdC -kmaster-%d + -o%s.new ${repos-file}.new''' % (seq, sigfile)) + commit.append(sigfile) + + ## Commit the changes + for base in commit: + new = '%s.new' % base + OS.rename(new, base) + finally: + OS.chdir(cwd) + rmtree('tmp') def cmd_update(args): cwd = OS.getcwd() @@ -249,21 +289,25 @@ def cmd_update(args): ## Fetch a new distribution OS.mkdir('tmp') OS.chdir('tmp') + seq = int(conf['master-sequence']) run('wget -q -O tripe-keys.tar.gz ${repos-url}') - run('wget -q -O tripe-keys.sig ${sig-url}') + run('wget -q -O tripe-keys.sig %s' % seqsubst('sig-url', seq)) run('tar xfz tripe-keys.tar.gz') ## Verify the signature - want = C.bytes(r_nonalpha.sub('', conf['hk-master'])) - got = fingerprint('repos/master.pub', 'tripe-keys-master') + want = C.bytes(rx_nonalpha.sub('', conf['hk-master'])) + got = fingerprint('repos/master.pub', 'master-%d' % seq) if want != got: raise VerifyError - run('''catsign -krepos/master.pub verify -avC -ktripe-keys-master - -t${sig-fresh} tripe-keys.sig tripe-keys.tar.gz''') + run('''catsign -krepos/master.pub verify -avC -kmaster-%d + -t${sig-fresh} tripe-keys.sig tripe-keys.tar.gz''' % seq) ## OK: update our copy OS.chdir(cwd) if OS.path.exists('repos'): OS.rename('repos', 'repos.old') OS.rename('tmp/repos', 'repos') + if not FC.cmp('tmp/tripe-keys.conf', 'tripe-keys.conf'): + moan('configuration file changed: recommend running another update') + OS.rename('tmp/tripe-keys.conf', 'tripe-keys.conf') rmtree('repos.old') finally: @@ -283,25 +327,25 @@ def cmd_generate(args): zap('keyring'); zap(keyring_pub) run('key -kkeyring merge repos/param') run('key -kkeyring add -a${kx} -pparam -e${kx-expire} -t%s tripe-${kx}' % - (tag,)) - run('key -kkeyring extract -f-secret %s %s' % (keyring_pub, tag)) - print 'Generated %s key = %s' % \ - (tag, - hexhyphens(fingerprint('repos/master.pub', 'tripe-keys-master'))) - + tag) + run('key -kkeyring extract -f-secret %s' % keyring_pub) def cmd_clean(args): rmtree('repos') rmtree('tmp') - for i in 'master', 'keyring.pub': - zap(i) - zap('%s.old' % i) + for i in OS.listdir('.'): + r = i + if r.endswith('.old'): r = r[:-4] + if (r == 'master' or r == 'param' or + r == 'keyring' or r == 'keyring.pub' or r.startswith('peer-')): + zap(i) ### Main driver class UsageError (Exception): pass commands = {'help': (cmd_help, 0, 1, ''), + 'newmaster': (cmd_newmaster, 0, 0, ''), 'setup': (cmd_setup, 0, 0, ''), 'upload': (cmd_upload, 0, 0, ''), 'update': (cmd_update, 0, 0, ''),