/*
 * authz.c: authorization related code
 *
 * ====================================================================
 *    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 <http_request.h>
#include <http_log.h>

#include "svn_pools.h"
#include "svn_dirent_uri.h"
#include "svn_path.h"

#include "private/svn_fspath.h"

#include "mod_authz_svn.h"
#include "dav_svn.h"


svn_boolean_t
dav_svn__allow_read(request_rec *r,
                    const dav_svn_repos *repos,
                    const char *path,
                    svn_revnum_t rev,
                    apr_pool_t *pool)
{
  const char *uri;
  request_rec *subreq;
  enum dav_svn__build_what uri_type;
  svn_boolean_t allowed = FALSE;
  authz_svn__subreq_bypass_func_t allow_read_bypass = NULL;

  /* Easy out:  if the admin has explicitly set 'SVNPathAuthz Off',
     then this whole callback does nothing. */
  if (! dav_svn__get_pathauthz_flag(r))
    {
      return TRUE;
    }

  /* Sometimes we get paths that do not start with '/' and
     hence below uri concatenation would lead to wrong uris .*/
  if (path && path[0] != '/')
    path = apr_pstrcat(pool, "/", path, SVN_VA_NULL);

  /* If bypass is specified and authz has exported the provider.
     Otherwise, we fall through to the full version.  This should be
     safer than allowing or disallowing all accesses if there is a
     configuration error.
     XXX: Is this the proper thing to do in this case? */
  allow_read_bypass = dav_svn__get_pathauthz_bypass(r);
  if (allow_read_bypass != NULL)
    {
      if (allow_read_bypass(r, path, repos->repo_basename) == OK)
        return TRUE;
      else
        return FALSE;
    }

  /* If no revnum is specified, assume HEAD. */
  if (SVN_IS_VALID_REVNUM(rev))
    uri_type = DAV_SVN__BUILD_URI_VERSION;
  else
    uri_type = DAV_SVN__BUILD_URI_PUBLIC;

  /* Build a Version Resource uri representing (rev, path). */
  uri = dav_svn__build_uri(repos, uri_type, rev, path, FALSE /* add_href */,
                           pool);

  /* Check if GET would work against this uri. */
  subreq = ap_sub_req_method_uri("GET", uri, r, r->output_filters);

  if (subreq)
    {
      if (subreq->status == HTTP_OK)
        allowed = TRUE;

      ap_destroy_sub_req(subreq);
    }

  return allowed;
}


svn_boolean_t
dav_svn__allow_list_repos(request_rec *r,
                          const char *repos_name,
                          apr_pool_t *pool)
{
  const char *uri;
  request_rec *subreq;
  svn_boolean_t allowed = FALSE;

  /* Easy out:  if the admin has explicitly set 'SVNPathAuthz Off',
     then this whole callback does nothing. */
  if (! dav_svn__get_pathauthz_flag(r))
    {
      return TRUE;
    }

  /* Do not use short_circuit mode: bypass provider expects R to be request to
     the repository to find repository relative authorization file. */

  /* Build a Public Resource uri representing repository root. */
  uri =  svn_urlpath__join(dav_svn__get_root_dir(r),
                           svn_path_uri_encode(repos_name, pool), pool);

  /* Check if GET would work against this uri. */
  subreq = ap_sub_req_method_uri("GET", uri, r, r->output_filters);

  if (subreq)
    {
      if (subreq->status == HTTP_OK)
        allowed = TRUE;

      ap_destroy_sub_req(subreq);
    }

  return allowed;
}

/* This function implements 'svn_repos_authz_func_t', specifically
   for read authorization.

   Convert incoming ROOT and PATH into a version-resource URI and
   perform a GET subrequest on it.  This will invoke any authz modules
   loaded into apache.  Set *ALLOWED to TRUE if the subrequest
   succeeds, FALSE otherwise.

   BATON must be a pointer to a dav_svn__authz_read_baton.
   Use POOL for for any temporary allocation.
*/
static svn_error_t *
authz_read(svn_boolean_t *allowed,
           svn_fs_root_t *root,
           const char *path,
           void *baton,
           apr_pool_t *pool)
{
  dav_svn__authz_read_baton *arb = baton;
  svn_revnum_t rev = SVN_INVALID_REVNUM;
  const char *revpath = NULL;

  /* Our ultimate goal here is to create a Version Resource (VR) url,
     which is a url that represents a path within a revision.  We then
     send a subrequest to apache, so that any installed authz modules
     can allow/disallow the path.

     ### That means that we're assuming that any installed authz
     module is *only* paying attention to revision-paths, not paths in
     uncommitted transactions.  Someday we need to widen our horizons. */

  if (svn_fs_is_txn_root(root))
    {
      /* This means svn_repos_dir_delta2 is comparing two txn trees,
         rather than a txn and revision.  It's probably updating a
         working copy that contains 'disjoint urls'.

         Because the 2nd transaction is likely to have all sorts of
         paths linked in from random places, we need to find the
         original (rev,path) of each txn path.  That's what needs
         authorization.  */

      svn_stringbuf_t *path_s = svn_stringbuf_create(path, pool);
      const char *lopped_path = "";

      /* The path might be copied implicitly, because it's down in a
         copied tree.  So we start at path and walk up its parents
         asking if anyone was copied, and if so where from.  */
      while (! (svn_path_is_empty(path_s->data)
                || svn_fspath__is_root(path_s->data, path_s->len)))
        {
          SVN_ERR(svn_fs_copied_from(&rev, &revpath, root,
                                     path_s->data, pool));

          if (SVN_IS_VALID_REVNUM(rev) && revpath)
            {
              revpath = svn_fspath__join(revpath, lopped_path, pool);
              break;
            }

          /* Lop off the basename and try again. */
          lopped_path = svn_relpath_join(svn_fspath__basename(path_s->data,
                                                              pool),
                                         lopped_path, pool);
          svn_path_remove_component(path_s);
        }

      /* If no copy produced this path, its path in the original
         revision is the same as its path in this txn. */
      if ((rev == SVN_INVALID_REVNUM) && (revpath == NULL))
        {
          rev = svn_fs_txn_root_base_revision(root);
          revpath = path;
        }
    }
  else  /* revision root */
    {
      rev = svn_fs_revision_root_revision(root);
      revpath = path;
    }

  /* We have a (rev, path) pair to check authorization on. */
  *allowed = dav_svn__allow_read(arb->r, arb->repos, revpath, rev, pool);

  return SVN_NO_ERROR;
}


svn_repos_authz_func_t
dav_svn__authz_read_func(dav_svn__authz_read_baton *baton)
{
  /* Easy out: If the admin has explicitly set 'SVNPathAuthz Off',
     then we don't need to do any authorization checks. */
  if (! dav_svn__get_pathauthz_flag(baton->r))
    return NULL;

  return authz_read;
}


svn_boolean_t
dav_svn__allow_read_resource(const dav_resource *resource,
                             svn_revnum_t rev,
                             apr_pool_t *pool)
{
  return dav_svn__allow_read(resource->info->r, resource->info->repos,
                             resource->info->repos_path, rev, pool);
}
