Beispiel #1
0
static void copy_request(char *rbuf, apr_size_t rbuflen, request_rec *r)
{
    char *p;

    if (r->the_request == NULL) {
        apr_cpystrn(rbuf, "NULL", rbuflen);
        return; /* short circuit below */
    }

    if (r->parsed_uri.password == NULL) {
        p = r->the_request;
    }
    else {
        /* Don't reveal the password in the server-status view */
        p = apr_pstrcat(r->pool, r->method, " ",
                        apr_uri_unparse(r->pool, &r->parsed_uri,
                        APR_URI_UNP_OMITPASSWORD),
                        r->assbackwards ? NULL : " ", r->protocol, NULL);
    }

    /* now figure out if we copy over the 1st rbuflen chars or the last */
    if (!ap_mod_status_reqtail) {
        apr_cpystrn(rbuf, p, rbuflen);
    }
    else {
        apr_size_t slen = strlen(p);
        if (slen < rbuflen) {
            /* it all fits anyway */
            apr_cpystrn(rbuf, p, rbuflen);
        }
        else {
            apr_cpystrn(rbuf, p+(slen-rbuflen+1), rbuflen);
        }
    }
}
Beispiel #2
0
apr_status_t h2_request_rwrite(h2_request *req, request_rec *r)
{
    apr_status_t status;
    
    req->config    = h2_config_rget(r);
    req->method    = r->method;
    req->scheme    = (r->parsed_uri.scheme? r->parsed_uri.scheme
                      : ap_http_scheme(r));
    req->authority = r->hostname;
    req->path      = apr_uri_unparse(r->pool, &r->parsed_uri, 
                                     APR_URI_UNP_OMITSITEPART);

    if (!ap_strchr_c(req->authority, ':') && r->server && r->server->port) {
        apr_port_t defport = apr_uri_port_of_scheme(req->scheme);
        if (defport != r->server->port) {
            /* port info missing and port is not default for scheme: append */
            req->authority = apr_psprintf(r->pool, "%s:%d", req->authority,
                                          (int)r->server->port);
        }
    }
    
    AP_DEBUG_ASSERT(req->scheme);
    AP_DEBUG_ASSERT(req->authority);
    AP_DEBUG_ASSERT(req->path);
    AP_DEBUG_ASSERT(req->method);

    status = add_all_h1_header(req, r->pool, r->headers_in);

    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r,
                  "h2_request(%d): rwrite %s host=%s://%s%s",
                  req->id, req->method, req->scheme, req->authority, req->path);
                  
    return status;
}
Beispiel #3
0
static int test_aup(apr_pool_t *p)
{
    int i;
    apr_status_t rv;
    apr_uri_t info;
    struct aup_test *t;
    const char *failed;
    int rc = 0;

    for (i = 0; i < sizeof(aup_tests) / sizeof(aup_tests[0]); i++) {
        memset(&info, 0, sizeof(info));
        t = &aup_tests[i];
        rv = apr_uri_parse(p, t->uri, &info);
        failed = (rv != t->rv) ? "bad rc" : NULL;
        if (!failed && t->rv == APR_SUCCESS) {
            if (!same_str(info.scheme, t->scheme))
                failed = "bad scheme";
            if (!same_str(info.hostinfo, t->hostinfo))
                failed = "bad hostinfo";
            if (!same_str(info.user, t->user))
                failed = "bad user";
            if (!same_str(info.password, t->password))
                failed = "bad password";
            if (!same_str(info.hostname, t->hostname))
                failed = "bad hostname";
            if (!same_str(info.port_str, t->port_str))
                failed = "bad port_str";
            if (!same_str(info.path, t->path))
                failed = "bad path";
            if (!same_str(info.query, t->query))
                failed = "bad query";
            if (!same_str(info.fragment, t->fragment))
                failed = "bad fragment";
            if (info.port != t->port)
                failed = "bad port";
        }
        if (failed) {
            ++rc;
            fprintf(stderr, "failure for testcase %d/uri %s: %s\n", i,
                    t->uri, failed);
            show_info(rv, t->rv, &info);
        }
        else if (t->rv == APR_SUCCESS) {
            const char *s = apr_uri_unparse(p, &info,
                                            APR_URI_UNP_REVEALPASSWORD);

            if (strcmp(s, t->uri)) {
                fprintf(stderr, "apr_uri_unparsed failed for testcase %d\n", i);
                fprintf(stderr, "  got %s, expected %s\n", s, t->uri);
            }
        }
    }

    return rc;
}
static const char *log_request_line(request_rec *r, char *a)
{
    /* NOTE: If the original request contained a password, we
     * re-write the request line here to contain XXXXXX instead:
     * (note the truncation before the protocol string for HTTP/0.9 requests)
     * (note also that r->the_request contains the unmodified request)
     */
    return ap_escape_logitem(r->pool,
                             (r->parsed_uri.password)
                               ? apr_pstrcat(r->pool, r->method, " ",
                                             apr_uri_unparse(r->pool,
                                                             &r->parsed_uri, 0),
                                             r->assbackwards ? NULL : " ",
                                             r->protocol, NULL)
                               : r->the_request);
}
Beispiel #5
0
static char * add_auth_token(apr_pool_t *pool, saxctxt *ctx, apr_uri_t *u)
{
  apr_uri_t u2 = *u;
  const char *unparsed_uri, *auth_token, *ip;
  char *timestamp, *forwarded_list, *last;
  apr_status_t rv;
  apr_time_exp_t xt;
  apr_size_t sz;
  apr_table_t *params;

  unparsed_uri = apr_uri_unparse(pool, &u2, APR_URI_UNP_OMITQUERY);

  rv = apr_time_exp_lt(&xt, apr_time_now() + apr_time_from_sec(ctx->cfg->auth_exptime));
  timestamp = apr_palloc(pool, TIME_STR_SIZE + 1);
  rv = apr_strftime(timestamp, &sz, TIME_STR_SIZE, "%FT%T%z", &xt);

  if (u2.query)
    u2.query = apr_pstrcat(pool, u2.query, "&vox_timestamp=", timestamp, NULL);
  else
    u2.query = apr_pstrcat(pool, "vox_timestamp=", timestamp, NULL);

  /* Convert the query string to a table */
  params = apr_table_make(pool, 1);
  qs_to_table(u2.query, params, pool);

  /* Generate the auth token */
  forwarded_list = (char *)apr_table_get(ctx->f->r->headers_in, "X-Forwarded-For");
  /* If X-Forwarded-For header exists, use first IP in it */
  if (forwarded_list &&
      (forwarded_list = apr_pstrdup(pool, forwarded_list)) &&
      (ip = apr_strtok(forwarded_list, ", \t", &last)))
    auth_token = make_auth_token(ctx->f->r, ip, unparsed_uri, params,
                                 ctx->cfg->auth_key);
  else /* Otherwise, use the normal remote_ip */
    auth_token = make_auth_token(ctx->f->r, ctx->f->r->connection->remote_ip,
                                 unparsed_uri, params, ctx->cfg->auth_key);

  if (auth_token) {
    u2.query = apr_pstrcat(pool, u2.query, "&vox_sig=", auth_token, NULL);
    ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, ctx->f->r->server,
                 "add_auth_token: new query string is %s", u2.query);
  }

  return u2.query;
}
Beispiel #6
0
/* This implements serf_bucket_headers_do_callback_fn_t.
 */
static int
capabilities_headers_iterator_callback(void *baton,
                                       const char *key,
                                       const char *val)
{
  options_context_t *opt_ctx = baton;
  svn_ra_serf__session_t *session = opt_ctx->session;

  if (svn_cstring_casecmp(key, "dav") == 0)
    {
      /* Each header may contain multiple values, separated by commas, e.g.:
           DAV: version-control,checkout,working-resource
           DAV: merge,baseline,activity,version-controlled-collection
           DAV: http://subversion.tigris.org/xmlns/dav/svn/depth */
      apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE,
                                                   opt_ctx->pool);

      opt_ctx->received_dav_header = TRUE;

      /* Right now we only have a few capabilities to detect, so just
         seek for them directly.  This could be written slightly more
         efficiently, but that wouldn't be worth it until we have many
         more capabilities. */

      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_DEPTH, vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_DEPTH, capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_MERGEINFO, vals))
        {
          /* The server doesn't know what repository we're referring
             to, so it can't just say capability_yes. */
          if (!svn_hash_gets(session->capabilities,
                             SVN_RA_CAPABILITY_MERGEINFO))
            {
              svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
                            capability_server_yes);
            }
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LOG_REVPROPS, vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_LOG_REVPROPS, capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS, vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_ATOMIC_REVPROPS, capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY, vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_PARTIAL_REPLAY, capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_INHERITED_PROPS, vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_INHERITED_PROPS, capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_REVERSE_FILE_REVS,
                                 vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE,
                        capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_EPHEMERAL_TXNPROPS, vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS, capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_INLINE_PROPS, vals))
        {
          session->supports_inline_props = TRUE;
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_REPLAY_REV_RESOURCE, vals))
        {
          session->supports_rev_rsrc_replay = TRUE;
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_SVNDIFF1, vals))
        {
          /* Use compressed svndiff1 format for servers that properly
             advertise this capability (Subversion 1.10 and greater). */
          session->supports_svndiff1 = TRUE;
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LIST, vals))
        {
          svn_hash_sets(session->capabilities,
                        SVN_RA_CAPABILITY_LIST, capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_SVNDIFF2, vals))
        {
          /* Same for svndiff2. */
          session->supports_svndiff2 = TRUE;
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PUT_RESULT_CHECKSUM, vals))
        {
          session->supports_put_result_checksum = TRUE;
        }
    }

  /* SVN-specific headers -- if present, server supports HTTP protocol v2 */
  else if (!svn_ctype_casecmp(key[0], 'S')
           && !svn_ctype_casecmp(key[1], 'V')
           && !svn_ctype_casecmp(key[2], 'N'))
    {
      /* If we've not yet seen any information about supported POST
         requests, we'll initialize the list/hash with "create-txn"
         (which we know is supported by virtue of the server speaking
         HTTPv2 at all. */
      if (! session->supported_posts)
        {
          session->supported_posts = apr_hash_make(session->pool);
          apr_hash_set(session->supported_posts, "create-txn", 10, (void *)1);
        }

      if (svn_cstring_casecmp(key, SVN_DAV_ROOT_URI_HEADER) == 0)
        {
          session->repos_root = session->session_url;
          session->repos_root.path =
            (char *)svn_fspath__canonicalize(val, session->pool);
          session->repos_root_str =
            svn_urlpath__canonicalize(
                apr_uri_unparse(session->pool, &session->repos_root, 0),
                session->pool);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_ME_RESOURCE_HEADER) == 0)
        {
#ifdef SVN_DEBUG
          char *ignore_v2_env_var = getenv(SVN_IGNORE_V2_ENV_VAR);

          if (!(ignore_v2_env_var
                && apr_strnatcasecmp(ignore_v2_env_var, "yes") == 0))
            session->me_resource = apr_pstrdup(session->pool, val);
#else
          session->me_resource = apr_pstrdup(session->pool, val);
#endif
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_REV_STUB_HEADER) == 0)
        {
          session->rev_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_REV_ROOT_STUB_HEADER) == 0)
        {
          session->rev_root_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_TXN_STUB_HEADER) == 0)
        {
          session->txn_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_TXN_ROOT_STUB_HEADER) == 0)
        {
          session->txn_root_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_STUB_HEADER) == 0)
        {
          session->vtxn_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_ROOT_STUB_HEADER) == 0)
        {
          session->vtxn_root_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_REPOS_UUID_HEADER) == 0)
        {
          session->uuid = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_YOUNGEST_REV_HEADER) == 0)
        {
          opt_ctx->youngest_rev = SVN_STR_TO_REV(val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_ALLOW_BULK_UPDATES) == 0)
        {
          session->server_allows_bulk = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_SUPPORTED_POSTS_HEADER) == 0)
        {
          /* May contain multiple values, separated by commas. */
          int i;
          apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE,
                                                       session->pool);

          for (i = 0; i < vals->nelts; i++)
            {
              const char *post_val = APR_ARRAY_IDX(vals, i, const char *);

              svn_hash_sets(session->supported_posts, post_val, (void *)1);
            }
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_REPOSITORY_MERGEINFO) == 0)
svn_error_t *svn_ra_open4(svn_ra_session_t **session_p,
                          const char **corrected_url_p,
                          const char *repos_URL,
                          const char *uuid,
                          const svn_ra_callbacks2_t *callbacks,
                          void *callback_baton,
                          apr_hash_t *config,
                          apr_pool_t *pool)
{
  apr_pool_t *sesspool = svn_pool_create(pool);
  svn_ra_session_t *session;
  const struct ra_lib_defn *defn;
  const svn_ra__vtable_t *vtable = NULL;
  svn_config_t *servers = NULL;
  const char *server_group;
  apr_uri_t repos_URI;
  apr_status_t apr_err;
#ifdef CHOOSABLE_DAV_MODULE
  const char *http_library = DEFAULT_HTTP_LIBRARY;
#endif
  /* Auth caching parameters. */
  svn_boolean_t store_passwords = SVN_CONFIG_DEFAULT_OPTION_STORE_PASSWORDS;
  svn_boolean_t store_auth_creds = SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS;
  const char *store_plaintext_passwords
    = SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS;
  svn_boolean_t store_pp = SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP;
  const char *store_pp_plaintext
    = SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT;
  const char *corrected_url;

  /* Initialize the return variable. */
  *session_p = NULL;

  apr_err = apr_uri_parse(sesspool, repos_URL, &repos_URI);
  /* ### Should apr_uri_parse leave hostname NULL?  It doesn't
   * for "file:///" URLs, only for bogus URLs like "bogus".
   * If this is the right behavior for apr_uri_parse, maybe we
   * should have a svn_uri_parse wrapper. */
  if (apr_err != APR_SUCCESS || repos_URI.hostname == NULL)
    return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
                             _("Illegal repository URL '%s'"),
                             repos_URL);

  if (callbacks->auth_baton)
    {
      /* The 'store-passwords' and 'store-auth-creds' parameters used to
       * live in SVN_CONFIG_CATEGORY_CONFIG. For backward compatibility,
       * if values for these parameters have already been set by our
       * callers, we use those values as defaults.
       *
       * Note that we can only catch the case where users explicitly set
       * "store-passwords = no" or 'store-auth-creds = no".
       *
       * However, since the default value for both these options is
       * currently (and has always been) "yes", users won't know
       * the difference if they set "store-passwords = yes" or
       * "store-auth-creds = yes" -- they'll get the expected behaviour.
       */

      if (svn_auth_get_parameter(callbacks->auth_baton,
                                 SVN_AUTH_PARAM_DONT_STORE_PASSWORDS) != NULL)
        store_passwords = FALSE;

      if (svn_auth_get_parameter(callbacks->auth_baton,
                                 SVN_AUTH_PARAM_NO_AUTH_CACHE) != NULL)
        store_auth_creds = FALSE;
    }

  if (config)
    {
      /* Grab the 'servers' config. */
      servers = apr_hash_get(config, SVN_CONFIG_CATEGORY_SERVERS,
                             APR_HASH_KEY_STRING);
      if (servers)
        {
          /* First, look in the global section. */

          SVN_ERR(svn_config_get_bool
            (servers, &store_passwords, SVN_CONFIG_SECTION_GLOBAL,
             SVN_CONFIG_OPTION_STORE_PASSWORDS,
             store_passwords));

          SVN_ERR(svn_config_get_yes_no_ask
            (servers, &store_plaintext_passwords, SVN_CONFIG_SECTION_GLOBAL,
             SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS,
             SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS));

          SVN_ERR(svn_config_get_bool
            (servers, &store_pp, SVN_CONFIG_SECTION_GLOBAL,
             SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP,
             store_pp));

          SVN_ERR(svn_config_get_yes_no_ask
            (servers, &store_pp_plaintext,
             SVN_CONFIG_SECTION_GLOBAL,
             SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT,
             SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT));

          SVN_ERR(svn_config_get_bool
            (servers, &store_auth_creds, SVN_CONFIG_SECTION_GLOBAL,
              SVN_CONFIG_OPTION_STORE_AUTH_CREDS,
              store_auth_creds));

          /* Find out where we're about to connect to, and
           * try to pick a server group based on the destination. */
          server_group = svn_config_find_group(servers, repos_URI.hostname,
                                               SVN_CONFIG_SECTION_GROUPS,
                                               sesspool);

          if (server_group)
            {
              /* Override global auth caching parameters with the ones
               * for the server group, if any. */
              SVN_ERR(svn_config_get_bool(servers, &store_auth_creds,
                                          server_group,
                                          SVN_CONFIG_OPTION_STORE_AUTH_CREDS,
                                          store_auth_creds));

              SVN_ERR(svn_config_get_bool(servers, &store_passwords,
                                          server_group,
                                          SVN_CONFIG_OPTION_STORE_PASSWORDS,
                                          store_passwords));

              SVN_ERR(svn_config_get_yes_no_ask
                (servers, &store_plaintext_passwords, server_group,
                 SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS,
                 store_plaintext_passwords));

              SVN_ERR(svn_config_get_bool
                (servers, &store_pp,
                 server_group, SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP,
                 store_pp));

              SVN_ERR(svn_config_get_yes_no_ask
                (servers, &store_pp_plaintext, server_group,
                 SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT,
                 store_pp_plaintext));
            }
#ifdef CHOOSABLE_DAV_MODULE
          /* Now, which DAV-based RA method do we want to use today? */
          http_library
            = svn_config_get_server_setting(servers,
                                            server_group, /* NULL is OK */
                                            SVN_CONFIG_OPTION_HTTP_LIBRARY,
                                            DEFAULT_HTTP_LIBRARY);

          if (strcmp(http_library, "neon") != 0 &&
              strcmp(http_library, "serf") != 0)
            return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
                                     _("Invalid config: unknown HTTP library "
                                       "'%s'"),
                                     http_library);
#endif
        }
    }

  if (callbacks->auth_baton)
    {
      /* Save auth caching parameters in the auth parameter hash. */
      if (! store_passwords)
        svn_auth_set_parameter(callbacks->auth_baton,
                               SVN_AUTH_PARAM_DONT_STORE_PASSWORDS, "");

      svn_auth_set_parameter(callbacks->auth_baton,
                             SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS,
                             store_plaintext_passwords);

      if (! store_pp)
        svn_auth_set_parameter(callbacks->auth_baton,
                               SVN_AUTH_PARAM_DONT_STORE_SSL_CLIENT_CERT_PP,
                               "");

      svn_auth_set_parameter(callbacks->auth_baton,
                             SVN_AUTH_PARAM_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT,
                             store_pp_plaintext);

      if (! store_auth_creds)
        svn_auth_set_parameter(callbacks->auth_baton,
                               SVN_AUTH_PARAM_NO_AUTH_CACHE, "");
    }

  /* Find the library. */
  for (defn = ra_libraries; defn->ra_name != NULL; ++defn)
    {
      const char *scheme;

      if ((scheme = has_scheme_of(defn->schemes, repos_URL)))
        {
          svn_ra__init_func_t initfunc = defn->initfunc;

#ifdef CHOOSABLE_DAV_MODULE
          if (defn->schemes == dav_schemes
              && strcmp(defn->ra_name, http_library) != 0)
            continue;
#endif

          if (! initfunc)
            SVN_ERR(load_ra_module(&initfunc, NULL, defn->ra_name,
                                   sesspool));
          if (! initfunc)
            /* Library not found. */
            continue;

          SVN_ERR(initfunc(svn_ra_version(), &vtable, sesspool));

          SVN_ERR(check_ra_version(vtable->get_version(), scheme));

          if (! has_scheme_of(vtable->get_schemes(sesspool), repos_URL))
            /* Library doesn't support the scheme at runtime. */
            continue;


          break;
        }
    }

  if (vtable == NULL)
    return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
                             _("Unrecognized URL scheme for '%s'"),
                             repos_URL);

  /* Create the session object. */
  session = apr_pcalloc(sesspool, sizeof(*session));
  session->vtable = vtable;
  session->pool = sesspool;

  /* Ask the library to open the session. */
  SVN_ERR_W(vtable->open_session(session, &corrected_url, repos_URL,
                                 callbacks, callback_baton, config, sesspool),
            apr_psprintf(pool, "Unable to connect to a repository at URL '%s'",
                         repos_URL));

  /* If the session open stuff detected a server-provided URL
     correction (a 301 or 302 redirect response during the initial
     OPTIONS request), then kill the session so the caller can decide
     what to do. */
  if (corrected_url_p && corrected_url)
    {
      if (! svn_path_is_url(corrected_url))
        {
          /* RFC1945 and RFC2616 state that the Location header's
             value (from whence this CORRECTED_URL ultimately comes),
             if present, must be an absolute URI.  But some Apache
             versions (those older than 2.2.11, it seems) transmit
             only the path portion of the URI.  See issue #3775 for
             details. */
          apr_uri_t corrected_URI = repos_URI;
          corrected_URI.path = (char *)corrected_url;
          corrected_url = apr_uri_unparse(pool, &corrected_URI, 0);
        }
      *corrected_url_p = svn_uri_canonicalize(corrected_url, pool);
      svn_pool_destroy(sesspool);
      return SVN_NO_ERROR;
    }

  /* Check the UUID. */
  if (uuid)
    {
      const char *repository_uuid;

      SVN_ERR(vtable->get_uuid(session, &repository_uuid, pool));
      if (strcmp(uuid, repository_uuid) != 0)
        {
          /* Duplicate the uuid as it is allocated in sesspool */
          repository_uuid = apr_pstrdup(pool, repository_uuid);
          svn_pool_destroy(sesspool);
          return svn_error_createf(SVN_ERR_RA_UUID_MISMATCH, NULL,
                                   _("Repository UUID '%s' doesn't match "
                                     "expected UUID '%s'"),
                                   repository_uuid, uuid);
        }
    }

  *session_p = session;
  return SVN_NO_ERROR;
}
Beispiel #8
0
/* This implements serf_bucket_headers_do_callback_fn_t.
 */
static int
capabilities_headers_iterator_callback(void *baton,
                                       const char *key,
                                       const char *val)
{
  options_context_t *opt_ctx = baton;
  svn_ra_serf__session_t *session = opt_ctx->session;

  if (svn_cstring_casecmp(key, "dav") == 0)
    {
      /* Each header may contain multiple values, separated by commas, e.g.:
           DAV: version-control,checkout,working-resource
           DAV: merge,baseline,activity,version-controlled-collection
           DAV: http://subversion.tigris.org/xmlns/dav/svn/depth */
      apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE,
                                                   opt_ctx->pool);

      /* Right now we only have a few capabilities to detect, so just
         seek for them directly.  This could be written slightly more
         efficiently, but that wouldn't be worth it until we have many
         more capabilities. */

      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_DEPTH, vals))
        {
          apr_hash_set(session->capabilities,
                       SVN_RA_CAPABILITY_DEPTH, APR_HASH_KEY_STRING,
                       capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_MERGEINFO, vals))
        {
          /* The server doesn't know what repository we're referring
             to, so it can't just say capability_yes. */
          apr_hash_set(session->capabilities,
                       SVN_RA_CAPABILITY_MERGEINFO, APR_HASH_KEY_STRING,
                       capability_server_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LOG_REVPROPS, vals))
        {
          apr_hash_set(session->capabilities,
                       SVN_RA_CAPABILITY_LOG_REVPROPS, APR_HASH_KEY_STRING,
                       capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS, vals))
        {
          apr_hash_set(session->capabilities,
                       SVN_RA_CAPABILITY_ATOMIC_REVPROPS, APR_HASH_KEY_STRING,
                       capability_yes);
        }
      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY, vals))
        {
          apr_hash_set(session->capabilities,
                       SVN_RA_CAPABILITY_PARTIAL_REPLAY, APR_HASH_KEY_STRING,
                       capability_yes);
        }
    }

  /* SVN-specific headers -- if present, server supports HTTP protocol v2 */
  else if (strncmp(key, "SVN", 3) == 0)
    {
      /* If we've not yet seen any information about supported POST
         requests, we'll initialize the list/hash with "create-txn"
         (which we know is supported by virtue of the server speaking
         HTTPv2 at all. */
      if (! session->supported_posts)
        {
          session->supported_posts = apr_hash_make(session->pool);
          apr_hash_set(session->supported_posts, "create-txn", 10, (void *)1);
        }

      if (svn_cstring_casecmp(key, SVN_DAV_ROOT_URI_HEADER) == 0)
        {
          session->repos_root = session->session_url;
          session->repos_root.path =
            (char *)svn_fspath__canonicalize(val, session->pool);
          session->repos_root_str =
            svn_urlpath__canonicalize(
                apr_uri_unparse(session->pool, &session->repos_root, 0),
                session->pool);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_ME_RESOURCE_HEADER) == 0)
        {
#ifdef SVN_DEBUG
          char *ignore_v2_env_var = getenv(SVN_IGNORE_V2_ENV_VAR);

          if (!(ignore_v2_env_var
                && apr_strnatcasecmp(ignore_v2_env_var, "yes") == 0))
            session->me_resource = apr_pstrdup(session->pool, val);
#else
          session->me_resource = apr_pstrdup(session->pool, val);
#endif
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_REV_STUB_HEADER) == 0)
        {
          session->rev_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_REV_ROOT_STUB_HEADER) == 0)
        {
          session->rev_root_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_TXN_STUB_HEADER) == 0)
        {
          session->txn_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_TXN_ROOT_STUB_HEADER) == 0)
        {
          session->txn_root_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_STUB_HEADER) == 0)
        {
          session->vtxn_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_ROOT_STUB_HEADER) == 0)
        {
          session->vtxn_root_stub = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_REPOS_UUID_HEADER) == 0)
        {
          session->uuid = apr_pstrdup(session->pool, val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_YOUNGEST_REV_HEADER) == 0)
        {
          opt_ctx->youngest_rev = SVN_STR_TO_REV(val);
        }
      else if (svn_cstring_casecmp(key, SVN_DAV_SUPPORTED_POSTS_HEADER) == 0)
        {
          /* May contain multiple values, separated by commas. */
          int i;
          apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE,
                                                       opt_ctx->pool);

          for (i = 0; i < vals->nelts; i++)
            {
              const char *post_val = APR_ARRAY_IDX(vals, i, const char *);

              apr_hash_set(session->supported_posts, post_val,
                           APR_HASH_KEY_STRING, (void *)1);
            }
        }
    }
Beispiel #9
0
AP_DECLARE(void) ap_add_common_vars(request_rec *r)
{
    apr_table_t *e;
    server_rec *s = r->server;
    conn_rec *c = r->connection;
    core_dir_config *conf =
        (core_dir_config *)ap_get_core_module_config(r->per_dir_config);
    const char *env_temp;
    const apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in);
    const apr_table_entry_t *hdrs = (const apr_table_entry_t *) hdrs_arr->elts;
    int i;
    apr_port_t rport;
    char *q;

    /* use a temporary apr_table_t which we'll overlap onto
     * r->subprocess_env later
     * (exception: if r->subprocess_env is empty at the start,
     * write directly into it)
     */
    if (apr_is_empty_table(r->subprocess_env)) {
        e = r->subprocess_env;
    }
    else {
        e = apr_table_make(r->pool, 25 + hdrs_arr->nelts);
    }

    /* First, add environment vars from headers... this is as per
     * CGI specs, though other sorts of scripting interfaces see
     * the same vars...
     */

    for (i = 0; i < hdrs_arr->nelts; ++i) {
        if (!hdrs[i].key) {
            continue;
        }

        /* A few headers are special cased --- Authorization to prevent
         * rogue scripts from capturing passwords; content-type and -length
         * for no particular reason.
         */

        if (!strcasecmp(hdrs[i].key, "Content-type")) {
            apr_table_addn(e, "CONTENT_TYPE", hdrs[i].val);
        }
        else if (!strcasecmp(hdrs[i].key, "Content-length")) {
            apr_table_addn(e, "CONTENT_LENGTH", hdrs[i].val);
        }
        /*
         * You really don't want to disable this check, since it leaves you
         * wide open to CGIs stealing passwords and people viewing them
         * in the environment with "ps -e".  But, if you must...
         */
#ifndef SECURITY_HOLE_PASS_AUTHORIZATION
        else if (!strcasecmp(hdrs[i].key, "Authorization")
                 || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) {
            if (conf->cgi_pass_auth == AP_CGI_PASS_AUTH_ON) {
                add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val);
            }
        }
#endif
        else
            add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val);
    }

    env_temp = apr_table_get(r->subprocess_env, "PATH");
    if (env_temp == NULL) {
        env_temp = getenv("PATH");
    }
    if (env_temp == NULL) {
        env_temp = DEFAULT_PATH;
    }
    apr_table_addn(e, "PATH", apr_pstrdup(r->pool, env_temp));

#if defined(WIN32)
    env2env(e, "SystemRoot");
    env2env(e, "COMSPEC");
    env2env(e, "PATHEXT");
    env2env(e, "WINDIR");
#elif defined(OS2)
    env2env(e, "COMSPEC");
    env2env(e, "ETC");
    env2env(e, "DPATH");
    env2env(e, "PERLLIB_PREFIX");
#elif defined(BEOS)
    env2env(e, "LIBRARY_PATH");
#elif defined(DARWIN)
    env2env(e, "DYLD_LIBRARY_PATH");
#elif defined(_AIX)
    env2env(e, "LIBPATH");
#elif defined(__HPUX__)
    /* HPUX PARISC 2.0W knows both, otherwise redundancy is harmless */
    env2env(e, "SHLIB_PATH");
    env2env(e, "LD_LIBRARY_PATH");
#else /* Some Unix */
    env2env(e, "LD_LIBRARY_PATH");
#endif

    apr_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r));
    apr_table_addn(e, "SERVER_SOFTWARE", ap_get_server_banner());
    apr_table_addn(e, "SERVER_NAME",
                   ap_escape_html(r->pool, ap_get_server_name_for_url(r)));
    apr_table_addn(e, "SERVER_ADDR", r->connection->local_ip);  /* Apache */
    apr_table_addn(e, "SERVER_PORT",
                  apr_psprintf(r->pool, "%u", ap_get_server_port(r)));
    add_unless_null(e, "REMOTE_HOST",
                    ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST, NULL));
    apr_table_addn(e, "REMOTE_ADDR", r->useragent_ip);
    apr_table_addn(e, "DOCUMENT_ROOT", ap_document_root(r));    /* Apache */
    apr_table_setn(e, "REQUEST_SCHEME", ap_http_scheme(r));
    apr_table_addn(e, "CONTEXT_PREFIX", ap_context_prefix(r));
    apr_table_addn(e, "CONTEXT_DOCUMENT_ROOT", ap_context_document_root(r));
    apr_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */
    if (apr_table_get(r->notes, "proxy-noquery") && (q = ap_strchr(r->filename, '?'))) {
        *q = '\0';
        apr_table_addn(e, "SCRIPT_FILENAME", apr_pstrdup(r->pool, r->filename));
        *q = '?';
    }
    else {
        apr_table_addn(e, "SCRIPT_FILENAME", r->filename);  /* Apache */
    }

    rport = c->client_addr->port;
    apr_table_addn(e, "REMOTE_PORT", apr_itoa(r->pool, rport));

    if (r->user) {
        apr_table_addn(e, "REMOTE_USER", r->user);
    }
    else if (r->prev) {
        request_rec *back = r->prev;

        while (back) {
            if (back->user) {
                apr_table_addn(e, "REDIRECT_REMOTE_USER", back->user);
                break;
            }
            back = back->prev;
        }
    }
    add_unless_null(e, "AUTH_TYPE", r->ap_auth_type);
    env_temp = ap_get_remote_logname(r);
    if (env_temp) {
        apr_table_addn(e, "REMOTE_IDENT", apr_pstrdup(r->pool, env_temp));
    }

    /* Apache custom error responses. If we have redirected set two new vars */

    if (r->prev) {
        /* PR#57785: reconstruct full URL here */
        apr_uri_t *uri = &r->prev->parsed_uri;
        if (!uri->scheme) {
            uri->scheme = (char*)ap_http_scheme(r->prev);
        }
        if (!uri->port) {
            uri->port = ap_get_server_port(r->prev);
            uri->port_str = apr_psprintf(r->pool, "%u", uri->port);
        }
        if (!uri->hostname) {
            uri->hostname = (char*)ap_get_server_name_for_url(r->prev);
        }
        add_unless_null(e, "REDIRECT_QUERY_STRING", r->prev->args);
        add_unless_null(e, "REDIRECT_URL",
                        apr_uri_unparse(r->pool, uri, 0));
    }

    if (e != r->subprocess_env) {
        apr_table_overlap(r->subprocess_env, e, APR_OVERLAP_TABLES_SET);
    }
}
static int
webid_auth_checker(request_rec *r) {
    int is_initial_req, req_access, req_method, ret;
    const char *req_dest;

    request_rec *r_dest;
    apr_uri_t apr_uri;

    if (r->filename == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
                      "Module bug?  Request filename is missing for URI %s", r->uri);
        return http_status_code(r, OK);
    }

    if (r->user == NULL || strlen(r->user) == 0) {
        return http_status_code(r, HTTP_FORBIDDEN);
    }

    // req_access: Read, Write, or Control
    is_initial_req = ap_is_initial_req(r);
    req_access = WEBID_ACCESS_INVALID;
    req_method = (AP_METHOD_BIT << r->method_number);

    if (is_initial_req && r->method_number == M_COPY) {
        // allow COPY of a readonly source URI
        // - target URI check happens by subrequest
        req_access = WEBID_ACCESS_READ;

    } else if (req_method == (req_method & WEBID_M_READ)) {
        // check the acl:Read method bitmask
        req_access = WEBID_ACCESS_READ;

    } else if (req_method == (req_method & WEBID_M_WRITE)) {
        // check the acl:Write method bitmask
        // - writes to ACL URIs are acl:Control (handled internally)
        req_access = WEBID_ACCESS_WRITE;

    } else {
        // unhandled methods require acl:Control
        req_access = WEBID_ACCESS_CONTROL;
    }

    ret = HTTP_FORBIDDEN;

    if (is_initial_req && (r->method_number == M_COPY || r->method_number == M_MOVE)) {
        req_dest = apr_table_get(r->headers_in, "Destination");
        if (req_dest == NULL) {
            const char *nscp_host = apr_table_get(r->headers_in, "Host");
            const char *nscp_path = apr_table_get(r->headers_in, "New-uri");
            if (nscp_host != NULL && nscp_path != NULL)
                req_dest = apr_psprintf(r->pool, "http://%s%s", nscp_host, nscp_path);
        }
        if (req_dest != NULL) {
            if ((apr_uri_parse(r->pool, req_dest, &apr_uri) == APR_SUCCESS) &&
                (apr_uri.scheme != NULL && strcmp(apr_uri.scheme, ap_http_scheme(r)) == 0) &&
                (apr_uri.hostname != NULL && strcmp(apr_uri.hostname, ap_get_server_name(r)) == 0)) {
                req_dest = apr_uri_unparse(r->pool, &apr_uri, APR_URI_UNP_OMITSITEPART);
                r_dest = ap_sub_req_method_uri(r->method, req_dest, r, NULL);
                if ((ret = check_request_acl(r, req_access)) == OK)
                    ret = check_request_acl(r_dest, WEBID_ACCESS_WRITE);
            } else {
                ret = HTTP_BAD_GATEWAY;
            }
        }
    } else {
        ret = check_request_acl(r, req_access);
    }

    return http_status_code(r, ret);
}
Beispiel #11
0
CStringA CPathUtils::GetAbsoluteURL
    ( const CStringA& URL
    , const CStringA& repositoryRootURL
    , const CStringA& parentPathURL)
{
    CStringA errorResult;
    SVNPool pool;

    /* If the URL is already absolute, there is nothing to do. */

    const char *canonicalized_url = svn_uri_canonicalize (URL, pool);
    if (svn_path_is_url (canonicalized_url))
        return canonicalized_url;

    /* Parse the parent directory URL into its parts. */

    apr_uri_t parent_dir_parsed_uri;
    if (apr_uri_parse (pool, parentPathURL, &parent_dir_parsed_uri))
        return errorResult;

    /* If the parent directory URL is at the server root, then the URL
       may have no / after the hostname so apr_uri_parse() will leave
       the URL's path as NULL. */

    if (! parent_dir_parsed_uri.path)
        parent_dir_parsed_uri.path = apr_pstrmemdup (pool, "/", 1);

    /* Handle URLs relative to the current directory or to the
       repository root.  The backpaths may only remove path elements,
       not the hostname.  This allows an external to refer to another
       repository in the same server relative to the location of this
       repository, say using SVNParentPath. */

    if ((0 == strncmp("../", URL, 3)) || (0 == strncmp("^/", URL, 2)))
    {
        apr_array_header_t *base_components = NULL;
        apr_array_header_t *relative_components = NULL;

        /* Decompose either the parent directory's URL path or the
           repository root's URL path into components.  */

        if (0 == strncmp ("../", URL, 3))
        {
            base_components
                = svn_path_decompose (parent_dir_parsed_uri.path, pool);
            relative_components
                = svn_path_decompose (canonicalized_url, pool);
        }
        else
        {
            apr_uri_t repos_root_parsed_uri;
            if (apr_uri_parse(pool, repositoryRootURL, &repos_root_parsed_uri))
                return errorResult;

            /* If the repository root URL is at the server root, then
               the URL may have no / after the hostname so
               apr_uri_parse() will leave the URL's path as NULL. */

            if (! repos_root_parsed_uri.path)
                repos_root_parsed_uri.path = apr_pstrmemdup (pool, "/", 1);

            base_components
                = svn_path_decompose (repos_root_parsed_uri.path, pool);
            relative_components
                = svn_path_decompose (canonicalized_url + 2, pool);
        }

        for (int i = 0; i < relative_components->nelts; ++i)
        {
            const char *component
                = APR_ARRAY_IDX(relative_components, i, const char *);

            if (0 == strcmp("..", component))
            {
                /* Constructing the final absolute URL together with
                   apr_uri_unparse() requires that the path be absolute,
                   so only pop a component if the component being popped
                   is not the component for the root directory. */

                if (base_components->nelts > 1)
                    apr_array_pop (base_components);
            }
            else
                APR_ARRAY_PUSH (base_components, const char *) = component;
        }

        parent_dir_parsed_uri.path = (char *)svn_path_compose(base_components,
                                                            pool);
        parent_dir_parsed_uri.query = NULL;
        parent_dir_parsed_uri.fragment = NULL;

        return apr_uri_unparse (pool, &parent_dir_parsed_uri, 0);
    }
Beispiel #12
0
static svn_error_t *
resolve_relative_external_url(const char **resolved_url,
                              const svn_wc_external_item2_t *item,
                              const char *repos_root_url,
                              const char *parent_dir_url,
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool)
{
  const char *url = item->url;
  apr_uri_t parent_dir_uri;
  apr_status_t status;

  *resolved_url = item->url;

  /* If the URL is already absolute, there is nothing to do. */
  if (svn_path_is_url(url))
    {
      /* "http://server/path" */
      *resolved_url = svn_uri_canonicalize(url, result_pool);
      return SVN_NO_ERROR;
    }

  if (url[0] == '/')
    {
      /* "/path", "//path", and "///path" */
      int num_leading_slashes = 1;
      if (url[1] == '/')
        {
          num_leading_slashes++;
          if (url[2] == '/')
            num_leading_slashes++;
        }

      /* "//schema-relative" and in some cases "///schema-relative".
         This last format is supported on file:// schema relative. */
      url = apr_pstrcat(scratch_pool,
                        apr_pstrndup(scratch_pool, url, num_leading_slashes),
                        svn_relpath_canonicalize(url + num_leading_slashes,
                                                 scratch_pool),
                        (char*)NULL);
    }
  else
    {
      /* "^/path" and "../path" */
      url = svn_relpath_canonicalize(url, scratch_pool);
    }

  /* Parse the parent directory URL into its parts. */
  status = apr_uri_parse(scratch_pool, parent_dir_url, &parent_dir_uri);
  if (status)
    return svn_error_createf(SVN_ERR_BAD_URL, 0,
                             "Illegal parent directory URL '%s'",
                             parent_dir_url);

  /* If the parent directory URL is at the server root, then the URL
     may have no / after the hostname so apr_uri_parse() will leave
     the URL's path as NULL. */
  if (! parent_dir_uri.path)
    parent_dir_uri.path = apr_pstrmemdup(scratch_pool, "/", 1);
  parent_dir_uri.query = NULL;
  parent_dir_uri.fragment = NULL;

  /* Handle URLs relative to the current directory or to the
     repository root.  The backpaths may only remove path elements,
     not the hostname.  This allows an external to refer to another
     repository in the same server relative to the location of this
     repository, say using SVNParentPath. */
  if ((0 == strncmp("../", url, 3)) ||
      (0 == strncmp("^/", url, 2)))
    {
      apr_array_header_t *base_components;
      apr_array_header_t *relative_components;
      int i;

      /* Decompose either the parent directory's URL path or the
         repository root's URL path into components.  */
      if (0 == strncmp("../", url, 3))
        {
          base_components = svn_path_decompose(parent_dir_uri.path,
                                               scratch_pool);
          relative_components = svn_path_decompose(url, scratch_pool);
        }
      else
        {
          apr_uri_t repos_root_uri;

          status = apr_uri_parse(scratch_pool, repos_root_url,
                                 &repos_root_uri);
          if (status)
            return svn_error_createf(SVN_ERR_BAD_URL, 0,
                                     "Illegal repository root URL '%s'",
                                     repos_root_url);

          /* If the repository root URL is at the server root, then
             the URL may have no / after the hostname so
             apr_uri_parse() will leave the URL's path as NULL. */
          if (! repos_root_uri.path)
            repos_root_uri.path = apr_pstrmemdup(scratch_pool, "/", 1);

          base_components = svn_path_decompose(repos_root_uri.path,
                                               scratch_pool);
          relative_components = svn_path_decompose(url + 2, scratch_pool);
        }

      for (i = 0; i < relative_components->nelts; ++i)
        {
          const char *component = APR_ARRAY_IDX(relative_components,
                                                i,
                                                const char *);
          if (0 == strcmp("..", component))
            {
              /* Constructing the final absolute URL together with
                 apr_uri_unparse() requires that the path be absolute,
                 so only pop a component if the component being popped
                 is not the component for the root directory. */
              if (base_components->nelts > 1)
                apr_array_pop(base_components);
            }
          else
            APR_ARRAY_PUSH(base_components, const char *) = component;
        }

      parent_dir_uri.path = (char *)svn_path_compose(base_components,
                                                     scratch_pool);
      *resolved_url = svn_uri_canonicalize(apr_uri_unparse(scratch_pool,
                                                           &parent_dir_uri, 0),
                                       result_pool);
      return SVN_NO_ERROR;
    }
Beispiel #13
0
/* compute a new uri based on the old one and the current request such
   that the uri maps to the same location on a different server.
   there are three cases:
     1. globally absolute: method://old-server(:port)/path/to/file
     2. locally absolute:  /path/to/file
     3. relative:          path/to/file

   we handle the cases as follows:

     1. check from_servers to ensure that old-server(:port) is listed;
        if not, we check if old-server is the current servername; if
        not, we _do not_ replace the server in the url; note that we
        _do not_ try to match urls of the form
        method://username:password@old-server(:port)/path/to/file
     2. just drop in to_server in the beginning
     3. figure out the current request_uri, and replace the most
        specific filename with path/to/file
*/
static char * remap_url(saxctxt *ctx, char *uri, int add_auth, int add_qstring_ignore)
{
  apr_uri_t u, u2;
  int i;
  char *s;
  apr_pool_t *pool = ctx->f->r->pool;

  ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctx->f->r->server,
               "remap_url: remapping %s (add_auth = %d, add_qstring_ignore = %d)",
               uri, add_auth, add_qstring_ignore);

  if(apr_uri_parse(pool, uri, &u) != APR_SUCCESS)
    return NULL;

  /* only CDNify HTTP and HTTPS requests for now */
  if(u.scheme && strcasecmp(u.scheme, "http") != 0 && strcasecmp(u.scheme, "https") != 0)
    return NULL;

  if(u.hostinfo) { /* case 1 */
    const char *hostinfo =
      (u.port_str && u.scheme && u.port != apr_uri_port_of_scheme(u.scheme)) ?
      u.hostinfo : u.hostname;

    /* does this hostinfo match the current ServerName or one of the ServerAliases? */
    if(matches_aliases(ctx->f->r->server, hostinfo))
      goto set_hostname_and_return;

    /* if not, cycle through from_servers and see if one of them matches */
    if(ctx->cfg->from_servers) {
      tattr *from = (tattr *)ctx->cfg->from_servers->elts;
      for(i = 0; i < ctx->cfg->from_servers->nelts; ++i)
        if(!strcasecmp(hostinfo, from[i].val))
          goto set_hostname_and_return;
    }

  } else if(u.path && u.path[0] == '/') { /* case 2 */
    goto set_hostname_and_return;

  } else if(u.path) { /* case 3 */

    /*
     * first figure out the local absolute path, minus the filename,
     * from r->uri; then, tack the relative uri onto the end
     */
    char *my_uri = apr_pstrdup(pool, ctx->f->r->uri);
    s = strrchr(my_uri, '/');
    if(s) {
      *(s+1) = '\0';
      u.path = apr_pstrcat(pool, my_uri, u.path, NULL);
    }
    goto set_hostname_and_return;
  }

  return NULL;

 set_hostname_and_return:
  if(apr_uri_parse(pool, (char *)ctx->cfg->to_server, &u2) != APR_SUCCESS)
    return NULL;
  u.scheme = u2.scheme;
  u.hostname = u2.hostname;
  u.port_str = u2.port_str;
  u.port = u2.port;

  if(add_qstring_ignore)
    u.query = add_qstring_ignore_token(pool, ctx, &u);

  if(add_auth)
    u.query = add_auth_token(pool, ctx, &u);

  return apr_uri_unparse(pool, &u, 0);
}
Beispiel #14
0
cookie_t *
chxj_save_cookie(request_rec *r)
{
  int                 ii;
  apr_array_header_t  *headers;
  apr_table_entry_t   *hentryp;
  apr_array_header_t  *err_headers;
  apr_table_entry_t   *err_hentryp;
  char                *old_cookie_id;
  char                *store_string;
  mod_chxj_config     *dconf;
  chxjconvrule_entry  *entryp;
  apr_table_t         *new_cookie_table;
  int                 has_cookie = 0;
  cookie_t            *cookie;
  cookie_t            *old_cookie;
  char                *refer_string;
  apr_uri_t           parsed_uri;
  int                 has_refer;


  DBG(r, "start chxj_save_cookie()");

  cookie = (cookie_t*)apr_palloc(r->pool, sizeof(cookie_t));
  cookie->cookie_id = NULL;

  has_cookie = 0;
  has_refer = 0;

  dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
  entryp = chxj_apply_convrule(r, dconf->convrules);
  if (! entryp) {
    DBG(r, "end chxj_save_cookie() no pattern");
    return NULL;
  }
  if (! (entryp->action & CONVRULE_COOKIE_ON_BIT)) {
    DBG(r, "end chxj_save_cookie() CookieOff");
    return NULL;
  }



  headers = (apr_array_header_t*)apr_table_elts(r->headers_out);
  hentryp = (apr_table_entry_t*)headers->elts;
  err_headers = (apr_array_header_t*)apr_table_elts(r->err_headers_out);
  err_hentryp = (apr_table_entry_t*)err_headers->elts;


  new_cookie_table = apr_table_make(r->pool, 0);

  for (ii=0; ii<headers->nelts; ii++) {
    if (strcasecmp(hentryp[ii].key, "Set-Cookie") == 0) {
      DBG(r, "=====================================");
      DBG(r, "cookie=[%s:%s]", hentryp[ii].key, hentryp[ii].val);

      char* key;
      char* val;
      char* buff;


      buff = apr_pstrdup(r->pool, hentryp[ii].val);
      val = strchr(buff, '=');
      if (val) {
        key = buff;
        *val++ = 0;
        apr_table_add(new_cookie_table, key, val);
        if (strcasecmp(REFERER_COOKIE_KEY, key) == 0) has_refer++;
        
      }

      has_cookie = 1;
      DBG(r, "=====================================");
    }
  }
  for (ii=0; ii<err_headers->nelts; ii++) {
    if (strcasecmp(err_hentryp[ii].key, "Set-Cookie") == 0) {
      DBG(r, "=====================================");
      DBG(r, "cookie=[%s:%s]", err_hentryp[ii].key, err_hentryp[ii].val);

      char* key;
      char* val;
      char* buff;


      buff = apr_pstrdup(r->pool, err_hentryp[ii].val);
      val = strchr(buff, '=');
      if (val) {
        key = buff;
        *val++ = 0;
        apr_table_add(new_cookie_table, key, val);
        if (strcasecmp(REFERER_COOKIE_KEY, key) == 0) has_refer++;
        
      }

      has_cookie = 1;
      DBG(r, "=====================================");
    }
  }
  apr_table_unset(r->headers_out, "Set-Cookie");
  apr_table_unset(r->err_headers_out, "Set-Cookie");

  if (! has_refer) {
    apr_uri_parse(r->pool,r->uri, &parsed_uri);
    refer_string = apr_psprintf(r->pool, 
                                "%s://%s%s", 
                                chxj_run_http_scheme(r),
                                r->hostname,
                                apr_uri_unparse(r->pool,
                                                &parsed_uri,
                                                APR_URI_UNP_OMITSITEPART));
    if (r->args && strlen(r->args)) {
      refer_string = apr_pstrcat(r->pool, refer_string, "?", r->args, NULL);
    }
    apr_table_setn(new_cookie_table, REFERER_COOKIE_KEY, refer_string);
    DBG(r, "ADD REFER[%s]", refer_string);
    has_cookie++;
  }


  /*
   * check input parameters
   */
  old_cookie_id = (char*)apr_table_get(r->headers_in, "CHXJ_COOKIE_ID");
  if (old_cookie_id) {
    old_cookie = chxj_load_cookie(r, old_cookie_id); 
    if (old_cookie && old_cookie->cookie_headers) {
      hentryp = (apr_table_entry_t*)old_cookie->cookie_headers->elts;
      for (ii=0; ii<old_cookie->cookie_headers->nelts; ii++) {
        if (hentryp && apr_table_get(new_cookie_table, hentryp[ii].key) == NULL) {
          apr_table_add(new_cookie_table, hentryp[ii].key, hentryp[ii].val);
          has_cookie = 1;
        }
      }
      chxj_delete_cookie(r,        old_cookie_id);
      chxj_delete_cookie_expire(r, old_cookie_id);
    }
  }

  if (! has_cookie) {
    DBG(r, "no cookie");
    DBG(r, "end chxj_save_cookie()");
    return NULL;
  }

  /*
   * create val
   */
  cookie->cookie_headers = (apr_array_header_t*)apr_table_elts(new_cookie_table);
  store_string = apr_palloc(r->pool, 1);
  store_string[0] = 0;
  hentryp = (apr_table_entry_t*)cookie->cookie_headers->elts;

  for (ii=0; ii<cookie->cookie_headers->nelts; ii++) {
    if (ii) store_string = apr_pstrcat(r->pool,
                               store_string, 
                               "\n",
                               NULL);

    store_string = apr_pstrcat(r->pool, 
                               store_string, 
                               hentryp[ii].key, 
                               "=",
                               hentryp[ii].val, 
                               NULL);
  }

  if (old_cookie_id && IS_COOKIE_LAZY(dconf)) {
    DBG(r, "LAZY COOKIE save");
    cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id);
  }
  else {
    DBG(r, "NO LAZY COOKIE save. old_cookie_id:[%s] LAZY:[%d]", old_cookie_id,IS_COOKIE_LAZY(dconf));
    cookie->cookie_id = alloc_cookie_id(r);
  }

  {
    int done_proc = 0;
#if defined(USE_MYSQL_COOKIE)
    if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
      if (! chxj_save_cookie_mysql(r, dconf, cookie->cookie_id, store_string)) {
        ERR(r, "%s:%d faild: chxj_save_cookie_mysql() cookie_id:[%s]", APLOG_MARK,cookie->cookie_id);
        cookie = NULL;
        goto on_error;
      }
      done_proc = 1;
    }
#endif
#if defined(USE_MEMCACHE_COOKIE)
    if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
      if (! chxj_save_cookie_memcache(r, dconf, cookie->cookie_id, store_string)) {
        ERR(r, "%s:%d failed: chxj_save_cookie_memcache() cookie_id:[%s]", APLOG_MARK, cookie->cookie_id);
        cookie = NULL;
        goto on_error;
      }
      done_proc = 1;
    }
#endif
    if (IS_COOKIE_STORE_DBM(dconf->cookie_store_type) || ! done_proc) {
      if (! chxj_save_cookie_dbm(r, dconf, cookie->cookie_id, store_string)) {
        ERR(r, "%s:%d failed: chxj_save_cookie_dbm() cookie_id:[%s]", APLOG_MARK, cookie->cookie_id);
        cookie = NULL;
        goto on_error;
      }
    }
  }

  if (cookie) {
    chxj_save_cookie_expire(r, cookie);
  }

on_error:
  DBG(r, "end chxj_save_cookie()");
  return cookie;
}