A place for spare thoughts


EnumerateChain extension method

Filed under: c#, patterns — Ivan Danilov @ 19:12

Very small, simple and extremely useful method:

        public static IEnumerable<T> EnumerateChain<T>(this T start, Func<T, T> next)
            where T : class
            while (start != null)
                yield return start;
                start = next(start);

How to use it you may ask. Suppose (just for the sake of example) you have some tree structure, with Name and Parent properties in each node. And you want to get path in tree of some given node in form of node names separated by slashes. Nothing could be easier:

public static string GetPathInTree(Node node)
    var names = node.EnumerateChain(n => n.Parent).Reverse().Select(n => n.Name);
    return String.Join("/", names);

Basically with this method you can traverse any structure as if it was normal IEnumerable. Very convenient, really 🙂


Setting git to work behind NTLM-authenticated proxy: cntlm to the rescue

Filed under: git — Ivan Danilov @ 20:23

Our office has corporate proxy – and that’s pretty common as far as I know. And it happened that our proxy has NTLM authentication which is not very common/popular among linux users (that’s an understatement, I know). So git and msysgit don’t support it out-of-the-box.

Thus, if you try to clone something over SSL behind such proxy, say, from github – you’ll see something like below:

$ git clone https://github.com/libgit2/libgit2sharp.git
Cloning into 'libgit2sharp'...
error: Failed connect to github.com:443; No error while accessing https://github.com/libgit2/libgit2sharp.git/info/refs
fatal: HTTP request failed

And it will take almost forever by the way (dozen of minutes in my case).

Well, to solve the problem you may specify proxy manually like that:

$ git config http.proxy http://domain\\\user:password@proxy.MyCorp.com:8080/

Note three backslashes, it is not a mistake.

But you already see the problem, don’t you? git config is saved in plaintext and I’m not very like the idea to store my password like that, even if in some location where nobody has access rights (domain administrators could see everything in the domain, remember?). And passing token instead of login/password is beyond msysgit abilities.

You may think: if I’m able to get to github in browser, even over SSH, then why git can’t? Maybe there’s some way to intercept git’s queries and wrap them through correct proxy/auth headers? And you’d be right: there is tool capable of that, name is cntlm.

Some time ago cntlm had have a bug preventing it from working in exactly the same situation: http://stackoverflow.com/questions/6345104/proxy-through-cntlm-why-git-clone-hangs

Fortunately, now the bug is fixed (at the time of writing, latest cntlm version was 0.92.3). So, what it is and how you can use it?

Cntlm is the proxy itself, that you run on your local box and when it receives a request – it re-sends it to so-called ‘parent proxy’ (which is exactly your NTLM-authenticated beast) with correct auth headers.

First, you need to download distributive and install it. In the installation folder you will find cntlm.ini file, which you want to edit. You have to set correct Username, Password and auth tokens and remove Password field (as you don’t want to store password in the plaintext). Then run command line and run these:

$ cntlm.exe -H -u username -d domain
PassLM          1AD35398BE6565DDB5C4EF70C0593492
PassNT          77B9081511704EE852F94227CF48A793
PassNTLMv2      B78FD04127AEDF090C1F7121ED002A4D    # Only for user 'username', domain 'domain'

Just paste these PassNTLMv2 string to the cntlm.ini (don’t forget to type your own username and password instead of the ‘username’ and ‘password’ strings above). Don’t touch PassLM or PassNT tokens if your system supports NTLMv2 because NT and LM are not secure.

It would be all of the configuration. Run ‘cntlm.exe’. You could try ‘cntlm.exe -v’ to activate verbose mode and have much info on the console and see if something went wrong. If you run cntlm without params – it will go to daemon mode and will silently run in background, listening for 3128 port (by default – can be changed in cntlm.ini easily). And by default it won’t accept connections from others non-local programs, so that your box will not become a gateway for everything possible if someone knows you’re running cntlm (that can be changed as well).

Now we need to make git use it. It’s easy:

$ git config --global http.proxy localhost:3128

$ git clone https://github.com/libgit2/libgit2sharp.git
Cloning into 'libgit2sharp'...
remote: Counting objects: 7992, done.
remote: Compressing objects: 100% (2160/2160), done.
remote: Total 7992 (delta 5944), reused 7634 (delta 5680)
Receiving objects: 100% (7992/7992), 39.44 MiB | 217 KiB/s, done.
Resolving deltas: 100% (5944/5944), done.

That’s it. In case you’re interested in detail info about cntlm command-line parameters, here it is.

Create a free website or blog at WordPress.com.