As I mentioned in the dim and distant past, I've been working on adding native GSSAPI support to Authen::SASL::Perl, so that the Authen::SASL::Cyrus module isn't required to use Kerberos.
Attached is the first cut of this support. It supports GSSAPI authentication, but does not implement security layers. This means that whilst a connection to the server using this module is authenticated, it is _not_ encrypted or integrity checked, and can be subverted by a man in the middle attacker. Security layers are a work in progress, I suspect that they may require some changes to the Authen::SASL::Perl framework, so I'll send them in an additional patch. Feedback welcome! Cheers, Simon.
Index: lib/Authen/SASL/Perl/GSSAPI.pm =================================================================== --- lib/Authen/SASL/Perl/GSSAPI.pm (revision 0) +++ lib/Authen/SASL/Perl/GSSAPI.pm (revision 0) @@ -0,0 +1,87 @@ +# Copyright (c) 2006 Simon Wilkinson +# All rights reserved. This program is free software; you can redistribute +# it and/or modify it under the same terms as Perl itself. + +package Authen::SASL::Perl::GSSAPI; + +use strict; + +use vars qw($VERSION @ISA); +use GSSAPI; + +$VERSION= "0.01"; [EMAIL PROTECTED] = qw(Authen::SASL::Perl); + +my %secflags = ( + noplaintext => 1, + noanonymous => 1, +); + +sub _order { 4 } +sub _secflags { + shift; + scalar grep { $secflags{$_} } @_; +} + +sub mechanism { 'GSSAPI' } + +sub client_start { + my $self = shift; + my $status; + my $principal = $self->service."@".$self->host; + + $self->{gss_name} = new GSSAPI::Name; + $status = $self->{gss_name}->import($self->{gss_name}, $principal, + gss_nt_service_name) + or return $self->set_error("GSSAPI Error : ".$status); + $self->{gss_ctx} = new GSSAPI::Context; + $self->{gss_state} = 0; + return $self->client_step(""); +} + +sub client_step +{ + my ($self, $challenge) = @_; + + my $status; + + if ($self->{gss_state}==0) { + my $outtok; + my $flags; + $status = $self->{gss_ctx}->init(undef, $self->{gss_name}, + gss_mech_krb5, + GSS_C_INTEG_FLAG | GSS_C_MUTUAL_FLAG, + undef, undef, $challenge, undef, + $outtok, $flags, undef); + + if (GSSAPI::Status::GSS_ERROR($status->major)) { + return $self->set_error("GSSAPI Error : ".$status); + } + if ($status->major == GSS_S_COMPLETE) { + $self->{gss_state}=1; + } + return $outtok; + } elsif ($self->{gss_state}==1) { + # If the server has an empty output token when it COMPLETEs, Cyrus SASL + # kindly sends us that empty token. We need to ignore it, which introduces + # another round into the process. + return "" if $challenge eq ""; + + my $unwrapped; + $status = $self->{gss_ctx}->unwrap($challenge, $unwrapped, undef, undef) + or return $self->set_error("GSSAPI Error : ".$status); + + # XXX - Security layer support will require us to decode this packet + + # Need to set message to be 0x01, 0x00, 0x00, 0x00 for no security layers + my $message = pack('CCCC', 0x01, 0x00, 0x00, 0x00); + $message.= $self->_call('user'); + my $outtok; + $status = $self->{gss_ctx}->wrap(0, undef, $message, undef, $outtok) + or return $self->set_error("GSSAPI Error : ".$status); + + $self->{gss_state}=0; + return $outtok; + } +} +