def do(self): if 'otps' not in request.params or 'aes' not in request.params or 'mail' not in request.params : redirect_to(action="index", msg='All fields are requiered') if request.params['otps'] == '' or request.params['aes'] == '' or request.params['mail'] == '' : redirect_to(action='index', msg='All fields are requested') aes = request.params['aes'].strip() otps = request.params['otps'].strip().split('\n') mail = request.params['mail'].strip() # check: is this email already in our system ? if so, is the user registered? if so, are the email addresses the same ? c = Session.query(Key).filter(Key.email == mail) if c.count() != 0: if 'user' not in request.params: redirect_to(action='index', msg='This email address is already registered, please use the <a href="/manager">manager</a> to add this key.') pass if request.params['user'] != mail: redirect_to(action='index', msg = 'This is NOT your email address') pass # check how many OTPs there are if len(otps) < 3: redirect_to(action='index', msg='We need at least 3 OTPs') # check AES length if not yubi_decrypt.RE_AES_KEY.match(aes): redirect_to(action='index', msg='BAD AES Key') # check how many OTP there are for otp in otps: if otp: try: data = yubi_decrypt.YubikeyToken(otp.strip(), aes) except yubi_decrypt.InvalidToken: redirect_to(action="index", msg="Bad OTP - at least one is wrong!") secret_id = data.secret_id public_id = data.public_id # get API key if one already exists api = Session.query(Key).filter(Key.email == mail) if api.count() > 0: c.replay = True api_key = api[0].api.key else: c.replay = False api_key = generate_api() # crypt AES key crypted = xtea.crypt(self.xtea_key, aes).encode('hex') # last check : is this AES unique ? if Session.query(id_AES).filter(id_AES.aes == crypted).count() != 0: redirect_to(action="index", msg="Bad AES - Please generate a new one.") # create new key object key = Key() key.private_id = secret_id key.public_id = public_id key.email = mail # create new key - AES part new_aes = id_AES() new_aes.aes = crypted Session.add(new_aes) Session.commit() id_aes = Session.query(id_AES).filter(id_AES.aes == crypted).one().id # add ID to key key.id_aes = id_aes # create new key - API part if c.replay: key.api_key = api[0].api.id else: api = API() api.key = api_key Session.add(api) Session.commit() api_id = Session.query(API).filter(API.key == api_key).one().id key.api_key = api_id Session.add(key) Session.commit() c.api_key = api_key return render('/addkey/success.html')
def check_yubikey(otp, h, xtea_key,boolean=False): now = datetime.now() key_id = otp[0:12] yubi = Session.query(Key).filter(Key.public_id == key_id) if yubi.count() == 0: abort(404, "No key found!") yubik = yubi.one() xt = yubik.yubi_aes.aes.decode('hex') aes = xtea.crypt(xtea_key, xt) api_key = yubik.api.key # first of all: check signature if available if h and not yubisign_check(api_key, 'otp=%s'%otp, h): if boolean: return False else: abort(203, 'Bad signature') try: data = yubi_decrypt.YubikeyToken(otp, aes) except yubi_decrypt.InvalidAESKey: if boolean: return False else: abort(203, 'Invalid AES') except yubi_decrypt.InvalidToken: if boolean: return False else: output = '''status=BAD_OTP t=%s''' % now sign = yubisign(api_key, output) return '%s\nh=%s' % (output, sign) if data.secret_id != yubik.private_id: if boolean: return False else: abort(203, '''It seems your key is the wrong one. Private IDs don't match!''') counter = data.counter + data.counter_session if counter <= yubik.increment: if boolean: return False else: output = '''status=REPLAYED_OTP t=%s''' % now sign = yubisign(api_key, output) return '%s\nh=%s' % (output, sign) # ok, checks are done, all is green # let' update yubi for the increment part: take increment value from yubikey, and insert it yubik.increment = counter Session.flush() Session.commit() if boolean: return yubik output = '''status=OK t=%s''' % now sign = yubisign(api_key, output) return '%s\nh=%s' % (output, sign)