File Coverage

blib/lib/LWP/Authen/Negotiate.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package LWP::Authen::Negotiate;
2              
3 1     1   26247 use strict;
  1         3  
  1         41  
4 1     1   6 use warnings;
  1         2  
  1         30  
5              
6 1     1   896 use LWP::Debug;
  1         520  
  1         5  
7              
8             require Exporter;
9 1     1   1008 use AutoLoader qw(AUTOLOAD);
  1         1469  
  1         5  
10              
11             our @ISA = qw(Exporter);
12              
13             # Items to export into callers namespace by default. Note: do not export
14             # names by default without a very good reason. Use EXPORT_OK instead.
15             # Do not simply export all your public functions/methods/constants.
16              
17             # This allows declaration use LWP::Authen::Negotiate ':all';
18             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
19             # will save memory.
20             our %EXPORT_TAGS = ( 'all' => [ qw(
21              
22             ) ] );
23              
24             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
25              
26             our @EXPORT = qw(
27              
28             );
29              
30             our $VERSION = '0.08';
31              
32              
33 1     1   1115 use MIME::Base64 "2.12";
  1         929  
  1         164  
34 1     1   450 use GSSAPI 0.18;
  0            
  0            
35              
36              
37             sub authenticate
38             {
39             LWP::Debug::debug("authenticate() version $VERSION called");
40             my ($class,$ua,$proxy,$auth_param,$response,$request,$arg,$size) = @_;
41              
42             my $uri = URI->new($request->uri);
43             my $targethost = $request->uri()->host();
44              
45             my $otoken;
46             my $status;
47             TRY: {
48             my ($target, $tname);
49              
50             # import the servername from LWP request
51             # to a GSSAPI tokenname. Import can fail
52             # in case of broken DNS or /etc/hosts
53             # or missing Kerberosprincipal for target system
54             #
55             LWP::Debug::debug("target hostname $targethost");
56             $status = GSSAPI::Name->import(
57             $target,
58             join( '@', 'HTTP', $targethost ),
59             GSSAPI::OID::gss_nt_hostbased_service
60             );
61             last TRY if ( $status->major != GSS_S_COMPLETE );
62             $status = $target->display( $tname );
63             last TRY if ( $status->major != GSS_S_COMPLETE );
64              
65             LWP::Debug::debug("GSSAPI servicename $tname");
66             my $auth_header = $proxy ? 'Proxy-Authorization'
67             : 'Authorization';
68              
69             my $itoken = q{};
70             foreach ($response->header('WWW-Authenticate')) {
71             last if /^Negotiate (.+)/ && ($itoken=decode_base64($1));
72             }
73              
74             # Preload gss_init_security_context parameters
75             # see RFC 2744 5.19. gss_init_sec_context
76             #
77             my $ctx = GSSAPI::Context->new();
78             my $imech = GSSAPI::OID::gss_mech_krb5;
79              
80             my $iflags = GSS_C_REPLAY_FLAG;
81             if ( $ENV{LWP_AUTHEN_NEGOTIATE_DELEGATE} ) {
82             $iflags = $iflags
83             | GSS_C_MUTUAL_FLAG
84             | GSS_C_DELEG_FLAG;
85             }
86             my $bindings = GSS_C_NO_CHANNEL_BINDINGS;
87             my $creds = GSS_C_NO_CREDENTIAL;
88             my $itime = 0;
89             #
90             # let's go with init_security_context!
91             #
92             $status = $ctx->init( $creds, $target,
93             $imech, $iflags, $itime , $bindings,$itoken,
94             undef, $otoken, undef, undef);
95             if ( $status->major == GSS_S_COMPLETE
96             or $status->major == GSS_S_CONTINUE_NEEDED ) {
97             LWP::Debug::debug( 'successfull $ctx->init()');
98             my $referral = $request->clone;
99             $referral->header( $auth_header => "Negotiate ".encode_base64($otoken,""));
100             return $ua->request( $referral, $arg, $size, $response );
101             }
102             }
103             #
104             # this is the errorhandler,
105             # the try block is normally leaved via return
106             #
107             LWP::Debug::debug( $status->generic_message());
108             LWP::Debug::debug( $status->specific_message() );
109             return $response;
110              
111             }
112              
113             1;
114             __END__