Ruby Win32 SSPI 0.0.1 - Enabling NTLM/Negotiate proxy authen

My work place implemented install a proxy server recently, and because
it
demands NTLM/Negotiate authentication, a bunch of my “utility” scripts
that
scraped the web for me stopped working. Well, that sounded like the
opportunity to develop a cool Ruby library!

This library provides bindings to the Win32 SSPI library, which enables
authentication as the current user with proxy servers using the
“Negotiate”/SPNEGO protocol (which typically just means NTLM).

There are some pure Ruby implementations of the NTLM protocol, but this
is
the only one I know of that will authenticate with a proxy server as the
current user - meaning you don’t have to put your username or password
in an
environment variable or anywhere else.

The library also includes a patch for open-uri and Net:HTTP that will
make
the authentication process seamless.

I have only tested this in my own environment so I’m sure its fragile.
Please try it out if you have run into this issue yourself.

The project can be found at:

  • fingers slipped and I sent previous announcement early - oops! *

My work place implemented install a proxy server recently, and because
it
demands NTLM/Negotiate authentication, a bunch of my “utility” scripts
that
scraped the web for me stopped working. Well, that sounded like the
opportunity to develop a cool Ruby library!

This library provides bindings to the Win32 SSPI library, which enables
authentication as the current user with proxy servers using the
“Negotiate”/SPNEGO protocol (which typically just means NTLM).

There are some pure Ruby implementations of the NTLM protocol, but this
is
the only one I know of that will authenticate with a proxy server as the
current user - meaning you don’t have to put your username or password
in an
environment variable or anywhere else.

The library also includes a patch for open-uri and Net:HTTP that will
make
the authentication process seamless.

I have only tested this in my own environment so I’m sure its fragile.
Please try it out if you have run into this issue yourself.

The project can be found at: http://rubyforge.org/projects/rubysspi/

Gem install will be available when the index updates:

gem install rubysspi

Documentation is available in the gem, but here is the README from the
distribution. Comments and feedback welcome!

Justin

=== README ===

= Introduction

This library provides bindings to the Win32 SSPI libraries, which
implement
various security protocols for Windows. The library was primarily
developed
to give Negotiate/NTLM proxy authentication abilities to Net::HTTP,
similar
to support found in Internet Explorer or Firefox.

The libary is NOT an implementation of the NTLM protocol, and does not
give
the ability to authenticate as any given user. It is able to
authenticate
with a proxy server as the current user.

This project can be found on rubyforge at:

http://rubyforge.org/projects/rubysspi

= Using with open-uri

To use the library with open-uri, make sure to set the environment
variable
+http_proxy+ to your proxy server. This must be a hostname and port in
URL
form. E.g.:

http://proxy.corp.com:8080

The library will grab your current username and domain from the
environment
variables +USERNAME+ and +USERDOMAIN+. This should be set for you by
Windows
already.

The library implements a patch on top of Net::HTTP, which means open-uri
gets it too. At the top of your script, make sure to require the patch
after
+open-uri+:

require +open-uri+
require +rubysspi/proxy_auth+

open(“http://www.google.com”) { |f| puts(f.gets(nil)) }

Note that this patch does NOT work with the +http_proxy_user+ and
+http_proxy_password+ environment variables. The library will ONLY
authenticate as the current user.

= Using with Net::HTTP

Net::HTTP will not use the proxy server supplied in the environment
variable
automatically, so you have to supply the proxy address yourself.
Otherwise,
it’s exactly the same:

require ‘net/http’
require 'rubysspi/proxy_auth+

Net::HTTP::Proxy(“proxy.corp.com”, 8080).start(“www.google.com”) do
|http|
resp = http.request_get “/”
puts resp.body
end

= Using rubysspi directly

As stated, the library is geared primarily towards supporting
Negotiate/NTLM
authentication with proxy servers. In this vein, you can manually
authenticate a given HTTP connection with a single call:

require ‘rubysspi’

Net::HTTP.Proxy(proxy.host, proxy.port).start(“www.google.com”) do
|http|
resp = SSPI::NegotiateAuth.proxy_auth_get http, “/”
end

The +resp+ variable will contain the response from Google, with any
proxy
authorization necessary taken care of automatically. Note that if the
+http+
connection is not closed, any subsequent requests will NOT require
authentication.

If the above method is used, it is recommended that you do NOT require
the
‘rubysspi/proxy_auth’ library, as the interaction between the two will
fail.

The library can be used directly to generate tokens appropriate for the
current user, too.

To get started, first create an instance of the SSPI::NegotiateAuth
class:

require ‘rubysspi’

n = SSPI::NegotiateAuth.new

Next, get the first token by calling get_initial_token:

token = n.get_initial_token

This token returned will be Base64 encoded and can be directly placed in
an
HTTP header. This token can be easily decoded, however, and is usually
an
NTLM Type 1 message.

After getting a response from the server (usually an NTLM Type 2
message),
pass it into the complete_authentication:

token = n.complete_authentication(server_token)

Note that server_token can be Base64 encoded or not, and if it starts
with
“Negotiate”, that phrase will be stripped off. This allows the response
from
a Proxy-Authentication header to be passed into the method directly. The
token can be decoded externally and passed in, too.

The token returned (usually an NTLM Type 3) message can then be sent to
the
server and the connection should be authenticated.

= Thanks & References

Many references were used in decoding both NTLM messages and integrating
with the SSPI library. Among them are:

And of course, thanks to my Lord and Savior, Jesus Christ. In the name
of
the Father, the Son, and the Holy Spirit.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs