Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kerberos Proxy support #514

Closed
christophvw opened this issue Apr 27, 2020 · 23 comments
Closed

Kerberos Proxy support #514

christophvw opened this issue Apr 27, 2020 · 23 comments
Assignees
Milestone

Comments

@christophvw
Copy link

I cannot connect to any repository because MiKTeX lacks support for kerberos-proxy authentication -
our corporate proxy supports Kerberos authentication only.

Please add kerberos authentication to the Console.

@christophvw
Copy link
Author

maybe set

curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANYSAFE);

when proxy authentication is set but username/password is empty?
This should allow Negotiate (Kerberos), NTLM and NTLM with winbind.

@christophvw
Copy link
Author

christophvw commented May 5, 2020

Changing the following code in CurlWebSession::Initialize() works fine.
TODO: don't ask for a username/password everytime

  if (proxySettings.user.empty())
  {
	  SetOption(CURLOPT_PROXYUSERNAME, "");
	  SetOption(CURLOPT_PROXYPASSWORD, "");
	  SetOption(CURLOPT_PROXYAUTH, CURLAUTH_GSSNEGOTIATE);
  }
  else
  {
	  SetOption(CURLOPT_PROXYAUTH, CURLAUTH_ANY);
	  userPassword = proxySettings.user;
	  userPassword += ':';
	  userPassword += proxySettings.password;
	  SetOption(CURLOPT_PROXYUSERPWD, userPassword.c_str());
  }

@christophvw
Copy link
Author

Maybe CurlWebSession should check if Kerberos is supported and then don't ask for the password anymore...

long auth;
res = curl_easy_getinfo(curlMsg->easy_handle, CURLINFO_PROXYAUTH_AVAIL, &auth);
if ((!res) && (auth))
{
    if (auth & CURLAUTH_NEGOTIATE)
    {
        /* Kerberos supported */
    }

}

@edocevoli
Copy link
Member

You will not be asked for username/password if leave Authentication required unchecked:

Capture

@edocevoli edocevoli self-assigned this May 6, 2020
@edocevoli edocevoli added this to the 2.9.7420 milestone May 6, 2020
@christophvw
Copy link
Author

Maybe it would be helpful to add a checkbox to use the windows proxy settings and set this as default. Then the endusers won't have to configure anything at all in most cases.

This should do the trick:
https://docs.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpgetdefaultproxyconfiguration

Grüße aus Spandau

@christophvw
Copy link
Author

christophvw commented May 6, 2020

Ok, forget about that. This reads the proxy settings from the WINHTTP config, which is not the same as what IE will use.

The static proxy configuration can be read from registry, but that will not cover automatic configuration with a PAC file.
Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings

@christophvw
Copy link
Author

Microsoft seems to have sample code released how to get the proxy settings (MIT license)
https://github.com/microsoft/Windows-classic-
samples/blob/master/Samples/WinhttpProxy/cpp/GetProxy.cpp

@edocevoli
Copy link
Member

Thank you, but MiKTeX doesn't use the WinHTTP API.

We now let Curl pick the right authentication method. This should fix the issue.

@christophvw
Copy link
Author

christophvw commented May 6, 2020

I don't think your change will be enough.

I was only able get negotiate/kerberos to work when I set these as well:
SetOption(CURLOPT_PROXYUSERNAME, "");
SetOption(CURLOPT_PROXYPASSWORD, "");

And about the WinHTTP API - I didn't meant to replace curl. But it could be a nice addition (for the windows build) to automatically get the correct proxy settings.

@edocevoli
Copy link
Member

Okay, so then you have to enter empty credentials in order to make it work.

@christophvw
Copy link
Author

Yes, I just gave it a try. The following code works fine:

    SetOption(CURLOPT_PROXYAUTH, CURLAUTH_ANY);
    if (proxySettings.authenticationRequired)
    {
      ...
    }
    else
    {
        SetOption(CURLOPT_PROXYUSERNAME, "");
        SetOption(CURLOPT_PROXYPASSWORD, "");
    }

But when you don't pass empty credentials you will get an error message.

@edocevoli
Copy link
Member

No, we will not set empty credentials since this might break basic authentication. Instead, the user, when prompted for credentials, has to provide empty credentials.

@christophvw
Copy link
Author

That's a bad idea. How should users know the proxy needs empty credentials? They will enter their Windows Credentials and it will fail.

@christophvw
Copy link
Author

Then you should use curl_easy_getinfo with CURLINFO_PROXYAUTH_AVAIL and pass empty credentials when CURLAUTH_NEGOTIATE is available. (And don't ask anymore in this case!)

@edocevoli
Copy link
Member

Curl honors the standard proxy variables variable. For example:

http_proxy=http://:@10.103.33.1:1080/

uses empty credentials. You have to uncheck Use a proxy server in the connection settings dialog.

SetOption(CURLOPT_PROXYAUTH, CURLAUTH_ANY); must always be executed.

@christophvw
Copy link
Author

These variables will cause a lot of trouble as you can't set any exceptions. We cannot use them.

i,e. this will break local REST API debugging as Postman will try to send all requests to the proxy as well then.

@christophvw
Copy link
Author

How should the change from my previous comment break basic auth?

I only set empty username and password when proxySettings.authenticationRequired is false...
This should not affect basic auth at all.

@edocevoli
Copy link
Member

What makes you 100% sure that it does not break basic authentication? I don't want to start a code review of Curl. And since I cannot easily test it, I will stay on the safe side. Sorry.

@christophvw
Copy link
Author

Basic auth without password? How should this work at all?
Or do you mean proxy without authentication?

@christophvw
Copy link
Author

christophvw commented May 12, 2020

I made some tests with this patch and McAfee WebGateway proxy:

   SetOption(CURLOPT_PROXYAUTH, CURLAUTH_ANY);
    if (proxySettings.authenticationRequired)
    {
      ...
    }
    else
    {
        SetOption(CURLOPT_PROXYUSERNAME, "");
        SetOption(CURLOPT_PROXYPASSWORD, "");
    }

"Authentication required" checked (and provided valid credentials):
Basic

[2020-05-12 08:37:56.416 +02:00] [3635] NTLM (141642121, 10.116.16.16) URL: https://api2.miktex.org
[2020-05-12 08:37:56.416 +02:00] [3635] NTLM (141642121, 10.116.16.16) Incoming credentials: Basic
[2020-05-12 08:37:56.421 +02:00] [3646] NTLM (141642121, 10.116.16.16) Authenticated: 1

NTLM

[2020-05-12 09:18:32.306 +02:00] [3617] NTLM (141719964, 10.116.16.16) URL: https://api2.miktex.org
[2020-05-12 09:18:32.306 +02:00] [3617] NTLM (141719964, 10.116.16.16) Incoming credentials: NTLM TlRM
[2020-05-12 09:18:32.315 +02:00] [3623] NTLM (141719964, 10.116.16.16) Authenticated: 1

Kerberos (expected to fail with credentials, because I didn't allow fallback to Negotiate with NTLM)

[2020-05-12 08:32:58.232 +02:00] [3620] Kerberos (141635306, 10.116.16.16) URL: https://api2.miktex.org
[2020-05-12 08:32:58.232 +02:00] [3620] Kerberos (141635306, 10.116.16.16) Incoming credentials: Negotiate TlRM
[2020-05-12 08:32:58.232 +02:00] [3620] Kerberos (141635306, 10.116.16.16) Authentication didn't return values, failure ID: 0, authentication failed: 1

"Authentication required" not checked:
NTLM

[2020-05-12 08:34:02.688 +02:00] [3626] NTLM (141637906, 10.116.16.16) URL: https://api2.miktex.org
[2020-05-12 08:34:02.688 +02:00] [3626] NTLM (141637906, 10.116.16.16) Incoming credentials: NTLM
[2020-05-12 08:34:02.697 +02:00] [3609] NTLM (141637906, 10.116.16.16) Authenticated: 1

Kerberos

[2020-05-12 08:31:17.464 +02:00] [3635] Kerberos (141631438, 10.116.16.16) URL: https://api2.miktex.org
[2020-05-12 08:31:17.464 +02:00] [3635] Kerberos (141631438, 10.116.16.16) Incoming credentials: Negotiate 
[2020-05-12 08:31:17.465 +02:00] [3635] Kerberos (141631438, 10.116.16.16) Authenticated: 1

@edocevoli
Copy link
Member

edocevoli commented May 12, 2020

Thank you. I will consider your patch for a future release. The current release (2.9.7420) is almost out and it should fix the issue with the caveat that the user has to enter empty credentials.

@edocevoli
Copy link
Member

Haven't tried it, but it should be possible to configure empty credentials:

Capture

@christophvw
Copy link
Author

Configuring empty credentials with :@fqdn does not work. Currently the user has to enable the "Requires Authentication" and click "OK" everytime on the window asking for credentials.

This is annoying...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants