From b625a739aed13426b48f03e4c3f89ddb913274f3 Mon Sep 17 00:00:00 2001 From: mationic Date: Sat, 3 Oct 2015 04:26:27 +0200 Subject: Adjustments for sqlite3 module (probably brakes mysql functionality). Added ca-bundle.pem. --- dbconf.py | 84 ++++++++++++++++++++++++++++++++++++----------------------- yubiserve.cfg | 4 +-- yubiserve.py | 63 +++++++++++++++++++++++++------------------- 3 files changed, 90 insertions(+), 61 deletions(-) diff --git a/dbconf.py b/dbconf.py index a0fe1af..e280b4c 100755 --- a/dbconf.py +++ b/dbconf.py @@ -7,7 +7,7 @@ try: except ImportError: pass try: - import sqlite + import sqlite3 as sqlite except ImportError: pass @@ -90,11 +90,13 @@ else: if (argv[1][2] == 'd') and (len(argv)>2): nickname = re.escape(argv[2]) cur.execute("SELECT * FROM yubikeys WHERE nickname = '" + nickname + "'") - if (cur.rowcount == 0): + rowcount = len(cur.fetchall()) + if (rowcount == 0): print 'Key not found.' else: cur.execute("SELECT * FROM yubikeys WHERE nickname = '" + nickname + "' AND active = '1'") - if (cur.rowcount == 1): + rowcount = len(cur.fetchall()) + if (rowcount == 1): cur.execute("UPDATE yubikeys SET active = '1' WHERE nickname = '" + nickname + "'") print "Key '" + nickname + "' disabled." con.commit() @@ -104,11 +106,13 @@ else: elif (argv[1][2] == 'e') and (len(argv)>2): nickname = re.escape(argv[2]) cur.execute("SELECT * FROM yubikeys WHERE nickname = '" + nickname + "'") - if (cur.rowcount == 0): + rowcount = len(cur.fetchall()) + if (rowcount == 0): print 'Key not found.' else: cur.execute("SELECT * FROM yubikeys WHERE nickname = '" + nickname + "' AND active = '1'") - if (cur.rowcount == 1): + rowcount = len(cur.fetchall()) + if (rowcount == 1): cur.execute("UPDATE yubikeys SET active = '1' WHERE nickname = '" + nickname + "'") print "Key '" + nickname + "' enabled." con.commit() @@ -117,7 +121,8 @@ else: elif (argv[1][2] == 'k') and (len(argv)>2): nickname = re.escape(argv[2]) cur.execute("SELECT * FROM yubikeys WHERE nickname = '" + nickname + "'") - if (cur.rowcount == 0): + rowcount = len(cur.fetchall()) + if (rowcount == 0): print 'Key not found.' else: cur.execute("DELETE FROM yubikeys WHERE nickname = '" + nickname + "'") @@ -127,7 +132,8 @@ else: nickname = re.escape(argv[2]) if ((len(argv[2])<=16) and (len(argv[3]) <= 16) and (len(argv[4]) <= 12) and (len(argv[5])<=32)): cur.execute("SELECT * FROM yubikeys WHERE nickname = '" + argv[2] + "' OR publicname = '" + argv[3] + "'") - if (cur.rowcount == 0): + rowcount = len(cur.fetchall()) + if (rowcount == 0): cur.execute("INSERT INTO yubikeys VALUES ('" + argv[2] + "', '" + argv[3] + "', '" + time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) + "', '" + argv[4] + "', '" + argv[5] + "', 1, 1, 1)") con.commit() print "Key '" + argv[2] + "' added to database." @@ -139,12 +145,14 @@ else: quit() elif (argv[1][2] == 'l'): cur.execute('SELECT nickname, publicname, active FROM yubikeys') - if cur.rowcount != 0: - print " " + str(cur.rowcount) + " keys into database:" + rows = cur.fetchall() + rowcount = len(rows) + if rowcount != 0: + print " " + str(rowcount) + " keys into database:" print '[Nickname]\t\t>> [PublicID]' - for i in range(0, cur.rowcount): - (nickname, publicname, active) = cur.fetchone() - print ' ' + nickname + ' ' * (23-len(nickname)) + ">> " + publicname + ' ' * (21-len(publicname)) + ">> " + active + for row in rows: + (nickname, publicname, active) = row + print ' ' + str(nickname) + ' ' * (23-len(nickname)) + ">> " + str(publicname) + ' ' * (21-len(publicname)) + ">> " + str(active) print '' else: print 'No keys in database\n' @@ -154,11 +162,13 @@ else: if (argv[1][2] == 'd') and (len(argv)>2): nickname = re.escape(argv[2]) cur.execute("SELECT * FROM oathtokens WHERE nickname = '" + nickname + "'") - if (cur.rowcount == 0): + rowcount = len(cur.fetchall()) + if (rowcount == 0): print 'Key not found.' else: cur.execute("SELECT * FROM oathtokens WHERE nickname = '" + nickname + "' AND active = '1'") - if (cur.rowcount == 1): + rowcount = len(cur.fetchall()) + if (rowcount == 1): cur.execute("UPDATE oathtokens SET active = '1' WHERE nickname = '" + nickname + "'") print "Key '" + nickname + "' disabled." con.commit() @@ -168,11 +178,13 @@ else: elif (argv[1][2] == 'e') and (len(argv)>2): nickname = re.escape(argv[2]) cur.execute("SELECT * FROM oathtokens WHERE nickname = '" + nickname + "'") - if (cur.rowcount == 0): + rowcount = len(cur.fetchall()) + if (rowcount == 0): print 'Key not found.' else: cur.execute("SELECT * FROM oathtokens WHERE nickname = '" + nickname + "' AND active = '1'") - if (cur.rowcount == 1): + rowcount = len(cur.fetchall()) + if (rowcount == 1): cur.execute("UPDATE oathtokens SET active = '1' WHERE nickname = '" + nickname + "'") print "Key '" + nickname + "' enabled." con.commit() @@ -181,7 +193,8 @@ else: elif (argv[1][2] == 'k') and (len(argv)>2): nickname = re.escape(argv[2]) cur.execute("SELECT * FROM oathtokens WHERE nickname = '" + nickname + "'") - if (cur.rowcount == 0): + rowcount = len(cur.fetchall()) + if (rowcount == 0): print 'Key not found.' else: cur.execute("DELETE FROM oathtokens WHERE nickname = '" + nickname + "'") @@ -191,7 +204,8 @@ else: nickname = re.escape(argv[2]) if (len(argv[2])<=16) and (len(argv[3]) <= 16) and (len(argv[4]) <= 40): cur.execute("SELECT * FROM oathtokens WHERE nickname = '" + argv[2] + "' OR publicname = '" + argv[3] + "'") - if (cur.rowcount == 0): + rowcount = len(cur.fetchall()) + if (rowcount == 0): cur.execute("INSERT INTO oathtokens VALUES ('" + nickname + "', '" + argv[3] + "', '" + time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) + "', '" + argv[4] + "', 1, 1)") con.commit() print "Key '" + argv[2] + "' added to database." @@ -203,12 +217,14 @@ else: quit() elif (argv[1][2] == 'l'): cur.execute('SELECT nickname, publicname FROM oathtokens') - if cur.rowcount != 0: - print " " + str(cur.rowcount) + " keys into database:" + rows = cur.fetchall() + rowcount = len(rows) + if rowcount != 0: + print " " + str(rowcount) + " keys into database:" print '[Nickname]\t\t>> [PublicID]' - for i in range(0, cur.rowcount): - (nickname, publicname) = cur.fetchone() - print ' ' + nickname + ' ' * (23-len(nickname)) + ">> " + publicname + for row in rows: + (nickname, publicname) = row + print ' ' + str(nickname) + ' ' * (23-len(nickname)) + ">> " + str(publicname) print '' else: print 'No keys in database\n' @@ -218,12 +234,14 @@ else: if (argv[1][2] == 'a') and (len(argv)>2): nickname = re.escape(argv[2]) cur.execute("SELECT * FROM apikeys WHERE nickname = '" + nickname + "'") - if (cur.rowcount != 0): + rowcount = len(cur.fetchall()) + if (rowcount != 0): print 'API Key for this nickname is already present. Remove it or choose another one.\n' quit() cur.execute('SELECT id FROM apikeys ORDER BY id DESC LIMIT 1') - if (cur.rowcount != 0): - id = cur.fetchone()[0] + 1 + rowcount = len(cur.fetchall()) + if (rowcount != 0): + id = cur.fetchall()[0][0] + 1 else: id = 1 api_key = randomChars(20) @@ -234,7 +252,8 @@ else: elif (argv[1][2] == 'k') and (len(argv)>2): nickname = re.escape(argv[2]) cur.execute("SELECT * FROM apikeys WHERE nickname = '" + nickname + "'") - if (cur.rowcount == 0): + rowcount = len(cur.fetchall()) + if (rowcount == 0): print "API Key for this nickname Doesn't exists!\n" quit() cur.execute("DELETE FROM apikeys WHERE nickname = '" + nickname + "'") @@ -242,12 +261,13 @@ else: print "API Key for '" + nickname + "' has been deleted.\n" elif (argv[1][2] == 'l'): cur.execute('SELECT nickname FROM apikeys') - if cur.rowcount != 0: - print ' ' + str(cur.rowcount) + ' keys into database:' + rows = cur.fetchall() + rowcount = len(rows) + if rowcount != 0: + print ' ' + str(rowcount) + ' keys into database:' print '[Nickname]' - for i in range(0, cur.rowcount): - nickname = cur.fetchone()[0] - print ' ' + nickname + for row in rows: + print ' ' + str(row[0]) print '' else: print 'No keys in database\n' diff --git a/yubiserve.cfg b/yubiserve.cfg index 06993bf..6ff8296 100644 --- a/yubiserve.cfg +++ b/yubiserve.cfg @@ -1,5 +1,5 @@ -yubiservePORT = 8000; -yubiserveSSLPORT = 8001; +yubiservePORT = 8700; +yubiserveSSLPORT = 8701; yubiserveHOST = '0.0.0.0'; yubiDB = 'sqlite'; #yubiDB = 'mysql'; diff --git a/yubiserve.py b/yubiserve.py index 704ed4c..0ada8bd 100755 --- a/yubiserve.py +++ b/yubiserve.py @@ -23,7 +23,7 @@ try: except ImportError: pass try: - import sqlite + import sqlite3 as sqlite except ImportError: pass @@ -126,10 +126,11 @@ class OTPValidation(): self.token = self.modhex2hex(match.group(2)) cur = self.con.cursor() cur.execute('SELECT aeskey, internalname FROM yubikeys WHERE publicname = "' + self.userid + '" AND active = "1"') - if (cur.rowcount != 1): + rows = cur.fetchall() + if (len(rows) != 1): self.validationResult = self.status['BAD_OTP'] return self.validationResult - (self.aeskey, self.internalname) = cur.fetchone() + (self.aeskey, self.internalname) = rows[0] self.plaintext = self.aes128ecb_decrypt(self.aeskey, self.token) uid = self.plaintext[:12] if (self.internalname != uid): @@ -141,10 +142,11 @@ class OTPValidation(): self.internalcounter = self.hexdec(self.plaintext[14:16] + self.plaintext[12:14] + self.plaintext[22:24]) self.timestamp = self.hexdec(self.plaintext[20:22] + self.plaintext[18:20] + self.plaintext[16:18]) cur.execute('SELECT counter, time FROM yubikeys WHERE publicname = "' + self.userid + '" AND active = "1"') - if (cur.rowcount != 1): + rows = cur.fetchall() + if (len(rows) != 1): self.validationResult = self.status['BAD_OTP'] return self.validationResult - (self.counter, self.time) = cur.fetchone() + (self.counter, self.time) = rows[0] if (self.counter) >= (self.internalcounter): self.validationResult = self.status['REPLAYED_OTP'] return self.validationResult @@ -168,7 +170,7 @@ class YubiServeHandler (BaseHTTPServer.BaseHTTPRequestHandler): global config #try: if config['yubiDB'] == 'sqlite': - con = sqlite.connect(os.path.dirname(os.path.realpath(__file__)) + '/yubikeys.sqlite') + con = sqlite.connect(os.path.dirname(os.path.realpath(__file__)) + '/yubikeys.sqlite', check_same_thread=False) elif config['yubiDB'] == 'mysql': con = MySQLdb.connect(host=config['yubiMySQLHost'], user=config['yubiMySQLUser'], passwd=config['yubiMySQLPass'], db=config['yubiMySQLName']) #except: @@ -217,22 +219,23 @@ class YubiServeHandler (BaseHTTPServer.BaseHTTPRequestHandler): self.end_headers() iso_time = time.strftime("%Y-%m-%dT%H:%M:%S") try: - result = 't=' + iso_time + '\r\notp=' + getData['otp'] + '\r\nnonce=' + getData['nonce'] + '\r\nsl=100\r\nstatus=' + [k for k, v in otpvalidation.status.iteritems() if v == validation][0] + '\r\n' - orderedResult = 'nonce=' + getData['nonce'] + '&otp=' + getData['otp'] + '&sl=100&status=' + [k for k, v in otpvalidation.status.iteritems() if v == validation][0] + '&t=' + iso_time + result = str('t=' + iso_time + '\r\notp=' + getData['otp'] + '\r\nnonce=' + getData['nonce'] + '\r\nsl=100\r\nstatus=' + [k for k, v in otpvalidation.status.iteritems() if v == validation][0] + '\r\n') + orderedResult = str('nonce=' + getData['nonce'] + '&otp=' + getData['otp'] + '&sl=100&status=' + [k for k, v in otpvalidation.status.iteritems() if v == validation][0] + '&t=' + iso_time) except KeyError: - result = 't=' + iso_time + '\r\notp=' + getData['otp'] + '\r\nnonce=\r\nsl=100\r\nstatus=' + [k for k, v in otpvalidation.status.iteritems() if v == validation][0] + '\r\n' - orderedResult = 'nonce=&otp=' + getData['otp'] + 'sl=100&status=' + [k for k, v in otpvalidation.status.iteritems() if v == validation][0] + '&t=' + iso_time + result = str('t=' + iso_time + '\r\notp=' + getData['otp'] + '\r\nnonce=\r\nsl=100\r\nstatus=' + [k for k, v in otpvalidation.status.iteritems() if v == validation][0] + '\r\n') + orderedResult = str('nonce=&otp=' + getData['otp'] + 'sl=100&status=' + [k for k, v in otpvalidation.status.iteritems() if v == validation][0] + '&t=' + iso_time) otp_hmac = '' try: if (getData['id'] != None): apiID = re.escape(getData['id']) cur = self.con.cursor() cur.execute("SELECT secret from apikeys WHERE id = '" + apiID + "'") - if cur.rowcount != 0: - api_key = cur.fetchone()[0] + rows = cur.fetchall() + if len(rows) != 0: + api_key = str(rows[0][0]) otp_hmac = hmac.new(api_key, msg=orderedResult, digestmod=hashlib.sha1).hexdigest().decode('hex').encode('base64').strip() else: - result = 't=' + iso_time + '\r\notp=' + getData['otp'] + '\r\nstatus=NO_CLIENT\r\n' + result = str('t=' + iso_time + '\r\notp=' + getData['otp'] + '\r\nstatus=NO_CLIENT\r\n') except KeyError: pass self.wfile.write('h=' + otp_hmac + '\r\n' + result + '\r\n') @@ -245,16 +248,17 @@ class YubiServeHandler (BaseHTTPServer.BaseHTTPRequestHandler): self.send_header('Content-type', 'text/plain') self.end_headers() iso_time = time.strftime("%Y-%m-%dT%H:%M:%S") - result = 't=' + iso_time + '\r\notp=\r\nnonce=\r\nstatus=MISSING_PARAMETER\r\n' - orderedResult = 'nonce=&otp=&status=MISSING_PARAMETER&t=' + iso_time + result = str('t=' + iso_time + '\r\notp=\r\nnonce=\r\nstatus=MISSING_PARAMETER\r\n') + orderedResult = str('nonce=&otp=&status=MISSING_PARAMETER&t=' + iso_time) otp_hmac = '' try: if (getData['id'] != None): apiID = re.escape(getData['id']) cur = self.con.cursor() cur.execute("SELECT secret from apikeys WHERE id = '" + apiID + "'") - if cur.rowcount != 0: - api_key = cur.fetchone()[0] + rows = cur.fetchall() + if len(rows) != 0: + api_key = str(rows[0][0]) otp_hmac = hmac.new(api_key, msg=orderedResult, digestmod=hashlib.sha1).hexdigest().decode('hex').encode('base64').strip() except KeyError: pass @@ -283,18 +287,19 @@ class YubiServeHandler (BaseHTTPServer.BaseHTTPRequestHandler): self.send_header('Content-type', 'text/plain') self.end_headers() iso_time = time.strftime("%Y-%m-%dT%H:%M:%S") - result = 'otp=' + getData['otp'] + '\r\nstatus=' + validation + '\r\nt=' + iso_time + result = str('otp=' + getData['otp'] + '\r\nstatus=' + validation + '\r\nt=' + iso_time) otp_hmac = '' try: if (getData['id'] != None): apiID = re.escape(getData['id']) cur = self.con.cursor() cur.execute("SELECT secret from apikeys WHERE id = '" + apiID + "'") - if cur.rowcount != 0: - api_key = cur.fetchone()[0] + rows = cur.fetchall() + if len(rows) != 0: + api_key = str(rows[0][0]) otp_hmac = hmac.new(api_key, msg=result, digestmod=hashlib.sha1).hexdigest().decode('hex').encode('base64').strip() else: - result = 'otp=' + getData['otp'] + '\r\nstatus=NO_CLIENT\r\nt=' + iso_time + result = str('otp=' + getData['otp'] + '\r\nstatus=NO_CLIENT\r\nt=' + iso_time) except KeyError: pass self.wfile.write(result + '\r\nh=' + otp_hmac) @@ -304,15 +309,16 @@ class YubiServeHandler (BaseHTTPServer.BaseHTTPRequestHandler): self.send_header('Content-type', 'text/plain') self.end_headers() iso_time = time.strftime("%Y-%m-%dT%H:%M:%S") - result = 'otp=\r\nstatus=BAD_OTP\r\nt=' + iso_time + result = str('otp=\r\nstatus=BAD_OTP\r\nt=' + iso_time) otp_hmac = '' try: if (getData['id'] != None): apiID = re.escape(getData['id']) cur = self.con.cursor() cur.execute("SELECT secret from apikeys WHERE id = '" + apiID + "'") - if cur.rowcount != 0: - api_key = cur.fetchone()[0] + rows = cur.fetchall() + if len(rows) != 0: + api_key = str(rows[0][0]) otp_hmac = hmac.new(api_key, msg=result, digestmod=hashlib.sha1).hexdigest().decode('hex').encode('base64').strip() except KeyError: pass @@ -324,15 +330,16 @@ class YubiServeHandler (BaseHTTPServer.BaseHTTPRequestHandler): self.send_header('Content-type', 'text/plain') self.end_headers() iso_time = time.strftime("%Y-%m-%dT%H:%M:%S") - result = 'otp=\r\nstatus=MISSING_PARAMETER\r\nt=' + iso_time + result = str('otp=\r\nstatus=MISSING_PARAMETER\r\nt=' + iso_time) otp_hmac = '' try: if (getData['id'] != None): apiID = re.escape(getData['id']) cur = self.con.cursor() cur.execute("SELECT secret from apikeys WHERE id = '" + apiID + "'") - if cur.rowcount != 0: - api_key = cur.fetchone()[0] + rows = cur.fetchall() + if len(rows) != 0: + api_key = str(rows[0][0]) otp_hmac = hmac.new(api_key, msg=result, digestmod=hashlib.sha1).hexdigest().decode('hex').encode('base64').strip() except KeyError: pass @@ -350,8 +357,10 @@ class SecureHTTPServer(BaseHTTPServer.HTTPServer): BaseHTTPServer.HTTPServer.__init__(self, server_address, HandlerClass) ctx = SSL.Context(SSL.SSLv23_METHOD) fpem = os.path.dirname(os.path.realpath(__file__)) + '/yubiserve.pem' + capem = os.path.dirname(os.path.realpath(__file__)) + '/ca-bundle.pem' ctx.use_privatekey_file (fpem) ctx.use_certificate_file(fpem) + ctx.load_verify_locations(capem) self.socket = SSL.Connection(ctx, socket.socket(self.address_family, self.socket_type)) self.server_bind() self.server_activate() -- cgit v1.2.3