Skip to content

Commit

Permalink
Proxy auth with custom HTTP transport
Browse files Browse the repository at this point in the history
Add three settings:
- http.proxy-auth
- http.proxy-username
- http.proxy-password

proxy-auth defaults to "auto" so that most use cases work out of the
box. I don't know why you would disable authentication support, but I
added a "disable" option in this case. You can also force the use of a
mechanism and abort if the proxy doesn't advertise it.

proxy-username and proxy-password: String vs Option<String>?
curl doesn't negotiate (SPNEGO, here "gss") if handle.proxy_username and
handle.proxy_password aren't called. This authentication mechanism
doesn't require a user/pass in cargo config. This shouldn't hurt (?)
when the proxy doesn't require authentication.

About curl-rust's spnego and ntlm features:
https://github.com/alexcrichton/curl-rust/blob/b50c5d355aab69483752db51815c5a679b29d6c4/curl-sys/Cargo.toml#L54-L60
**This is the last blocker I think.** If we require those features, then
vendored curl builds will require "a suitable GSS-API library or SSPI on
Windows" [0] for the "gss" setting to work (which is what corporate
proxies are using most of the time). I think this PR is blocked until we
can either  vendor those dependencies, or we change the official cargo
builds to link dynamically to libcurl.
  • Loading branch information
hhirtz committed Nov 28, 2022
1 parent a004f94 commit e7a5905
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/cargo/ops/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,9 @@ pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult<
if let Some(proxy) = http_proxy(config)? {
handle.proxy(&proxy)?;
}
handle.proxy_auth(&http.proxy_auth.to_easy())?;
handle.proxy_username(&http.proxy_username)?;
handle.proxy_password(&http.proxy_password)?;
if let Some(cainfo) = &http.cainfo {
let cainfo = cainfo.resolve_path(config);
handle.cainfo(&cainfo)?;
Expand Down
35 changes: 34 additions & 1 deletion src/cargo/util/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ use crate::util::{internal, toml as cargo_toml};
use crate::util::{FileLock, Filesystem, IntoUrl, IntoUrlWithBase, Rustc};
use anyhow::{anyhow, bail, format_err, Context as _};
use cargo_util::paths;
use curl::easy::Easy;
use curl::easy::{Auth, Easy};
use lazycell::LazyCell;
use serde::Deserialize;
use toml_edit::{easy as toml, Item};
Expand Down Expand Up @@ -2215,10 +2215,43 @@ impl Drop for PackageCacheLock<'_> {
}
}

#[derive(Debug, Default, Deserialize, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub enum CargoHttpProxyAuth {
#[default]
Auto,
Disable,
Basic,
Digest,
Gss,
Ntlm,
}

impl CargoHttpProxyAuth {
pub fn to_easy(&self) -> Auth {
let mut easy = Auth::new();
let easy = match self {
Self::Auto => easy.basic(true).digest(true).gssnegotiate(true).ntlm(true),
Self::Disable => &mut easy,
Self::Basic => easy.basic(true),
Self::Digest => easy.digest(true),
Self::Gss => easy.gssnegotiate(true),
Self::Ntlm => easy.ntlm(true),
};
easy.clone()
}
}

#[derive(Debug, Default, Deserialize, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub struct CargoHttpConfig {
pub proxy: Option<String>,
#[serde(default)]
pub proxy_auth: CargoHttpProxyAuth,
#[serde(default)]
pub proxy_username: String,
#[serde(default)]
pub proxy_password: String,
pub low_speed_limit: Option<u32>,
pub timeout: Option<u64>,
pub cainfo: Option<ConfigRelativePath>,
Expand Down
25 changes: 25 additions & 0 deletions src/doc/src/reference/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ vcs = "none" # VCS to use ('git', 'hg', 'pijul', 'fossil', 'none')
[http]
debug = false # HTTP debugging
proxy = "host:port" # HTTP proxy in libcurl format
proxy-auth = "auto" # HTTP proxy authentication mechanism
proxy-username = "" # HTTP proxy username
proxy-password = "" # HTTP proxy password
ssl-version = "tlsv1.3" # TLS version to use
ssl-version.max = "tlsv1.3" # maximum TLS version
ssl-version.min = "tlsv1.1" # minimum TLS version
Expand Down Expand Up @@ -627,6 +630,28 @@ setting in your global git configuration. If none of those are set, the
`HTTPS_PROXY` or `https_proxy` environment variables set the proxy for HTTPS
requests, and `http_proxy` sets it for HTTP requests.

##### `http.proxy-auth`
* Type: string
* Default: "auto"
* Environment: `CARGO_HTTP_PROXY_AUTH`

Sets a mechanism to authenticate against the proxy.
Possible values are: "auto", "disable", "basic", "digest", "gss" and "ntlm".

##### `http.proxy-username`
* Type: string
* Default: ""
* Environment: `CARGO_HTTP_PROXY_USERNAME`

Authenticate against the proxy using the given username.

##### `http.proxy-password`
* Type: string
* Default: ""
* Environment: `CARGO_HTTP_PROXY_PASSWORD`

Authenticate against the proxy using the given password.

##### `http.timeout`
* Type: integer
* Default: 30
Expand Down
6 changes: 6 additions & 0 deletions src/doc/src/reference/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ In summary, the supported environment variables are:
* `CARGO_FUTURE_INCOMPAT_REPORT_FREQUENCY` - How often we should generate a future incompat report notification, see [`future-incompat-report.frequency`].
* `CARGO_HTTP_DEBUG` — Enables HTTP debugging, see [`http.debug`].
* `CARGO_HTTP_PROXY` — Enables HTTP proxy, see [`http.proxy`].
* `CARGO_HTTP_PROXY_AUTH` — The proxy authentication mechanism, see [`http.proxy-auth`].
* `CARGO_HTTP_PROXY_USERNAME` — The proxy username, see [`http.proxy-username`].
* `CARGO_HTTP_PROXY_PASSWORD` — The proxy password, see [`http.proxy-password`].
* `CARGO_HTTP_TIMEOUT` — The HTTP timeout, see [`http.timeout`].
* `CARGO_HTTP_CAINFO` — The TLS certificate Certificate Authority file, see [`http.cainfo`].
* `CARGO_HTTP_CHECK_REVOKE` — Disables TLS certificate revocation checks, see [`http.check-revoke`].
Expand Down Expand Up @@ -163,6 +166,9 @@ In summary, the supported environment variables are:
[`future-incompat-report.frequency`]: config.md#future-incompat-reportfrequency
[`http.debug`]: config.md#httpdebug
[`http.proxy`]: config.md#httpproxy
[`http.proxy-auth`]: config.md#httpproxy-auth
[`http.proxy-username`]: config.md#httpproxy-username
[`http.proxy-password`]: config.md#httpproxy-password
[`http.timeout`]: config.md#httptimeout
[`http.cainfo`]: config.md#httpcainfo
[`http.check-revoke`]: config.md#httpcheck-revoke
Expand Down

0 comments on commit e7a5905

Please sign in to comment.