Ejemplo n.º 1
0
  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')
Ejemplo n.º 2
0
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)