Exemple #1
0
  def testNoCreds(self):
    """authenticate() a user with no creds"""
    user = Prototype()
    user.username = '******'
    user.nonce = 'y'
    user.nextnonce = 'z'

    def callback(u):
      assert False, 'Callback called in MISSING_CREDS'

    user = pychap.authenticate(callback, user)

    # nonce
    self.assertEqual(user.nonce, 'y')

    #nextnonce
    self.assertEqual(user.nextnonce, 'z')

    #passkey
    self.assertEqual(getattr(user, 'passkey', None), None)

    #authenticated
    self.assertEqual(user.authenticated, False)

    #authmessage
    self.assertEqual(user.message, pychap.MISSING_CREDS)
Exemple #2
0
  def testPasskey(self):
    """user is not authenticated"""
    user = Prototype()
    user.username = '******'
    user.nonce = 'x'
    user.nextnonce = 'x'
    user.cnonce = 'x'
    user.response = 'x'
    user.passkey = 'x'

    def callback(u):
      assert False, 'Callback called in MISSING_CREDS'

    user = pychap.authenticate(callback, user)

    # nonce
    self.assertEqual(user.nonce, 'x')

    #nextnonce
    self.assertEqual(user.nextnonce, 'x')

    #passkey
    self.assertEqual(user.passkey, 'x')

    #authenticated
    self.assertEqual(user.authenticated, False)

    #authmessage
    self.assertEqual(user.message, pychap.DENIED)
Exemple #3
0
  def testWithoutModifiedPasskey(self):
    """authenticate() a user without a modified passkey"""
    nonce = 'a_nonce'
    nextnonce = 'a_nextnonce'
    response = hashlib.sha1(nonce).hexdigest()
    cnonce = hashlib.sha1(
      hashlib.sha1(nextnonce).hexdigest()).hexdigest()
    user = Prototype()
    user.username = '******'
    user.nonce = nonce
    user.nextnonce = nextnonce
    user.cnonce = cnonce
    user.response = response
    user.passkey = 'y'

    def callback(u):
      assert False, 'Callback called in MISSING_CREDS'

    user = pychap.authenticate(callback, user)

    # nonce
    self.assertEqual(user.nonce, nonce)

    #nextnonce
    self.assertEqual(user.nextnonce, nextnonce)

    #passkey
    self.assertEqual(user.passkey, 'y') 

    #authenticated
    self.assertEqual(user.authenticated, False)

    #authmessage
    self.assertEqual(user.message, pychap.UNMODIFIED)
Exemple #4
0
  def d3_put(self, request, credentials, match):
    # A call to the "/users/" URL without a username is pointless.
    if not match: # match could be ''
      self.message_out(501,
          'The URL \\"/users/\\" is not implemented on this host.')
      return

    target_user = BaseUser.get(match)
    if target_user is None:
      # If the user does not exist, we assume the caller intended to create a new
      # one.
      target_user = BaseUser(match)
      new_user = pychap.authenticate(store.put_user, target_user)
      return self.out(status=201, message='Created.',
          creds=new_user.credentials,
          body={'username': new_user.username})

    # Otherwise we assume the caller is trying to update this user's data, so we
    # try to authenticate.
    creds = authenticate(credentials)
    auth_user = BaseUser.get(creds[0])

    # It is wrong to assume that we are existing in a magic pony land where all
    # the planets line up prefectly and our programs are bug free.  In this
    # case, if we don't make this seemingly meaningless assigment of one user
    # object to another, then when a user updates their own data, really bad
    # shit happens to our authentication scheme.
    if target_user.username == auth_user.username:
      target_user = auth_user

    # The first thing we need to do is check to see if the caller is trying to
    # update the permission level group membership.
    new_groups = request.get('groups')
    if new_groups != target_user.groups and isinstance(new_groups, list):
      # Define a function to use with the builtin 'reduce()' to determine the
      # permission level of the calling user.
      def reduce_level(current_level, group):
        if groups.MAP[group] > current_level:
          current_level = groups.MAP[group]
        return current_level

      level = reduce(reduce_level, auth_user.groups, 0)

      # Once we have the permission level of the calling user, we can then check
      # all of the modifications they have indicated that they want to make.
      for g in new_groups:
        if g in target_user.groups:
          continue # The user already belongs to this group.
        group_level = groups.MAP.get(g)
        if group_level is None:
          continue # The group does not exist.
        if group_level > level:
          continue # The user does not have permission for this group.
        # Else add the user to the group.
        target_user.groups.append(g)

    target_user.put()
    self.out(status=200, message='Updated.',
        creds=creds,
        body={'username': target_user.username, 'groups': target_user.groups})
Exemple #5
0
 def testNewUser(self):
   """authenticate() a new user (no nonce or nextnonce)"""
   user = Prototype()
   user.someother = 1
   user.username = '******'
   self.assertEqual(
       pychap.authenticate(self.callback, user),
       self.user)
Exemple #6
0
 def testSetPasskey(self):
   """authenticate() a user with no passkey"""
   user = Prototype()
   user.username = '******'
   user.nonce = 'a'
   user.nextnonce = 'b'
   user.cnonce = 'c'
   user.response = 'd'
   self.assertEqual(pychap.authenticate(self.callback, user),
       self.user)
Exemple #7
0
def main():
  TEMP_TEST_USERNAME = '******'

  http_method = os.environ['REQUEST_METHOD']

  if http_method == 'GET':
    respond('200 OK', TEMP_TEST_USERNAME)
    return

  # Check to see if we are on the local dev_appserver.
  # If not, we bail!
  if not os.environ['SERVER_SOFTWARE'].startswith('Development'):
    respond('403 Forbidden','')
    return

  logging.critical('/testsetup has been accessed')

  import store
  user = store.BaseUser.get(TEMP_TEST_USERNAME)

  if http_method == 'PUT':
    if user is None:
      user = store.BaseUser(TEMP_TEST_USERNAME)
      user.groups = [
             'users',
             'sys_admin',
             'user_admin',
             'account_admin',
             'database']
      import pychap
      pychap.authenticate(store.put_user, user)

    respond('200 OK', TEMP_TEST_USERNAME)

  elif http_method == 'DELETE':
    if user is not None:
      user.delete()
    respond('204 No Content', '')

  else:
    respond('405 Method Not Allowed','')
Exemple #8
0
 def testNewUser(self):
   """user authenticates"""
   user = Prototype()
   user.username = u'a'
   user.nonce = u'b'
   user.nextnonce = u'c'
   user.cnonce = u'd'
   user.response = u'e'
   user.passkey = u'58e6b3a414a1e090dfc6029add0f3555ccba127f'
   self.assertEqual(
       pychap.authenticate(self.callback, user),
       self.user)
Exemple #9
0
  def testInvalidPasskey(self):
    """invalid passkey"""
    user = Prototype()
    user.username = '******'
    user.nonce = 'x'
    user.nextnonce = 'x'
    user.cnonce = 'x'
    user.response = 'x'
    user.passkey = []

    def callback(u):
      assert False, 'Callback called in MISSING_CREDS'

    ex = False
    try:
      user = pychap.authenticate(callback, user)
    except AssertionError, ae:
      ex = ae
Exemple #10
0
  def testInvalidParams(self):
    """Invalid Params."""
    ex = False
    try:
      pychap.authenticate(None)
    except TypeError:
      ex = True
    assert ex, 'params (None) raises exception.'

    ex = False
    try:
      pychap.authenticate((lambda : None))
    except TypeError:
      ex = True
    assert ex, 'params (lambda, None) raises exception.'

    ex = False
    try:
      pychap.authenticate((lambda : None), 1)
    except AssertionError:
      ex = True
    assert ex, 'params (lambda, 1) raises exception.'

    user = Prototype()
    user.nonce = 4
    ex = False
    try:
      pychap.authenticate((lambda : None), user)
    except AssertionError:
      ex = True
    assert ex, 'params (lambda, "", 4) raises exception.'

    user = Prototype()
    user.username = '******'
    user.nonce = 4
    ex = False
    try:
      pychap.authenticate((lambda : None), user)
    except AssertionError:
      ex = True
    assert ex, 'params (lambda, "", 4) raises exception.'

    user = Prototype()
    user.username = '******'
    user.nonce = ''
    user.nextnonce = 99
    ex = False
    try:
      pychap.authenticate((lambda : None), user)
    except AssertionError:
      ex = True
    assert ex, 'params (lambda, "", "", "") raises exception.'

    user = Prototype()
    user.username = '******'
    user.nonce = 'x'
    user.nextnonce = 'x'
    user.cnonce = 1
    ex = False
    try:
      pychap.authenticate((lambda : None), user)
    except AssertionError:
      ex = True
    assert ex, 'params (lambda, "", "", False) raises exception.'

    user = Prototype()
    user.username = '******'
    user.nonce = 'x'
    user.nextnonce = 'x'
    user.cnonce = 'x'
    user.response = [1]
    ex = False
    try:
      pychap.authenticate((lambda : None), user)
    except AssertionError:
      ex = True
    assert ex, 'params (lambda, []) raises exception.'
Exemple #11
0
def authenticate(creds):
  """Take the CHAP credentials of a user and try to authenticate.

  Args:
    creds: A list of credentials: username, cnonce, response
  Returns:
    A list of username, nonce, and nextnonce if the user authenticates.

  Raises:
    AuthenticationError: If the credentials are invalid.
    Authenticate: If the credentials are incomplete or the response does not
    match the stored passkey.

  """

  # If the DCube head dictionary does not have an 'authorization' entry, then
  # we asign it an empty list by default. This is to prevent bugs later in
  # the program where a list object is expected.
  creds = creds or []

  # Make sure the credentials object is a list with more than 1 entry. If we
  # don't even have a single item in the credentials list, there is nothing
  # more we can do besides return a relevant DCube message.
  if not isinstance(creds, list) or len(creds) is 0:
    raise AuthenticationError('No authorization credentials.')

  # auth[0] should be the username. If it is not a string, the caller sent an
  # invalid username in the request and we respond with a relevant DCube
  # message.
  if not isinstance(creds[0], basestring):
    raise AuthenticationError('Username \\"%s\\" is invalid.'%
      (creds[0] is None and 'null' or str(creds[0])))
  username = creds[0]
  # Get the user from the datastore.
  user = BaseUser.get(username)
  if user is None: # The user does not exist.
    raise AuthenticationError('Username \\"%s\\" does not exist.'% username)

  # If the user exists there is no reason it should not have the nonce and
  # nextnonce attributes.
  assert user.nonce, ('%s user.nonce is expected to exist! (%s)'%
      (username, user.nonce))
  assert user.nextnonce, ('%s user.nextnonce is expected to exist! (%s)'%
      (username, user.nextnonce))

  user.cnonce = None
  user.response = None
  if len(creds) == 3:
    # If the user sent the cnonce and response, we need to check those too.
    # auth[1] should be the cnonce and auth[2] should be the response. Both the
    # cnonce and response must be strings. If not, we send back the relevant
    # message for the response.
    if not isinstance(creds[1], basestring):
      raise AuthenticationError('The given cnonce \\"%s\\" is invalid.'%
          (creds[1] is None and 'null' or str(creds[1])))
    if not isinstance(creds[2], basestring):
      raise AuthenticationError('The given response \\"%s\\" is invalid.'%
          (creds[2] is None and 'null' or str(creds[2])))
    user.cnonce = creds[1]
    user.response = creds[2]

  # Use the pychap module to authenticate. If the users credentials are
  # updated by pychap it will call store.put(). This process ensures that the
  # new CHAP credentials are persisted to disk and ready for the next request
  # made by this user.
  auth_user = pychap.authenticate(store.put_user, user)
  # DEBUG logging.warn('Auth message: %s', auth_user.message)
  if not auth_user.authenticated:
    # The user did not authenticate, so we return the relevant output message.
    raise Authenticate(
        user.username, auth_user.nonce, auth_user.nextnonce)

  # If we made it this far, then everything has gone OK and we return the user
  # credentials..
  return [auth_user.username, auth_user.nonce, auth_user.nextnonce]