/* authz_info.c : Information derived from authz settings.
 *
 * ====================================================================
 *    Licensed to the Apache Software Foundation (ASF) under one
 *    or more contributor license agreements.  See the NOTICE file
 *    distributed with this work for additional information
 *    regarding copyright ownership.  The ASF licenses this file
 *    to you under the Apache License, Version 2.0 (the
 *    "License"); you may not use this file except in compliance
 *    with the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing,
 *    software distributed under the License is distributed on an
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *    KIND, either express or implied.  See the License for the
 *    specific language governing permissions and limitations
 *    under the License.
 * ====================================================================
 */

#include <apr_hash.h>
#include <apr_pools.h>
#include <apr_tables.h>

#include "svn_hash.h"

#include "svn_private_config.h"

#include "authz.h"


svn_boolean_t
svn_authz__acl_applies_to_repo(const authz_acl_t *acl,
                               const char *repos)
{
  /* The repository name must match the one in the rule, iff the rule
     was defined for a specific repository. */
  return (0 == strcmp(acl->rule.repos, AUTHZ_ANY_REPOSITORY))
      || (0 == strcmp(repos, acl->rule.repos));
}

svn_boolean_t
svn_authz__get_acl_access(authz_access_t *access_p,
                          const authz_acl_t *acl,
                          const char *user, const char *repos)
{
  authz_access_t access;
  svn_boolean_t has_access;
  int i;

  /* The repository name must match the one in the rule, iff the rule
     was defined for a specific repository. */
  if (!svn_authz__acl_applies_to_repo(acl, repos))
    return FALSE;

  /* Check anonymous access first. */
  if (!user || 0 == strcmp(user, AUTHZ_ANONYMOUS_USER))
    {
      if (!acl->has_anon_access)
        return FALSE;

      if (access_p)
        *access_p = acl->anon_access;
      return TRUE;
    }

  /* Get the access rights for all authenticated users. */
  has_access = acl->has_authn_access;
  access = (has_access ? acl->authn_access : authz_access_none);

  /* Scan the ACEs in the ACL and merge the access rights. */
  for (i = 0; i < acl->user_access->nelts; ++i)
    {
      const authz_ace_t *const ace =
        &APR_ARRAY_IDX(acl->user_access, i, authz_ace_t);
      const svn_boolean_t match =
        ((ace->members && svn_hash_gets(ace->members, user))
         || (!ace->members && 0 == strcmp(user, ace->name)));

      if (!match != !ace->inverted) /* match XNOR ace->inverted */
        {
          access |= ace->access;
          has_access = TRUE;
        }
    }

  if (access_p)
    *access_p = access;
  return has_access;
}

/* Set *RIGHTS_P to the combination of LHS and RHS, i.e. intersect the
 * minimal rights and join the maximum rights.
 */
static void
combine_rights(authz_rights_t *rights_p,
               const authz_rights_t *lhs,
               const authz_rights_t *rhs)
{
  rights_p->min_access = lhs->min_access & rhs->min_access;
  rights_p->max_access = lhs->max_access | rhs->max_access;
}


/* Given GLOBAL_RIGHTS and a repository name REPOS, set *RIGHTS_P to
 * to the actual accumulated rights defined for that repository.
 * Return TRUE if these rights were defined explicitly.
 */
static svn_boolean_t
resolve_global_rights(authz_rights_t *rights_p,
                      const authz_global_rights_t *global_rights,
                      const char *repos)
{
  if (0 == strcmp(repos, AUTHZ_ANY_REPOSITORY))
    {
      /* Return the accumulated rights that are not repository-specific. */
      *rights_p = global_rights->any_repos_rights;
      return TRUE;
    }
  else
    {
      /* Check if we have explicit rights for this repository. */
      const authz_rights_t *const rights =
        svn_hash_gets(global_rights->per_repos_rights, repos);

      if (rights)
        {
          combine_rights(rights_p, rights, &global_rights->any_repos_rights);
          return TRUE;
        }
    }

  /* Fall-through: return the rights defined for "any" repository
     because this user has no specific rules for this specific REPOS. */
  *rights_p = global_rights->any_repos_rights;
  return FALSE;
}


svn_boolean_t
svn_authz__get_global_rights(authz_rights_t *rights_p,
                             const authz_full_t *authz,
                             const char *user, const char *repos)
{
  if (!user || 0 == strcmp(user, AUTHZ_ANONYMOUS_USER))
    {
      /* Check if we have explicit rights for anonymous access. */
      if (authz->has_anon_rights)
        {
          return resolve_global_rights(rights_p, &authz->anon_rights, repos);
        }
      else
        {
          /* Return the implicit rights, i.e., none. */
          rights_p->min_access = authz_access_none;
          rights_p->max_access = authz_access_none;
          return FALSE;
        }
    }
  else
    {
      svn_boolean_t combine_user_rights = FALSE;
      svn_boolean_t access = FALSE;

      /* Check if we have explicit rights for this user. */
      const authz_global_rights_t *const user_rights =
        svn_hash_gets(authz->user_rights, user);

      if (user_rights)
        {
          access = resolve_global_rights(rights_p, user_rights, repos);
          combine_user_rights = TRUE;
        }
      else if (authz->has_neg_rights)
        {
          /* Check if inverted-rule rights apply */
          access = resolve_global_rights(rights_p, &authz->neg_rights, repos);
          combine_user_rights = TRUE;
        }

      /* Rights given to _any_ authenticated user may apply, too. */
      if (authz->has_authn_rights)
        {
          authz_rights_t authn;
          access |= resolve_global_rights(&authn, &authz->authn_rights, repos);

          if (combine_user_rights)
            combine_rights(rights_p, rights_p, &authn);
          else
            *rights_p = authn;
        }

      return access;
    }
}
