Beispiel #1
0
/**
 * Compare two resources to check if they are the same
 * @param res1 Resource 1
 * @param res2 Resource 2
 * @return     1 if they are the same
 */
static int dav_ns_is_same(const dav_resource *res1, const dav_resource *res2)
{
  const char *destination;
  apr_uri_t  uri1, uri2;

  /* Parse resource 1 */
  apr_uri_parse(res1->pool, res1->uri, &uri1);

  /* Parse resource 2 */
  destination = apr_table_get(res2->info->request->headers_in, "destination");
  if (destination)
    apr_uri_parse(res2->pool, destination, &uri2);
  else
    apr_uri_parse(res2->pool, res2->uri, &uri2);

  /* Host may not appear */
  if (!uri1.hostname)
    uri1.hostname = res1->info->request->server->server_hostname;
  if (!uri2.hostname)
    uri2.hostname = res2->info->request->server->server_hostname;

  /* Compare */
  return strcmp(uri1.hostname, uri2.hostname) == 0 &&
         strcmp(uri1.path, uri2.path) == 0;
}
Beispiel #2
0
static const char *
SVNMasterURI_cmd(cmd_parms *cmd, void *config, const char *arg1)
{
  dir_conf_t *conf = config;
  apr_uri_t parsed_uri;
  const char *uri_base_name = "";

  /* SVNMasterURI requires mod_proxy and mod_proxy_http
   * (r->handler = "proxy-server" in mirror.c), make sure
   * they are present. */
  if (ap_find_linked_module("mod_proxy.c") == NULL)
    return "module mod_proxy not loaded, required for SVNMasterURI";
  if (ap_find_linked_module("mod_proxy_http.c") == NULL)
    return "module mod_proxy_http not loaded, required for SVNMasterURI";
  if (APR_SUCCESS != apr_uri_parse(cmd->pool, arg1, &parsed_uri))
    return "unable to parse SVNMasterURI value";
  if (parsed_uri.path)
    uri_base_name = svn_urlpath__basename(
                        svn_urlpath__canonicalize(parsed_uri.path, cmd->pool),
                        cmd->pool);
  if (! *uri_base_name)
    return "SVNMasterURI value must not be a server root";

  conf->master_uri = apr_pstrdup(cmd->pool, arg1);

  return NULL;
}
Beispiel #3
0
/*
 * parse a URL according to one of two schemes (NULL for any)
 */
static const char * oidc_valid_url_scheme(apr_pool_t *pool, const char *arg,
		const char *scheme1, const char *scheme2) {

	apr_uri_t uri;

	if (apr_uri_parse(pool, arg, &uri) != APR_SUCCESS) {
		return apr_psprintf(pool, "'%s' cannot be parsed as a URL", arg);
	}

	if (uri.scheme == NULL) {
		return apr_psprintf(pool,
				"'%s' cannot be parsed as a URL (no scheme set)", arg);
	}

	if ((scheme1 != NULL) && (apr_strnatcmp(uri.scheme, scheme1) != 0)) {
		if ((scheme2 != NULL) && (apr_strnatcmp(uri.scheme, scheme2) != 0)) {
			return apr_psprintf(pool,
					"'%s' cannot be parsed as a \"%s\" or \"%s\" URL (scheme == %s)!",
					arg, scheme1, scheme2, uri.scheme);
		} else if (scheme2 == NULL) {
			return apr_psprintf(pool,
					"'%s' cannot be parsed as a \"%s\" URL (scheme == %s)!",
					arg, scheme1, uri.scheme);
		}
	}

	if (uri.hostname == NULL) {
		return apr_psprintf(pool,
				"'%s' cannot be parsed as a valid URL (no hostname set, check your slashes)",
				arg);
	}

	return NULL;
}
Beispiel #4
0
apr_status_t use_new_connection(test_baton_t *tb,
                                apr_pool_t *pool)
{
    apr_uri_t url;
    apr_status_t status;

    if (tb->connection)
        cleanup_conn(tb->connection);
    tb->connection = NULL;

    status = apr_uri_parse(pool, tb->serv_url, &url);
    if (status != APR_SUCCESS)
        return status;

    status = serf_connection_create2(&tb->connection, tb->context,
                                     url,
                                     tb->conn_setup,
                                     tb,
                                     default_closed_connection,
                                     tb,
                                     pool);
    apr_pool_cleanup_register(pool, tb->connection, cleanup_conn,
                              apr_pool_cleanup_null);

    return status;
}
Beispiel #5
0
svn_error_t *
svn_ra_neon__copy_href(svn_stringbuf_t *dst, const char *src,
                       apr_pool_t *pool)
{
  /* parse the PATH element out of the URL and store it.

     ### do we want to verify the rest matches the current session?

     Note: mod_dav does not (currently) use an absolute URL, but simply a
     server-relative path (i.e. this uri_parse is effectively a no-op).
  */

  apr_uri_t uri;
  apr_status_t apr_status;

  /* SRC can have trailing '/' */
  if (svn_path_is_url(src))
    src = svn_uri_canonicalize(src, pool);
  else
    src = svn_urlpath__canonicalize(src, pool);
  apr_status = apr_uri_parse(pool, src, &uri);

  if (apr_status != APR_SUCCESS)
    return svn_error_wrap_apr(apr_status,
                              _("Unable to parse URL '%s'"),
                              src);

  svn_stringbuf_setempty(dst);
  svn_stringbuf_appendcstr(dst, uri.path);

  return SVN_NO_ERROR;
}
END_TEST

void core_setup(void) {
  const unsigned int kIdx = 0;
  const unsigned int kEls = kIdx + 1;
  cas_cfg *cfg = NULL;
  cas_dir_cfg *d_cfg = NULL;
  apr_uri_t login;
  request = (request_rec *) malloc(sizeof(request_rec));

  apr_pool_create(&pool, NULL);
  request->pool = pool;
  /* set up the request */
  request->headers_in = apr_table_make(request->pool, 0);
  request->headers_out = apr_table_make(request->pool, 0);
  request->err_headers_out = apr_table_make(request->pool, 0);

  apr_table_set(request->headers_in, "Host", "foo.example.com");
  apr_table_set(request->headers_in, "CAS_foo", "foo-value");
  apr_table_set(request->headers_in, "Cookie", "foo=bar; "
                CAS_DEFAULT_COOKIE "=0123456789abcdef; baz=zot");

  request->server = apr_pcalloc(request->pool,
                                sizeof(struct server_rec));
  request->connection = apr_pcalloc(request->pool, sizeof(struct conn_rec));
  request->connection->local_addr = apr_pcalloc(request->pool,
                                                sizeof(apr_sockaddr_t));


  apr_pool_userdata_set("https", "scheme", NULL, request->pool);
  request->server->server_hostname = "foo.example.com";
  request->connection->local_addr->port = 80;
  request->unparsed_uri = "/foo?bar=baz&zot=qux";
  request->uri = "/foo";
  request->args = "bar=baz&zot=qux";
  apr_uri_parse(request->pool, "http://foo.example.com/foo?bar=baz&zot=qux",
                &request->parsed_uri);

  /* set up the per server, and per directory configs */
  auth_cas_module.module_index = kIdx;
  cfg = cas_create_server_config(request->pool, request->server);
  cfg->CASDebug = TRUE;
  memset(&login, 0, sizeof(login));
  login.scheme = "https";
  login.hostname = "login.example.com";
  login.path = "/cas/login";
  login.port = 0;
  memcpy(&cfg->CASLoginURL, &login, sizeof(apr_uri_t));

  d_cfg = cas_create_dir_config(request->pool, NULL);

  request->request_config = apr_pcalloc(request->pool,
                                      sizeof(ap_conf_vector_t *)*kEls);  
  request->server->module_config = apr_pcalloc(request->pool,
                                               sizeof(ap_conf_vector_t *)*kEls);
  request->per_dir_config = apr_pcalloc(request->pool,
                                        sizeof(ap_conf_vector_t *)*kEls);
  ap_set_module_config(request->server->module_config, &auth_cas_module, cfg);
  ap_set_module_config(request->per_dir_config, &auth_cas_module, d_cfg);
}
Beispiel #7
0
int main(int argc, char **argv)
{
	if (argc < 2) 
	{
		usage();
		exit(1);
	}

	apr_uri_t info;
	apr_initialize();

	apr_pool_create(&p, NULL);
	apr_uri_parse(p, argv[1], &info);

	printf("scheme: %s\n", info.scheme);
	printf("hostname: %s\n", info.hostname);
	printf("hostinfo: %s\n", info.hostinfo);
	printf("port: %s\n", info.port_str);
	printf("path: %s\n", info.path);
	printf("query: %s\n", info.query);

	apr_pool_destroy(p);

	return 0;
}
Beispiel #8
0
/*
 * check if the specified entry in metadata is a valid URI
 */
static apr_byte_t oidc_metadata_is_valid_uri(request_rec *r, const char *type,
		const char *issuer, const json_t *json, const char *key,
		apr_byte_t is_mandatory) {

	apr_uri_t uri;
	json_t *entry = NULL;

	entry = json_object_get(json, key);

	if (entry == NULL) {
		if (is_mandatory) {
			oidc_error(r,
					"%s (%s) JSON metadata does not contain the mandatory \"%s\" entry",
					type, issuer, key);
		}
		return (!is_mandatory);
	}

	if (!json_is_string(entry)) {
		oidc_error(r,
				"%s (%s) JSON metadata contains a \"%s\" entry, but it is not a string value",
				type, issuer, key);
		return FALSE;
	}

	if (apr_uri_parse(r->pool, json_string_value(entry), &uri) != APR_SUCCESS) {
		oidc_error(r,
				"%s (%s) JSON metadata contains a \"%s\" entry, but it is not a valid URI",
				type, issuer, key);
		return FALSE;
	}

	return TRUE;
}
Beispiel #9
0
int lua_apr_ldap(lua_State *L)
{
  lua_apr_ldap_object *object;
  apr_ldap_err_t *error = NULL;
  apr_pool_t *memory_pool;
  apr_status_t status;
  int portno, secure = APR_LDAP_NONE;
  const char *url, *hostname;
  apr_uri_t info;

  lua_settop(L, 2);
  memory_pool = to_pool(L);
  url = luaL_optstring(L, 1, "ldap://127.0.0.1");
  if (lua_toboolean(L, 2))
    secure = APR_LDAP_STARTTLS;

  /* Get and parse the LDAP URL. */
  status = apr_uri_parse(memory_pool, url, &info);
  if (status != APR_SUCCESS)
    return push_error_status(L, status);

  /* Get the host name and port number of the LDAP server. */
  hostname = (info.hostname != NULL) ? info.hostname : "127.0.0.1";
  portno = (info.port_str != NULL) ? info.port : APR_URI_LDAP_DEFAULT_PORT;

  /* Use a secure connection? */
  if (info.scheme != NULL && strcmp(info.scheme, "ldaps") == 0)
    secure = APR_LDAP_SSL;

  /* Create the userdata object and memory pool. */
  object = new_object(L, &lua_apr_ldap_type);
  status = apr_pool_create(&object->pool, NULL);
  if (status != APR_SUCCESS)
    return push_error_status(L, status);

  /* Automatically call apr_ldap_ssl_init() as needed because this
   * stuff is so low level it doesn't make sense to expose it to Lua. */
  if (secure != APR_LDAP_NONE && !ldap_ssl_inited) {
    if (ldap_pool == NULL) {
      /* Create a private memory pool for SSL and rebind support. */
      status = apr_pool_create(&ldap_pool, NULL);
      if (status != APR_SUCCESS)
        return push_error_status(L, status);
    }
    status = apr_ldap_ssl_init(ldap_pool, NULL, 0, &error);
    if (status != APR_SUCCESS)
      return push_error_status(L, status);
    ldap_ssl_inited = 1;
  }

  /* Open the LDAP connection. */
  status = apr_ldap_init(object->pool, &object->ldap, hostname, portno, secure, &error);
  if (status != APR_SUCCESS)
    return push_ldap_error(L, status, error);

  return 1;
}
END_TEST

START_TEST(getCASScope_test) {
  apr_uri_parse(request->pool, "http://www.example.com/foo/bar/baz.html",
                &request->parsed_uri);
  /* different control paths need to be tested -- c->CASDebug, c->CASGateway
   * for correct and incorrect path, CASRenew, ... */
  fail();
}
END_TEST

START_TEST(getCASPath_test) {
  char *path;
  apr_uri_parse(request->pool, "http://www.example.com/foo/bar/baz.html",
                &request->parsed_uri);

  path = getCASPath(request);
  fail_unless(strcmp(path, "/foo/bar/") == 0);
}
Beispiel #12
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;
}
Beispiel #13
0
int url_InitFile(const char* fileName, apr_pool_t* pool)
{
  apr_status_t s;
  apr_file_t* file;
  char buf[URL_BUF_LEN];
  LineState line;

  urlCount = 0;
  urlSize = INITIAL_URLS;
  urls = (URLInfo*)malloc(sizeof(URLInfo) * INITIAL_URLS);

  s = apr_file_open(&file, fileName, APR_READ, APR_OS_DEFAULT, pool);
  if (s != APR_SUCCESS) {
    fprintf(stderr, "Can't open \"%s\"\n", fileName);
    return -1;
  }

  linep_Start(&line, buf, URL_BUF_LEN, 0);
  s = linep_ReadFile(&line, file);
  if (s != APR_SUCCESS) {
    apr_file_close(file);
    return -1;
  }

  do {
    while (linep_NextLine(&line)) {
      char* urlStr = linep_GetLine(&line);
      if (urlCount == urlSize) {
	urlSize *= 2;
	urls = (URLInfo*)realloc(urls, sizeof(URLInfo) * urlSize);
      }
      s = apr_uri_parse(pool, urlStr, &(urls[urlCount].url));
      if (s != APR_SUCCESS) {
	fprintf(stderr, "Invalid URL \"%s\"\n", urlStr);
	apr_file_close(file);
	return -1;
      }
      if (initUrl(&(urls[urlCount]), pool) != 0) {
	apr_file_close(file);
	return -1;
      }
      urlCount++;
    }
    linep_Reset(&line);
    s = linep_ReadFile(&line, file);
  } while (s == APR_SUCCESS);

  printf("Read %i URLs from \"%s\"\n", urlCount, fileName);

  apr_file_close(file);
  return 0;
}
END_TEST

START_TEST(getCASLoginURL_test) {
  cas_cfg *c = ap_get_module_config(request->server->module_config,
                                    &auth_cas_module);
  const char *url = "https://*****:*****@login.example.com/cas/login?foo=bar";
  char *rv;
  apr_uri_t parsed_url;
  apr_uri_parse(request->pool, url, &parsed_url);
  memcpy(&c->CASLoginURL, &parsed_url, sizeof(apr_uri_t));
  rv = getCASLoginURL(request, c);
  fail_unless(strcmp(rv, "https://login.example.com/cas/login") == 0);
}
END_TEST

START_TEST(removeGatewayCookie_test) {
  const char *expected = "MOD_CAS_G=TRUE;Secure;Path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT";
  const char *ernVal;
  const char *response =
	"<cas:serviceResponse xmlns:cas=\"http://www.yale.edu/tp/cas\">"
	"<cas:authenticationSuccess>"
	"<cas:user>good</cas:user>"
	"</cas:authenticationSuccess>"
	"</cas:serviceResponse>";
  int rv;
  cas_cfg *c = ap_get_module_config(request->server->module_config,
                                    &auth_cas_module);
  c->CASCookiePath = "/tmp/";

  /*
   * setup request as if we've just returned from a gateway trip,
   * with a gateway cookie and a cas ticket
   */
  apr_table_set(request->headers_in, "Cookie", "MOD_CAS_G=TRUE; cookie_name=cookie_value ");
  request->unparsed_uri = "/foo?ticket=ST-1234";
  request->uri = "/foo";
  request->args = apr_pstrdup(request->pool, "ticket=ST-1234");
  request->connection->local_addr->port = 443;
  request->ap_auth_type = "cas";
  fail_unless(strcmp(request->args, "ticket=ST-1234") == 0, request->args);
  apr_uri_parse(request->pool, "http://foo.example.com/foo?ticket=ST-12345",
                &request->parsed_uri);

  /*
   * setup fake serviceValidate response from cas server
   */
  set_curl_response(response);

  /*
   * authenticate the user
   */
  c->CASCertificatePath = "/";
  rv = cas_authenticate(request);
  fail_unless(rv == HTTP_MOVED_TEMPORARILY, "cas_authenticate failed");
  fail_unless(strcmp(request->user, "good") == 0, request->user);

  /*
   * verify that the Set-Cookie header removes the gateway cookie
   */
  apr_table_compress(request->err_headers_out, APR_OVERLAP_TABLES_MERGE);
  ernVal = apr_table_get(request->err_headers_out, "Set-Cookie");
  fail_unless(strstr(ernVal, expected) != NULL, ernVal);
}
Beispiel #16
0
int url_InitOne(const char* urlStr, apr_pool_t* pool)
{
  apr_status_t s;

  urlCount = urlSize = 1;
  urls = (URLInfo*)malloc(sizeof(URLInfo));

  s = apr_uri_parse(pool, urlStr, &(urls[0].url));
  if (s != APR_SUCCESS) {
    fprintf(stderr, "Invalid URL\n");
    return -1;
  }

  return initUrl(&(urls[0]), pool);
}
/* Return the responder URI object which should be used in the given
 * configuration for the given certificate, or NULL if none can be
 * determined. */
static apr_uri_t *determine_responder_uri(SSLSrvConfigRec *sc, X509 *cert,
                                          conn_rec *c, apr_pool_t *p)
{
    apr_uri_t *u = apr_palloc(p, sizeof *u);
    const char *s;
    apr_status_t rv;

    /* Use default responder URL if forced by configuration, else use
     * certificate-specified responder, falling back to default if
     * necessary and possible. */
    if (sc->server->ocsp_force_default == TRUE) {
        s = sc->server->ocsp_responder;
    }
    else {
        s = extract_responder_uri(cert, p);

        if (s == NULL && sc->server->ocsp_responder) {
            s = sc->server->ocsp_responder;
        }
    }

    if (s == NULL) {
        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01918)
                      "no OCSP responder specified in certificate and "
                      "no default configured");
        return NULL;
    }

    rv = apr_uri_parse(p, s, u);
    if (rv || !u->hostname) {
        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(01919)
                      "failed to parse OCSP responder URI '%s'", s);
        return NULL;
    }

    if (strcasecmp(u->scheme, "http") != 0) {
        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(01920)
                      "cannot handle OCSP responder URI '%s'", s);
        return NULL;
    }

    if (!u->port) {
        u->port = apr_uri_port_of_scheme(u->scheme);
    }

    return u;
}
END_TEST

START_TEST(getCASService_root_proxied_test) {
  cas_cfg *c = ap_get_module_config(request->server->module_config,
                                    &auth_cas_module);
  char *service;
  const char *expected_service = 
      "http%3a%2f%2frev-proxy.example.com%2fapp%2ffoo%3fbar%3dbaz%26zot%3dqux";
  const char *root = "http://rev-proxy.example.com/app";
  apr_uri_t parsed_url;
  apr_uri_parse(request->pool, root, &parsed_url);
  apr_pool_userdata_set("https", "scheme", NULL, request->pool);
  request->connection->local_addr->port = 9999;
  memcpy(&c->CASRootProxiedAs, &parsed_url, sizeof(apr_uri_t));

  service = getCASService(request, c);
  fail_unless(strcmp(service, expected_service) == 0);
}
Beispiel #19
0
static apr_status_t setup(test_baton_t **tb_p,
                          serf_connection_setup_t conn_setup,
                          int use_proxy,
                          apr_pool_t *pool)
{
    apr_status_t status;
    test_baton_t *tb;
    apr_uri_t url;

    tb = apr_pcalloc(pool, sizeof(*tb));
    *tb_p = tb;

    tb->pool = pool;
    tb->context = serf_context_create(pool);
    tb->bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL);

    status = default_server_address(&tb->serv_addr, pool);
    if (status != APR_SUCCESS)
        return status;

    if (use_proxy) {
        status = default_proxy_address(&tb->proxy_addr, pool);
        if (status != APR_SUCCESS)
            return status;

        /* Configure serf to use the proxy server */
        serf_config_proxy(tb->context, tb->proxy_addr);
    }

    status = apr_uri_parse(pool, SERV_URL, &url);
    if (status != APR_SUCCESS)
        return status;

    status = serf_connection_create2(&tb->connection, tb->context,
                                     url,
                                     conn_setup ? conn_setup :
                                         default_conn_setup,
                                     tb,
                                     default_closed_connection,
                                     tb,
                                     pool);

    return status;
}
Beispiel #20
0
static apr_status_t
create_client_socket(apr_socket_t **skt,
                     serv_ctx_t *servctx,
                     const char *url)
{
    apr_sockaddr_t *address;
    apr_uri_t uri;
    apr_status_t status;

    status = apr_uri_parse(servctx->pool, url, &uri);
    if (status != APR_SUCCESS)
        return status;

    status = apr_sockaddr_info_get(&address,
                                   uri.hostname,
                                   APR_UNSPEC,
                                   uri.port,
                                   0,
                                   servctx->pool);
    if (status != APR_SUCCESS)
        return status;

    status = apr_socket_create(skt,
                               address->family,
                               SOCK_STREAM,
#if APR_MAJOR_VERSION > 0
                               APR_PROTO_TCP,
#endif
                               servctx->pool);
    if (status != APR_SUCCESS)
        return status;

    /* Set the socket to be non-blocking */
    status = apr_socket_timeout_set(*skt, 0);
    if (status != APR_SUCCESS)
        return status;

    status = apr_socket_connect(*skt, address);
    if (status != APR_SUCCESS && !APR_STATUS_IS_EINPROGRESS(status))
        return status;

    return APR_SUCCESS;
}
Beispiel #21
0
/* Sets basic connection info */
static const char *set_log_sql_info(cmd_parms *cmd, void *dummy,
						const char *host, const char *user, const char *pwd)
{
	if (!user) { /* user is null, so only one arg passed */
	    /* TODO: to more error checking/force all params to be set */
		apr_uri_t uri;
		apr_uri_parse(cmd->pool, host, &uri);
		if (uri.scheme) {
			set_dbparam(cmd, NULL, "driver", uri.scheme);
		}
		if (uri.hostname) {
			set_dbparam(cmd, NULL, "hostname", uri.hostname);
		}
		if (uri.user) {
			set_dbparam(cmd, NULL, "username", uri.user);
		}
		if (uri.password) {
			set_dbparam(cmd, NULL, "password", uri.password);
		}
		if (uri.port_str) {
			set_dbparam(cmd, NULL, "port", uri.port_str);
		}
		if (uri.path) {
			/* extract Database name */
			char *off = ap_strchr(++uri.path,'/');
			if (off)
				*off='\0';
			set_dbparam(cmd, NULL, "database", uri.path);

		}
	} else {
		if (*host != '.') {
			set_dbparam(cmd, NULL, "hostname", host);
		}
		if (*user != '.') {
			set_dbparam(cmd, NULL, "username", user);
		}
		if (*pwd != '.') {
			set_dbparam(cmd, NULL, "password", pwd);
		}
	}
	return NULL;
}
Beispiel #22
0
apr_status_t
serf__setup_request_digest_auth(peer_t peer,
                                int code,
                                serf_connection_t *conn,
                                serf_request_t *request,
                                const char *method,
                                const char *uri,
                                serf_bucket_t *hdrs_bkt)
{
    digest_authn_info_t *digest_info = (peer == HOST) ? conn->authn_baton :
        conn->proxy_authn_baton;
    apr_status_t status = APR_SUCCESS;

    if (digest_info && digest_info->realm) {
        const char *value;
        apr_uri_t parsed_uri;

        /* TODO: per request pool? */

        /* Extract path from uri. */
        status = apr_uri_parse(conn->pool, uri, &parsed_uri);

        /* Build a new Authorization header. */
        digest_info->header = (peer == HOST) ? "Authorization" :
            "Proxy-Authorization";
        value = build_auth_header(digest_info, parsed_uri.path, method,
                                  conn->pool);

        serf_bucket_headers_setn(hdrs_bkt, digest_info->header,
                                 value);
        digest_info->digest_nc++;

        /* Store the uri of this request on the serf_request_t object, to make
           it available when validating the Authentication-Info header of the
           matching response. */
        request->auth_baton = parsed_uri.path;
    }

    return status;
}
Beispiel #23
0
apr_status_t dav_svn__location_body_filter(ap_filter_t *f,
                                           apr_bucket_brigade *bb)
{
    request_rec *r = f->r;
    locate_ctx_t *ctx = f->ctx;
    apr_bucket *bkt;
    const char *master_uri, *root_dir, *canonicalized_uri;
    apr_uri_t uri;

    /* Don't filter if we're in a subrequest or we aren't setup to
       proxy anything. */
    master_uri = dav_svn__get_master_uri(r);
    if (r->main || !master_uri) {
        ap_remove_output_filter(f);
        return ap_pass_brigade(f->next, bb);
    }

    /* And don't filter if our search-n-replace would be a noop anyway
       (that is, if our root path matches that of the master server). */
    apr_uri_parse(r->pool, master_uri, &uri);
    root_dir = dav_svn__get_root_dir(r);
    canonicalized_uri = svn_urlpath__canonicalize(uri.path, r->pool);
    if (strcmp(canonicalized_uri, root_dir) == 0) {
        ap_remove_output_filter(f);
        return ap_pass_brigade(f->next, bb);
    }

    /* ### FIXME: GET and PROPFIND requests that make it here must be
       ### referring to data inside commit transactions-in-progress.
       ### We've got to be careful not to munge the versioned data
       ### they return in the process of trying to do URI fix-ups.
       ### See issue #3445 for details. */

    /* We are url encoding the current url and the master url
       as incoming(from master) request body has it encoded already. */
    canonicalized_uri = svn_path_uri_encode(canonicalized_uri, r->pool);
    root_dir = svn_path_uri_encode(root_dir, r->pool);
    if (!f->ctx) {
        ctx = f->ctx = apr_pcalloc(r->pool, sizeof(*ctx));
        ctx->remotepath = canonicalized_uri;
        ctx->remotepath_len = strlen(ctx->remotepath);
        ctx->localpath = root_dir;
        ctx->localpath_len = strlen(ctx->localpath);
        ctx->pattern = apr_strmatch_precompile(r->pool, ctx->remotepath, 1);
        ctx->pattern_len = ctx->remotepath_len;
    }

    bkt = APR_BRIGADE_FIRST(bb);
    while (bkt != APR_BRIGADE_SENTINEL(bb)) {

        const char *data, *match;
        apr_size_t len;

        /* read */
        apr_bucket_read(bkt, &data, &len, APR_BLOCK_READ);
        match = apr_strmatch(ctx->pattern, data, len);
        if (match) {
            apr_bucket *next_bucket;
            apr_bucket_split(bkt, match - data);
            next_bucket = APR_BUCKET_NEXT(bkt);
            apr_bucket_split(next_bucket, ctx->pattern_len);
            bkt = APR_BUCKET_NEXT(next_bucket);
            apr_bucket_delete(next_bucket);
            next_bucket = apr_bucket_pool_create(ctx->localpath,
                                                 ctx->localpath_len,
                                                 r->pool, bb->bucket_alloc);
            APR_BUCKET_INSERT_BEFORE(bkt, next_bucket);
        }
        else {
            bkt = APR_BUCKET_NEXT(bkt);
        }
    }
    return ap_pass_brigade(f->next, bb);
}
Beispiel #24
0
static request_rec * test_setup(apr_pool_t *pool) {
	const unsigned int kIdx = 0;
	const unsigned int kEls = kIdx + 1;
	request_rec *request = (request_rec *) apr_pcalloc(pool,
			sizeof(request_rec));

	request->pool = pool;

	request->headers_in = apr_table_make(request->pool, 0);
	request->headers_out = apr_table_make(request->pool, 0);
	request->err_headers_out = apr_table_make(request->pool, 0);

	apr_table_set(request->headers_in, "Host", "www.example.com");
	apr_table_set(request->headers_in, "OIDC_foo", "some-value");
	apr_table_set(request->headers_in, "Cookie", "foo=bar; "
			"mod_auth_openidc_session" "=0123456789abcdef; baz=zot");

	request->server = apr_pcalloc(request->pool, sizeof(struct server_rec));
	request->server->process = apr_pcalloc(request->pool,
			sizeof(struct process_rec));
	request->server->process->pool = request->pool;
	request->connection = apr_pcalloc(request->pool, sizeof(struct conn_rec));
	request->connection->local_addr = apr_pcalloc(request->pool,
			sizeof(apr_sockaddr_t));

	apr_pool_userdata_set("https", "scheme", NULL, request->pool);
	request->server->server_hostname = "www.example.com";
	request->connection->local_addr->port = 80;
	request->unparsed_uri = "/bla?foo=bar&param1=value1";
	request->args = "foo=bar&param1=value1";
	apr_uri_parse(request->pool,
			"http://www.example.com/bla?foo=bar&param1=value1",
			&request->parsed_uri);

	auth_openidc_module.module_index = kIdx;
	oidc_cfg *cfg = oidc_create_server_config(request->pool, request->server);
	cfg->provider.issuer = "https://idp.example.com";
	cfg->provider.authorization_endpoint_url =
			"https://idp.example.com/authorize";
	cfg->provider.scope = "openid";
	cfg->provider.client_id = "client_id";
	cfg->redirect_uri = "https://www.example.com/protected/";

	oidc_dir_cfg *d_cfg = oidc_create_dir_config(request->pool, NULL);

	request->server->module_config = apr_pcalloc(request->pool,
			sizeof(ap_conf_vector_t *) * kEls);
	request->per_dir_config = apr_pcalloc(request->pool,
			sizeof(ap_conf_vector_t *) * kEls);
	ap_set_module_config(request->server->module_config, &auth_openidc_module,
			cfg);
	ap_set_module_config(request->per_dir_config, &auth_openidc_module, d_cfg);

	cfg->cache = &oidc_cache_shm;
	cfg->cache_cfg = NULL;
	cfg->cache_shm_size_max = 500;
	cfg->cache_shm_entry_size_max = 16384 + 255 + 17;
	cfg->cache->post_config(request->server);

	return request;
}
Beispiel #25
0
int main(int argc, const char **argv)
{
    apr_status_t status;
    apr_pool_t *pool;
    apr_sockaddr_t *address;
    serf_context_t *context;
    serf_connection_t *connection;
    app_baton_t app_ctx;
    handler_baton_t *handler_ctx;
    apr_uri_t url;
    const char *raw_url, *method;
    int count;
    apr_getopt_t *opt;
    char opt_c;
    char *authn = NULL;
    const char *opt_arg;

    /* For the parser threads */
    apr_thread_t *thread[3];
    apr_threadattr_t *tattr;
    apr_status_t parser_status;
    parser_baton_t *parser_ctx;

    apr_initialize();
    atexit(apr_terminate);

    apr_pool_create(&pool, NULL);
    apr_atomic_init(pool);
    /* serf_initialize(); */

    /* Default to one round of fetching. */
    count = 1;
    /* Default to GET. */
    method = "GET";

    apr_getopt_init(&opt, pool, argc, argv);

    while ((status = apr_getopt(opt, "a:hv", &opt_c, &opt_arg)) ==
           APR_SUCCESS) {
        int srclen, enclen;

        switch (opt_c) {
        case 'a':
            srclen = strlen(opt_arg);
            enclen = apr_base64_encode_len(srclen);
            authn = apr_palloc(pool, enclen + 6);
            strcpy(authn, "Basic ");
            (void) apr_base64_encode(&authn[6], opt_arg, srclen);
            break;
        case 'h':
            print_usage(pool);
            exit(0);
            break;
        case 'v':
            puts("Serf version: " SERF_VERSION_STRING);
            exit(0);
        default:
            break;
        }
    }

    if (opt->ind != opt->argc - 1) {
        print_usage(pool);
        exit(-1);
    }

    raw_url = argv[opt->ind];

    apr_uri_parse(pool, raw_url, &url);
    if (!url.port) {
        url.port = apr_uri_port_of_scheme(url.scheme);
    }
    if (!url.path) {
        url.path = "/";
    }

    if (strcasecmp(url.scheme, "https") == 0) {
        app_ctx.using_ssl = 1;
    }
    else {
        app_ctx.using_ssl = 0;
    }

    status = apr_sockaddr_info_get(&address,
                                   url.hostname, APR_UNSPEC, url.port, 0,
                                   pool);
    if (status) {
        printf("Error creating address: %d\n", status);
        exit(1);
    }

    context = serf_context_create(pool);

    /* ### Connection or Context should have an allocator? */
    app_ctx.bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL);
    app_ctx.ssl_ctx = NULL;
    app_ctx.authn = authn;

    connection = serf_connection_create(context, address,
                                        conn_setup, &app_ctx,
                                        closed_connection, &app_ctx,
                                        pool);

    handler_ctx = (handler_baton_t*)serf_bucket_mem_alloc(app_ctx.bkt_alloc,
                                                      sizeof(handler_baton_t));
    handler_ctx->allocator = app_ctx.bkt_alloc;
    handler_ctx->doc_queue = apr_array_make(pool, 1, sizeof(doc_path_t*));
    handler_ctx->doc_queue_alloc = app_ctx.bkt_alloc;

    handler_ctx->requests_outstanding =
        (apr_uint32_t*)serf_bucket_mem_alloc(app_ctx.bkt_alloc,
                                             sizeof(apr_uint32_t));
    apr_atomic_set32(handler_ctx->requests_outstanding, 0);
    handler_ctx->hdr_read = 0;

    parser_ctx = (void*)serf_bucket_mem_alloc(app_ctx.bkt_alloc,
                                       sizeof(parser_baton_t));

    parser_ctx->requests_outstanding = handler_ctx->requests_outstanding;
    parser_ctx->connection = connection;
    parser_ctx->app_ctx = &app_ctx;
    parser_ctx->doc_queue = handler_ctx->doc_queue;
    parser_ctx->doc_queue_alloc = handler_ctx->doc_queue_alloc;
    /* Restrict ourselves to this host. */
    parser_ctx->hostinfo = url.hostinfo;

    status = apr_thread_mutex_create(&parser_ctx->mutex,
                                     APR_THREAD_MUTEX_DEFAULT, pool);
    if (status) {
        printf("Couldn't create mutex %d\n", status);
        return status;
    }

    status = apr_thread_cond_create(&parser_ctx->condvar, pool);
    if (status) {
        printf("Couldn't create condvar: %d\n", status);
        return status;
    }

    /* Let the handler now which condvar to use. */
    handler_ctx->doc_queue_condvar = parser_ctx->condvar;

    apr_threadattr_create(&tattr, pool);

    /* Start the parser thread. */
    apr_thread_create(&thread[0], tattr, parser_thread, parser_ctx, pool);

    /* Deliver the first request. */
    create_request(url.hostinfo, url.path, NULL, NULL, parser_ctx, pool);

    /* Go run our normal thread. */
    while (1) {
        int tries = 0;

        status = serf_context_run(context, SERF_DURATION_FOREVER, pool);
        if (APR_STATUS_IS_TIMEUP(status))
            continue;
        if (status) {
            char buf[200];

            printf("Error running context: (%d) %s\n", status,
                   apr_strerror(status, buf, sizeof(buf)));
            exit(1);
        }

        /* We run this check to allow our parser threads to add more
         * requests to our queue.
         */
        for (tries = 0; tries < 3; tries++) {
            if (!apr_atomic_read32(handler_ctx->requests_outstanding)) {
#ifdef SERF_VERBOSE
                printf("Waiting...");
#endif
                apr_sleep(100000);
#ifdef SERF_VERBOSE
                printf("Done\n");
#endif
            }
            else {
                break;
            }
        }
        if (tries >= 3) {
            break;
        }
        /* Debugging purposes only! */
        serf_debug__closed_conn(app_ctx.bkt_alloc);
    }

    printf("Quitting...\n");
    serf_connection_close(connection);

    /* wake up the parser via condvar signal */
    apr_thread_cond_signal(parser_ctx->condvar);

    status = apr_thread_join(&parser_status, thread[0]);
    if (status) {
        printf("Error joining thread: %d\n", status);
        return status;
    }

    serf_bucket_mem_free(app_ctx.bkt_alloc, handler_ctx->requests_outstanding);
    serf_bucket_mem_free(app_ctx.bkt_alloc, parser_ctx);

    apr_pool_destroy(pool);
    return 0;
}
Beispiel #26
0
static apr_status_t put_req(const char *c, const char *orig_path,
                            parser_baton_t *ctx, apr_pool_t *pool)
{
    apr_status_t status;
    apr_uri_t url;

    /* Build url */
#ifdef SERF_VERBOSE
    printf("Url discovered: %s\n", c);
#endif

    status = apr_uri_parse(pool, c, &url);

    /* We got something that was minimally useful. */
    if (status == 0 && url.path) {
        const char *path, *query, *fragment;

        /* This is likely a relative URL. So, merge and hope for the
         * best.
         */
        if (!url.hostinfo && url.path[0] != '/') {
            struct iovec vec[2];
            char *c;
            apr_size_t nbytes;

            c = strrchr(orig_path, '/');

            /* assert c */
            if (!c) {
                return APR_EGENERAL;
            }

            vec[0].iov_base = (char*)orig_path;
            vec[0].iov_len = c - orig_path + 1;

            /* If the HTML is cute and gives us ./foo - skip the ./ */
            if (url.path[0] == '.' && url.path[1] == '/') {
                vec[1].iov_base = url.path + 2;
                vec[1].iov_len = strlen(url.path + 2);
            }
            else if (url.path[0] == '.' && url.path[1] == '.') {
                /* FIXME We could be cute and consolidate the path; we're a
                 * toy example.  So no.
                 */
                vec[1].iov_base = url.path;
                vec[1].iov_len = strlen(url.path);
            }
            else {
                vec[1].iov_base = url.path;
                vec[1].iov_len = strlen(url.path);
            }

            path = apr_pstrcatv(pool, vec, 2, &nbytes);
        }
        else {
            path = url.path;
        }

        query = url.query;
        fragment = url.fragment;

        return create_request(url.hostinfo, path, query, fragment, ctx, pool);
    }

    return APR_SUCCESS;
}
Beispiel #27
0
static svn_error_t *
multistatus_closed(svn_ra_serf__xml_estate_t *xes,
                   void *baton,
                   int leaving_state,
                   const svn_string_t *cdata,
                   apr_hash_t *attrs,
                   apr_pool_t *scratch_pool)
{
  struct svn_ra_serf__server_error_t *server_error = baton;
  const char *errcode;
  const char *status;

  switch (leaving_state)
    {
      case MS_RESPONSE_HREF:
        {
          apr_status_t result;
          apr_uri_t uri;

          result = apr_uri_parse(scratch_pool, cdata->data, &uri);
          if (result)
            return svn_ra_serf__wrap_err(result, NULL);
          svn_ra_serf__xml_note(xes, MS_RESPONSE, "path",
                                svn_urlpath__canonicalize(uri.path, scratch_pool));
        }
        break;
      case MS_RESPONSE_STATUS:
        svn_ra_serf__xml_note(xes, MS_RESPONSE, "status", cdata->data);
        break;
      case MS_RESPONSE_ERROR_HUMANREADABLE:
        svn_ra_serf__xml_note(xes, MS_RESPONSE, "human-readable", cdata->data);
        errcode = svn_hash_gets(attrs, "errcode");
        if (errcode)
          svn_ra_serf__xml_note(xes, MS_RESPONSE, "errcode", errcode);
        break;
      case MS_RESPONSE:
        if ((status = svn_hash__get_cstring(attrs, "status", NULL)) != NULL)
          {
            error_item_t *item;

            item = apr_pcalloc(server_error->pool, sizeof(*item));

            item->path = apr_pstrdup(server_error->pool,
                                     svn_hash_gets(attrs, "path"));

            SVN_ERR(parse_status_line(&item->http_status,
                                      &item->http_reason,
                                      status,
                                      server_error->pool,
                                      scratch_pool));

            /* Do we have a mod_dav specific message? */
            item->message = svn_hash_gets(attrs, "human-readable");

            if (item->message)
              {
                if ((errcode = svn_hash_gets(attrs, "errcode")) != NULL)
                  {
                    apr_int64_t val;

                    SVN_ERR(svn_cstring_atoi64(&val, errcode));
                    item->apr_err = (apr_status_t)val;
                  }

                item->message = apr_pstrdup(server_error->pool, item->message);
              }
            else
              item->message = apr_pstrdup(server_error->pool,
                                          svn_hash_gets(attrs, "description"));

            APR_ARRAY_PUSH(server_error->items, error_item_t *) = item;
          }
        break;


      case MS_PROPSTAT_STATUS:
        svn_ra_serf__xml_note(xes, MS_PROPSTAT, "status", cdata->data);
        break;
      case MS_PROPSTAT_ERROR_HUMANREADABLE:
        svn_ra_serf__xml_note(xes, MS_PROPSTAT, "human-readable", cdata->data);
        errcode = svn_hash_gets(attrs, "errcode");
        if (errcode)
          svn_ra_serf__xml_note(xes, MS_PROPSTAT, "errcode", errcode);
        break;
      case MS_PROPSTAT_RESPONSEDESCRIPTION:
        svn_ra_serf__xml_note(xes, MS_PROPSTAT, "description",
                              cdata->data);
        break;

      case MS_PROPSTAT:
        if ((status = svn_hash__get_cstring(attrs, "status", NULL)) != NULL)
          {
            apr_hash_t *response_attrs;
            error_item_t *item;

            response_attrs = svn_ra_serf__xml_gather_since(xes, MS_RESPONSE);
            item = apr_pcalloc(server_error->pool, sizeof(*item));

            item->path = apr_pstrdup(server_error->pool,
                                     svn_hash_gets(response_attrs, "path"));
            item->propname = apr_pstrdup(server_error->pool,
                                         svn_hash_gets(attrs, "propname"));

            SVN_ERR(parse_status_line(&item->http_status,
                                      &item->http_reason,
                                      status,
                                      server_error->pool,
                                      scratch_pool));

            /* Do we have a mod_dav specific message? */
            item->message = svn_hash_gets(attrs, "human-readable");

            if (item->message)
              {
                if ((errcode = svn_hash_gets(attrs, "errcode")) != NULL)
                  {
                    apr_int64_t val;

                    SVN_ERR(svn_cstring_atoi64(&val, errcode));
                    item->apr_err = (apr_status_t)val;
                  }

                item->message = apr_pstrdup(server_error->pool, item->message);
              }
            else
              item->message = apr_pstrdup(server_error->pool,
                                          svn_hash_gets(attrs, "description"));


            APR_ARRAY_PUSH(server_error->items, error_item_t *) = item;
          }
Beispiel #28
0
  }
  fclose(in);
  return 0;

error:
  if(line) bdestroy(line);
  if(in) fclose(in);
  return -1;
}

int Command_fetch(apr_pool_t *p, const char *url, int fetch_only)
{
  apr_uri_t info = {.port = 0};
  int rc = 0;
  const char *depends_file = NULL;
  apr_status_t rv = apr_uri_parse(p, url, &info);

  check( rv == APR_SUCCESS, "Failed to parse URL: %s", url);

  if(apr_fnmatch(GIT_PAT, info.path, 0) == APR_SUCCESS) {
    rc = Shell_exec(GIT_SH, "URL", url, NULL);
    check(rc == 0, "git failed.");
  } else if(apr_fnmatch(DEPEND_PAT, info.path, 0) == APR_SUCCESS) {
    check(!fetch_only, "No point in fetching a DEPENDS file.");

    if(info.scheme) {
      depends_file = DEPENDS_PATH;
      rc = Shell_exec(CURL_SH, "URL", url, "TARGET", depends_file, NULL);
      check(rc == 0, "Curl failed.");
    } else {
      depends_file = info.path;
Beispiel #29
0
int main(int argc, const char **argv)
{
    apr_status_t status;
    apr_pool_t *pool;
    serf_bucket_alloc_t *bkt_alloc;
    serf_context_t *context;
    serf_connection_t **connections;
    app_baton_t app_ctx;
    handler_baton_t handler_ctx;
    serf_bucket_t *req_hdrs = NULL;
    apr_uri_t url;
    const char *proxy = NULL;
    const char *raw_url, *method, *req_body_path = NULL;
    int count, inflight, conn_count;
    int i;
    int print_headers, debug;
    const char *username = NULL;
    const char *password = "";
    const char *pem_path = NULL, *pem_pwd = NULL;
    apr_getopt_t *opt;
    int opt_c;
    const char *opt_arg;

    apr_initialize();
    atexit(apr_terminate);

    apr_pool_create(&pool, NULL);
    /* serf_initialize(); */
    bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL);

    /* Default to one round of fetching with no limit to max inflight reqs. */
    count = 1;
    inflight = 0;
    conn_count = 1;
    /* Default to GET. */
    method = "GET";
    /* Do not print headers by default. */
    print_headers = 0;
    /* Do not debug by default. */
    debug = 0;

    
    apr_getopt_init(&opt, pool, argc, argv);
    while ((status = apr_getopt_long(opt, options, &opt_c, &opt_arg)) ==
           APR_SUCCESS) {

        switch (opt_c) {
        case 'U':
            username = opt_arg;
            break;
        case 'P':
            password = opt_arg;
            break;
        case 'd':
            debug = 1;
            break;
        case 'f':
            req_body_path = opt_arg;
            break;
        case 'h':
            print_usage(pool);
            exit(0);
            break;
        case 'H':
            print_headers = 1;
            break;
        case 'm':
            method = opt_arg;
            break;
        case 'n':
            errno = 0;
            count = apr_strtoi64(opt_arg, NULL, 10);
            if (errno) {
                printf("Problem converting number of times to fetch URL (%d)\n",
                       errno);
                return errno;
            }
            break;
        case 'c':
            errno = 0;
            conn_count = apr_strtoi64(opt_arg, NULL, 10);
            if (errno) {
                printf("Problem converting number of concurrent connections to use (%d)\n",
                       errno);
                return errno;
            }

            if (conn_count <= 0) {
                printf("Invalid number of concurrent connections to use (%d)\n",
                       conn_count);
                return 1;
            }
            break;
        case 'x':
            errno = 0;
            inflight = apr_strtoi64(opt_arg, NULL, 10);
            if (errno) {
                printf("Problem converting number of requests to have outstanding (%d)\n",
                       errno);
                return errno;
            }
            break;
        case 'p':
            proxy = opt_arg;
            break;
        case 'r':
            {
                char *sep;
                char *hdr_val;

                if (req_hdrs == NULL) {
                    /* first request header, allocate bucket */
                    req_hdrs = serf_bucket_headers_create(bkt_alloc);
                }
                sep = strchr(opt_arg, ':');
                if ((sep == NULL) || (sep == opt_arg) || (strlen(sep) <= 1)) {
                    printf("Invalid request header string (%s)\n", opt_arg);
                    return EINVAL;
                }
                hdr_val = sep + 1;
                while (*hdr_val == ' ') {
                    hdr_val++;
                }
                serf_bucket_headers_setx(req_hdrs, opt_arg, (sep - opt_arg), 1,
                                         hdr_val, strlen(hdr_val), 1);
            }
            break;
        case CERTFILE:
            pem_path = opt_arg;
            break;
        case CERTPWD:
            pem_pwd = opt_arg;
            break;
        case 'v':
            puts("Serf version: " SERF_VERSION_STRING);
            exit(0);
        default:
            break;
        }
    }

    if (opt->ind != opt->argc - 1) {
        print_usage(pool);
        exit(-1);
    }

    raw_url = argv[opt->ind];

    apr_uri_parse(pool, raw_url, &url);
    if (!url.port) {
        url.port = apr_uri_port_of_scheme(url.scheme);
    }
    if (!url.path) {
        url.path = "/";
    }

    if (strcasecmp(url.scheme, "https") == 0) {
        app_ctx.using_ssl = 1;
    }
    else {
        app_ctx.using_ssl = 0;
    }

    if (strcasecmp(method, "HEAD") == 0) {
        app_ctx.head_request = 1;
    }
    else {
        app_ctx.head_request = 0;
    }

    app_ctx.hostinfo = url.hostinfo;
    app_ctx.pem_path = pem_path;
    app_ctx.pem_pwd = pem_pwd;

    context = serf_context_create(pool);
    app_ctx.serf_ctx = context;

    if (proxy)
    {
        apr_sockaddr_t *proxy_address = NULL;
        apr_port_t proxy_port;
        char *proxy_host;
        char *proxy_scope;

        status = apr_parse_addr_port(&proxy_host, &proxy_scope, &proxy_port, proxy, pool);
        if (status)
        {
            printf("Cannot parse proxy hostname/port: %d\n", status);
            apr_pool_destroy(pool);
            exit(1);
        }

        if (!proxy_host)
        {
            printf("Proxy hostname must be specified\n");
            apr_pool_destroy(pool);
            exit(1);
        }

        if (!proxy_port)
        {
            printf("Proxy port must be specified\n");
            apr_pool_destroy(pool);
            exit(1);
        }

        status = apr_sockaddr_info_get(&proxy_address, proxy_host, APR_UNSPEC,
                                       proxy_port, 0, pool);

        if (status)
        {
            printf("Cannot resolve proxy address '%s': %d\n", proxy_host, status);
            apr_pool_destroy(pool);
            exit(1);
        }

        serf_config_proxy(context, proxy_address);
    }

    if (username)
    {
        serf_config_authn_types(context, SERF_AUTHN_ALL);
    }
    else
    {
        serf_config_authn_types(context, SERF_AUTHN_NTLM | SERF_AUTHN_NEGOTIATE);
    }

    serf_config_credentials_callback(context, credentials_callback);

    /* Setup debug logging */
    if (debug)
    {
        serf_log_output_t *output;
        apr_status_t status;

        status = serf_logging_create_stream_output(&output,
                                                   context,
                                                   SERF_LOG_DEBUG,
                                                   SERF_LOGCOMP_ALL_MSG,
                                                   SERF_LOG_DEFAULT_LAYOUT,
                                                   stderr,
                                                   pool);

        if (!status)
            serf_logging_add_output(context, output);
    }

    /* ### Connection or Context should have an allocator? */
    app_ctx.bkt_alloc = bkt_alloc;

    connections = apr_pcalloc(pool, conn_count * sizeof(serf_connection_t*));
    for (i = 0; i < conn_count; i++)
    {
        conn_baton_t *conn_ctx = apr_pcalloc(pool, sizeof(*conn_ctx));
        conn_ctx->app = &app_ctx;
        conn_ctx->ssl_ctx = NULL;

        status = serf_connection_create2(&connections[i], context, url,
                                         conn_setup, conn_ctx,
                                         closed_connection, conn_ctx,
                                         pool);
        if (status) {
            printf("Error creating connection: %d\n", status);
            apr_pool_destroy(pool);
            exit(1);
        }

        serf_connection_set_max_outstanding_requests(connections[i], inflight);
    }

    handler_ctx.completed_requests = 0;
    handler_ctx.print_headers = print_headers;

#if APR_VERSION_AT_LEAST(1, 3, 0)
    apr_file_open_flags_stdout(&handler_ctx.output_file, APR_BUFFERED, pool);
#else
    apr_file_open_stdout(&handler_ctx.output_file, pool);
#endif

    handler_ctx.host = url.hostinfo;
    handler_ctx.method = method;
    handler_ctx.path = apr_pstrcat(pool,
                                   url.path,
                                   url.query ? "?" : "",
                                   url.query ? url.query : "",
                                   NULL);
    handler_ctx.username = username;
    handler_ctx.password = password;
    handler_ctx.auth_attempts = 0;

    handler_ctx.req_body_path = req_body_path;

    handler_ctx.acceptor = accept_response;
    handler_ctx.acceptor_baton = &app_ctx;
    handler_ctx.handler = handle_response;
    handler_ctx.req_hdrs = req_hdrs;

    for (i = 0; i < count; i++) {
        /* We don't need the returned request here. */
        serf_connection_request_create(connections[i % conn_count],
                                       setup_request, &handler_ctx);
    }

    while (1) {
        status = serf_context_run(context, SERF_DURATION_FOREVER, pool);
        if (APR_STATUS_IS_TIMEUP(status))
            continue;
        if (status) {
            char buf[200];
            const char *err_string;
            err_string = serf_error_string(status);
            if (!err_string) {
                err_string = apr_strerror(status, buf, sizeof(buf));
            }

            printf("Error running context: (%d) %s\n", status, err_string);
            apr_pool_destroy(pool);
            exit(1);
        }
        if (apr_atomic_read32(&handler_ctx.completed_requests) >= count) {
            break;
        }
        /* Debugging purposes only! */
        serf_debug__closed_conn(app_ctx.bkt_alloc);
    }

    apr_file_close(handler_ctx.output_file);

    for (i = 0; i < conn_count; i++)
    {
        serf_connection_close(connections[i]);
    }

    apr_pool_destroy(pool);
    return 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;
}