1a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#!/usr/bin/env python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch# Authors:
4a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#   Trevor Perrin
5a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#   Martin von Loewis - python 3 port
6a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#
7a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch# See the LICENSE file for legal information regarding use of this file.
8a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
9a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochfrom __future__ import print_function
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import socket
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import math
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ != "__main__":
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise "This must be run as a command, not used as a module!"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochfrom tlslite import *
20a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochfrom tlslite import __version__
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if len(sys.argv) == 1 or (len(sys.argv)==2 and sys.argv[1].lower().endswith("help")):
23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("")
24a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("Version: %s" % __version__)
25a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("")
26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("RNG: %s" % prngName)
27a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("")
28a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("Modules:")
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if m2cryptoLoaded:
30a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        print("  M2Crypto    : Loaded")
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        print("  M2Crypto    : Not Loaded")
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if pycryptoLoaded:
34a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        print("  pycrypto    : Loaded")
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
36a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        print("  pycrypto    : Not Loaded")
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if gmpyLoaded:
38a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        print("  GMPY        : Loaded")
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
40a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        print("  GMPY        : Not Loaded")
41a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("")
42a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("Commands:")
43a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("")
44a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("  createsrp       <db>")
45a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("")
46a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("  add    <db> <user> <pass> [<bits>]")
47a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("  del    <db> <user>")
48a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("  check  <db> <user> [<pass>]")
49a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    print("  list   <db>")
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sys.exit()
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cmd = sys.argv[1].lower()
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Args:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self, argv):
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.argv = argv
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get(self, index):
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if len(self.argv)<=index:
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise SyntaxError("Not enough arguments")
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.argv[index]
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def getLast(self, index):
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if len(self.argv)>index+1:
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise SyntaxError("Too many arguments")
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.get(index)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)args = Args(sys.argv)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def reformatDocString(s):
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lines = s.splitlines()
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    newLines = []
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for line in lines:
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        newLines.append("  " + line.strip())
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "\n".join(newLines)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)try:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if cmd == "help":
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        command = args.getLast(2).lower()
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if command == "valid":
79a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            print("")
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
81a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            print("Bad command: '%s'" % command)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif cmd == "createsrp":
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbName = args.get(2)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        db = VerifierDB(dbName)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        db.create()
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif cmd == "add":
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbName = args.get(2)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        username = args.get(3)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        password = args.get(4)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
94a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        db = VerifierDB(dbName)
95a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        db.open()
96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        if username in db:
97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            print("User already in database!")
98a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            sys.exit()
99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        bits = int(args.getLast(5))
100a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        N, g, salt, verifier = VerifierDB.makeVerifier(username, password, bits)
101a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        db[username] = N, g, salt, verifier
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif cmd == "del":
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbName = args.get(2)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        username = args.getLast(3)
106a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        db = VerifierDB(dbName)
107a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        db.open()
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        del(db[username])
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif cmd == "check":
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbName = args.get(2)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        username = args.get(3)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if len(sys.argv)>=5:
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            password = args.getLast(4)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            password = None
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
118a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        db = VerifierDB(dbName)
119a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        db.open()
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            db[username]
123a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            print("Username exists")
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if password:
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if db.check(username, password):
127a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                    print("Password is correct")
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                else:
129a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                    print("Password is wrong")
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except KeyError:
131a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            print("Username does not exist")
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sys.exit()
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif cmd == "list":
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbName = args.get(2)
136a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        db = VerifierDB(dbName)
137a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        db.open()
138a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
139a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        print("Verifier Database")
140a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        def numBits(n):
141a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            if n==0:
142a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                return 0
143a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            return int(math.floor(math.log(n, 2))+1)
144a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        for username in db.keys():
145a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            N, g, s, v = db[username]
146a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            print(numBits(N), username)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
148a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        print("Bad command: '%s'" % cmd)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)except:
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise
151