📄 session.c
字号:
else server_group = NULL; if (server_group) { svn_config_get(cfg, proxy_host, server_group, SVN_CONFIG_OPTION_HTTP_PROXY_HOST, *proxy_host); svn_config_get(cfg, &port_str, server_group, SVN_CONFIG_OPTION_HTTP_PROXY_PORT, port_str); svn_config_get(cfg, proxy_username, server_group, SVN_CONFIG_OPTION_HTTP_PROXY_USERNAME, *proxy_username); svn_config_get(cfg, proxy_password, server_group, SVN_CONFIG_OPTION_HTTP_PROXY_PASSWORD, *proxy_password); svn_config_get(cfg, &timeout_str, server_group, SVN_CONFIG_OPTION_HTTP_TIMEOUT, timeout_str); SVN_ERR(svn_config_get_bool(cfg, compression, server_group, SVN_CONFIG_OPTION_HTTP_COMPRESSION, *compression)); svn_config_get(cfg, &debug_str, server_group, SVN_CONFIG_OPTION_NEON_DEBUG_MASK, debug_str); } /* Special case: convert the port value, if any. */ if (port_str) { char *endstr; const long int port = strtol(port_str, &endstr, 10); if (*endstr) return svn_error_create(SVN_ERR_RA_ILLEGAL_URL, NULL, _("Invalid URL: illegal character in proxy " "port number")); if (port < 0) return svn_error_create(SVN_ERR_RA_ILLEGAL_URL, NULL, _("Invalid URL: negative proxy port number")); if (port > 65535) return svn_error_create(SVN_ERR_RA_ILLEGAL_URL, NULL, _("Invalid URL: proxy port number greater " "than maximum TCP port number 65535")); *proxy_port = port; } else *proxy_port = 80; if (timeout_str) { char *endstr; const long int timeout = strtol(timeout_str, &endstr, 10); if (*endstr) return svn_error_create(SVN_ERR_RA_DAV_INVALID_CONFIG_VALUE, NULL, _("Invalid config: illegal character in " "timeout value")); if (timeout < 0) return svn_error_create(SVN_ERR_RA_DAV_INVALID_CONFIG_VALUE, NULL, _("Invalid config: negative timeout value")); *timeout_seconds = timeout; } else *timeout_seconds = 0; if (debug_str) { char *endstr; const long int debug = strtol(debug_str, &endstr, 10); if (*endstr) return svn_error_create(SVN_ERR_RA_DAV_INVALID_CONFIG_VALUE, NULL, _("Invalid config: illegal character in " "debug mask value")); *neon_debug = debug; } else *neon_debug = 0; return SVN_NO_ERROR;}/* Userdata for the `proxy_auth' function. */struct proxy_auth_baton{ const char *username; /* Cannot be NULL, but "" is okay. */ const char *password; /* Cannot be NULL, but "" is okay. */};/* An `ne_request_auth' callback, see ne_auth.h. USERDATA is a * `struct proxy_auth_baton *'. * * If ATTEMPT < 10, copy USERDATA->username and USERDATA->password * into USERNAME and PASSWORD respectively (but do not copy more than * NE_ABUFSIZ bytes of either), and return zero to indicate to Neon * that authentication should be attempted. * * If ATTEMPT >= 10, copy nothing into USERNAME and PASSWORD and * return 1, to cancel further authentication attempts. * * Ignore REALM. * * ### Note: There is no particularly good reason for the 10-attempt * limit. Perhaps there should only be one attempt, and if it fails, * we just cancel any further attempts. I used 10 just in case the * proxy tries various times with various realms, since we ignore * REALM. And why do we ignore REALM? Because we currently don't * have any way to specify different auth information for different * realms. (I'm assuming that REALM would be a realm on the proxy * server, not on the Subversion repository server that is the real * destination.) Do we have any need to support proxy realms? */static int proxy_auth(void *userdata, const char *realm, int attempt, char *username, char *password){ struct proxy_auth_baton *pab = userdata; if (attempt >= 10) return 1; /* Else. */ apr_cpystrn(username, pab->username, NE_ABUFSIZ); apr_cpystrn(password, pab->password, NE_ABUFSIZ); return 0;}#define RA_DAV_DESCRIPTION \ N_("Module for accessing a repository via WebDAV (DeltaV) protocol.")static const char *ra_dav_get_description(void){ return _(RA_DAV_DESCRIPTION);}static const char * const *ra_dav_get_schemes(apr_pool_t *pool){ static const char *schemes_no_ssl[] = { "http", NULL }; static const char *schemes_ssl[] = { "http", "https", NULL };#ifdef SVN_NEON_0_25 return ne_has_support(NE_FEATURE_SSL) ? schemes_ssl : schemes_no_ssl;#else /* ! SVN_NEON_0_25 */ return ne_supports_ssl() ? schemes_ssl : schemes_no_ssl;#endif /* if/else SVN_NEON_0_25 */}typedef struct neonprogress_baton_t{ svn_ra_progress_notify_func_t progress_func; void *progress_baton; apr_pool_t *pool;} neonprogress_baton_t;static voidra_dav_neonprogress(void *baton, off_t progress, off_t total){ const neonprogress_baton_t *neonprogress_baton = baton; if (neonprogress_baton->progress_func) { neonprogress_baton->progress_func(progress, total, neonprogress_baton->progress_baton, neonprogress_baton->pool); }}/* ### need an ne_session_dup to avoid the second gethostbyname * call and make this halfway sane. *//* Parse URL into *URI, doing some sanity checking and initializing the port to a default value if it wasn't specified in URL. */static svn_error_t *parse_url(ne_uri *uri, const char *url){ if (ne_uri_parse(url, uri) || uri->host == NULL || uri->path == NULL || uri->scheme == NULL) { ne_uri_free(uri); return svn_error_create(SVN_ERR_RA_ILLEGAL_URL, NULL, _("Malformed URL for repository")); } if (uri->port == 0) uri->port = ne_uri_defaultport(uri->scheme); return SVN_NO_ERROR;}static svn_error_t *svn_ra_dav__open(svn_ra_session_t *session, const char *repos_URL, const svn_ra_callbacks2_t *callbacks, void *callback_baton, apr_hash_t *config, apr_pool_t *pool){ apr_size_t len; ne_session *sess, *sess2; ne_uri uri = { 0 }; svn_ra_dav__session_t *ras; int is_ssl_session; svn_boolean_t compression; svn_config_t *cfg; const char *server_group; char *itr; neonprogress_baton_t *neonprogress_baton = apr_pcalloc(pool, sizeof(*neonprogress_baton)); /* Sanity check the URI */ SVN_ERR(parse_url(&uri, repos_URL)); /* Can we initialize network? */ if (ne_sock_init() != 0) { ne_uri_free(&uri); return svn_error_create(SVN_ERR_RA_DAV_SOCK_INIT, NULL, _("Network socket initialization failed")); } /* we want to know if the repository is actually somewhere else */ /* ### not yet: http_redirect_register(sess, ... ); */ /* HACK! Neon uses strcmp when checking for https, but RFC 2396 says * we should be using case-insensitive comparisons when checking for * URI schemes. To allow our users to use WeIrd CasE HttPS we force * the scheme to lower case before we pass it on to Neon, otherwise we * would crash later on when we assume Neon has set up its https stuff * but it really didn't. */ for (itr = uri.scheme; *itr; ++itr) *itr = tolower(*itr); is_ssl_session = (strcasecmp(uri.scheme, "https") == 0); if (is_ssl_session) {#ifdef SVN_NEON_0_25 if (ne_has_support(NE_FEATURE_SSL) == 0)#else /* ! SVN_NEON_0_25 */ if (ne_supports_ssl() == 0)#endif /* if/else SVN_NEON_0_25 */ { ne_uri_free(&uri); return svn_error_create(SVN_ERR_RA_DAV_SOCK_INIT, NULL, _("SSL is not supported")); } } /* Create two neon session objects, and set their properties... */ sess = ne_session_create(uri.scheme, uri.host, uri.port); sess2 = ne_session_create(uri.scheme, uri.host, uri.port); cfg = config ? apr_hash_get(config, SVN_CONFIG_CATEGORY_SERVERS, APR_HASH_KEY_STRING) : NULL; if (cfg) server_group = svn_config_find_group(cfg, uri.host, SVN_CONFIG_SECTION_GROUPS, pool); else server_group = NULL; /* If there's a timeout or proxy for this URL, use it. */ { const char *proxy_host; unsigned int proxy_port; const char *proxy_username; const char *proxy_password; int timeout; int debug; svn_error_t *err; err = get_server_settings(&proxy_host, &proxy_port, &proxy_username, &proxy_password, &timeout, &debug, &compression, cfg, uri.host, pool); if (err) { ne_uri_free(&uri); return err; } if (debug) ne_debug_init(stderr, debug); if (proxy_host) { ne_session_proxy(sess, proxy_host, proxy_port); ne_session_proxy(sess2, proxy_host, proxy_port); if (proxy_username) { /* Allocate the baton in pool, not on stack, so it will last till whenever Neon needs it. */ struct proxy_auth_baton *pab = apr_palloc(pool, sizeof(*pab)); pab->username = proxy_username; pab->password = proxy_password ? proxy_password : ""; ne_set_proxy_auth(sess, proxy_auth, pab); ne_set_proxy_auth(sess2, proxy_auth, pab); } } if (!timeout) timeout = DEFAULT_HTTP_TIMEOUT; ne_set_read_timeout(sess, timeout); ne_set_read_timeout(sess2, timeout); } /* make sure we will eventually destroy the session */ apr_pool_cleanup_register(pool, sess, cleanup_session, apr_pool_cleanup_null); apr_pool_cleanup_register(pool, sess2, cleanup_session, apr_pool_cleanup_null); ne_set_useragent(sess, "SVN/" SVN_VERSION); ne_set_useragent(sess2, "SVN/" SVN_VERSION); /* clean up trailing slashes from the URL */ len = strlen(uri.path); if (len > 1 && uri.path[len - 1] == '/') uri.path[len - 1] = '\0'; /* Create and fill a session_baton. */ ras = apr_pcalloc(pool, sizeof(*ras)); ras->pool = pool; ras->url = svn_stringbuf_create(repos_URL, pool); /* copies uri pointer members, they get free'd in __close. */ ras->root = uri; ras->sess = sess; ras->sess2 = sess2; ras->callbacks = callbacks; ras->callback_baton = callback_baton; ras->compression = compression; /* save config and server group in the auth parameter hash */ svn_auth_set_parameter(ras->callbacks->auth_baton, SVN_AUTH_PARAM_CONFIG, cfg); svn_auth_set_parameter(ras->callbacks->auth_baton, SVN_AUTH_PARAM_SERVER_GROUP, server_group); /* make sure we eventually destroy the uri */ apr_pool_cleanup_register(pool, &ras->root, cleanup_uri, apr_pool_cleanup_null); /* note that ras->username and ras->password are still NULL at this point. */ /* Register an authentication 'pull' callback with the neon sessions */ ne_set_server_auth(sess, request_auth, ras); ne_set_server_auth(sess2, request_auth, ras); /* Store our RA session baton in Neon's private data slot so we can get at it in functions that take only ne_session_t *sess (instead of the full svn_ra_dav__session_t *ras). */ ne_set_session_private(sess, SVN_RA_NE_SESSION_ID, ras); ne_set_session_private(sess2, SVN_RA_NE_SESSION_ID, ras); if (is_ssl_session) { const char *authorities, *trust_default_ca; authorities = svn_config_get_server_setting( cfg, server_group, SVN_CONFIG_OPTION_SSL_AUTHORITY_FILES, NULL); if (authorities != NULL) { char *files, *file, *last; files = apr_pstrdup(pool, authorities); while ((file = apr_strtok(files, ";", &last)) != NULL) { ne_ssl_certificate *ca_cert; files = NULL; ca_cert = ne_ssl_cert_read(file); if (ca_cert == NULL) { return svn_error_createf (SVN_ERR_RA_DAV_INVALID_CONFIG_VALUE, NULL, _("Invalid config: unable to load certificate file '%s'"), svn_path_local_style(file, pool)); } ne_ssl_trust_cert(sess, ca_cert); ne_ssl_trust_cert(sess2, ca_cert); } } /* When the CA certificate or server certificate has verification problems, neon will call our verify function before outright rejection of the connection.*/ ne_ssl_set_verify(sess, server_ssl_callback, ras); ne_ssl_set_verify(sess2, server_ssl_callback, ras); /* For client connections, we register a callback for if the server wants to authenticate the client via client certificate. */ ne_ssl_provide_clicert(sess, client_ssl_callback, ras); ne_ssl_provide_clicert(sess2, client_ssl_callback, ras); /* See if the user wants us to trust "default" openssl CAs. */ trust_default_ca = svn_config_get_server_setting( cfg, server_group, SVN_CONFIG_OPTION_SSL_TRUST_DEFAULT_CA, "true"); if (strcasecmp(trust_default_ca, "true") == 0) { ne_ssl_trust_default_ca(sess);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -