I'm writing a simple Go utility that makes some POST requests to the internet, but I need to go through a proxy and use NTLM without knowing the user's credentials. I've seen CSharp code like below:
wc = new CookieWebClient();
wc.UseDefaultCredentials = true;
wc.Proxy = WebRequest.DefaultWebProxy;
wc.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
In Go I've managed to determine the system proxy with what feels like a hack:
import (
"net/http"
"net/url"
"strings"
"golang.org/x/sys/windows/registry"
)
func getSystemProxy() func(req *http.Request) (*url.URL, error) {
var e error
var k registry.Key
var proxy *url.URL
var v string
// Open the "Internet Settings" registry key
k, e = registry.OpenKey(
registry.CURRENT_USER,
strings.Join(
[]string{
"Software",
"Microsoft",
"Windows",
"CurrentVersion",
"Internet Settings",
},
"\\",
),
registry.QUERY_VALUE,
)
if e != nil {
return http.ProxyFromEnvironment
}
defer k.Close()
// Read the "ProxyServer" value
v, _, e = k.GetStringValue("ProxyServer")
if (e != nil) || (v == "") {
return http.ProxyFromEnvironment
}
// Get the http= portion and fix it up
v = strings.Split(v, ";")[0]
v = strings.Replace(v, "=", "://", 1)
// Parse url
if proxy, e = url.Parse(v); e != nil {
return http.ProxyFromEnvironment
}
return http.ProxyURL(proxy)
}
I've been unable to find a Go equivalent to CSharp's https://learn.microsoft.com/en-us/dotnet/api/system.net.credentialcache.defaultnetworkcredentials?view=netcore-3.1. I have found https://github.com/Azure/go-ntlmssp but that requires me to hard-code the user's credentials, which I do not have, and I would need to compile a new binary for each user, which I do not want to do. I'm looking for a 0 config solution. I would prefer this to be as dynamic as possible. If CSharp can do it, why can't Go?
Any help would be greatly appreciated!
I've been told I can use WinHTTP or WinInet to achieve this. I will play with the
golang.org/x/sys/windows
package and call the procedures from the DLLs. Alternatively, I've been told I could usegithub.com/go-ole/go-ole
and use WinHTTP via COM objects like in this other SO question: Windows system credentials in Go HTTP NTLM requests.Update: I ultimately decided to settle on WinInet and I created my own package (gitlab.com/mjwhitta/win/wininet) which contains an http.Client which can be used to make GET and POST requests. See the README for an example of how to use it. I will probably expand on it in the future should I have the need. Pull requests are welcome.
Last update: Boy do I feel stupid. WinInet doesn't look to do NTLM for you... so I ported it to WinHttp (gitlab.com/mjwhitta/win/winhttp).