use strict;
use Net::POP3;
use Authen::SASL;
.
.
.
my $sasl=new Authen::SASL(mechanism=> "GSSAPI SASL",
callback => {
user => $USERNAME,
pass => $PASSWORD,
}
);
my $pop=Net::POP3->new($SERVER)
or die "Unable to connect to mail server: ",$!,"\n";
if ($pop->auth($sasl) > 0) {
my $messages=$pop->list()
or die "Unable to get messages: ",$!,"\n";
}
else {
print "Authentication failed: ",$!,"\n";
}
Note that '$!' contains nothing when it prints my authentication
failed message.
Can someone on this list help me or at least point me to a more
appropriate forum? Thanks.
--On Thursday, May 18, 2006 7:27 AM -0400 Dennis Putnam
<dennis...@aimaudit.com> wrote:
> I was told some of you folks are working with Kerberos auth using
> GSSAPI. I am trying to do the same thing with POP rather then LDAP and I
> am hoping someone here might be able to help me. It is not obvious to me
> what I really need to pass in the 'auth' method so I suspect that is the
> crux of my problem. When I try to authenticate to the POP server it
> fails and all that shows up in the POP log is 'badlogin'. Here is my
> relevant code:
>
> use strict;
> use Net::POP3;
> use Authen::SASL;
I was able to use Authen::SASL to do GSSAPI authentication via finger &
whois, using the Authen-SASL-GSSAPI-server package.
The following are my code snippets that may help you in the right direction:
############################################################################
# SASL related subroutines
############################################################################
sub sendreply
{
$SIG{PIPE} = 'IGNORE'; # Client is closing too fast
my ($s,$so) = @_;
$s = " " unless $s;
#print "Sendreply: ",substr($s,0,10),"\n";
syswrite ($so,$s);
}
sub getreply
{
my ($so) = @_;
my $s;
#print "Getreply is waiting.\n";
sysread($so,$s,4096);
#print "Getreply: ",substr($s,0,10),"\n";
return $s;
}
sub query_server {
my ($server, $query, $port) = @_;
# I tried using IO::Socket here, but the load time was noticeable.
# Using Getopt::Long is bad enough. On top of that, IO::Socket doesn't
# return meaningful error codes that I can see, so one can't distinguish
# between, say, "connection refused" and "host unreachable."
my $address = inet_aton ($server)
or die "Can't resolve server name $server\n";
my $proto = getprotobyname 'tcp';
$port ||= 43;
if ($port =~ /\D/) {
my $service = $port;
$port = getservbyname ($service, 'tcp')
or die "Unknown service $service\n";
}
socket (S, PF_INET, SOCK_STREAM, $proto)
or die "Can't create local socket: $!\n";
connect (S, sockaddr_in ($port, $address))
or die "Can't connect to $server: $!\n";
my $oldfh = select S; $| = 1; select $oldfh;
my $remote_ip = inet_ntoa($address);
my ($local_port, $local_ip) = sockaddr_in(getsockname(S));
$local_ip = inet_ntoa($local_ip);
#print "$local_ip;$local_port $remote_ip;$port\n";
my $saslClient = Authen::SASL->new (
mechanism => "GSSAPI",
callback => {
}
);
my $conn = $saslClient->client_new("host", "$remote_ip",
"$local_ip;$local_port", "$remote_ip;$port");
sendreply($conn->client_start(),\*S,0);
while ($conn->need_step) {
sendreply($conn->client_step(&getreply(\*S) ), \*S );
}
--Quanah
--
Quanah Gibson-Mount
Principal Software Developer
ITS/Shared Application Services
Stanford University
GnuPG Public Key: http://www.stanford.edu/~quanah/pgp.html
Dennis Putnam
Sr. IT Systems Administrator
AIM Systems, Inc.
11675 Rainwater Dr., Suite 200
Alpharetta, GA 30004
Phone: 678-240-4112
Main Phone: 678-297-0700
FAX: 678-297-2666 or 770-576-1000
The information contained in this e-mail and any attachments is
strictly confidential. If you are not the intended recipient, any
use, dissemination, distribution, or duplication of any part of this
e-mail or any attachment is prohibited. If you are not the intended
recipient, please notify the sender by return e-mail and delete all
copies, including the attachments.
>
> I was able to use Authen::SASL to do GSSAPI authentication via finger &
> whois, using the Authen-SASL-GSSAPI-server package.
What you show below is basically what most modules, eg Net::POP3 and
Net::LDAP, do behind the scenes.
I think the question that Dennis needs answered is what to use as callback
values when authenticating using Kerberos, SASL and GSSAPI
Graham.
Using Authen::SASL as a programmer means
1. create a Authen::SASL object
my $sasl = Authen::SASL->new( mechanism => 'GSSAPI' );
2. Pass this SASL object to the constructor/authentication method
of Protocol object you want to use.
From my point of view the POD of Net::POP3 (2.28) has
no method to pass an Authen::SASL object to Net::POP3
That means that at the Moment the Net::POP3 module can't use
ojects Authen::SASL interface like Authen::SASL::Perl::GSSAPI.
Somthing like
$pop3object->bind( sasl => $sasl );
is missing.
@Graham:
-is that correct?
-can you add that to Net::POP3?
My working example (with Net::LDAP, now part
of the Authen::SASL::Perl::GSSAPI POD) is this:
#! /usr/bin/perl -w
use strict;
use Net::LDAP 0.33;
use Authen::SASL 2.10;
# -------- Adjust to your environment --------
my $adhost = 'theserver.bla.net';
my $ldap_base = 'dc=bla,dc=net';
my $ldap_filter = '(&(sAMAccountName=BLAAGROL))';
my $sasl = Authen::SASL->new( mechanism => 'GSSAPI' );
my $ldap;
eval {
$ldap = Net::LDAP->new( $adhost,
onerror => 'die',
) or die "Cannot connect to LDAP host '$adhost':
'$@'";
$ldap->bind( sasl => $sasl );
};
if ($@) {
chomp $@;
die "\nBind error : $@",
"\nDetailed SASL error: ", $sasl->error,
"\nTerminated";
}
print "\nLDAP bind() succeeded, working in authenticated state";
my $mesg = $ldap->search( base => $ldap_base,
filter => $ldap_filter );
# -------- evaluate $mesg
> What you show below is basically what most modules, eg Net::POP3 and
> Net::LDAP, do behind the scenes.
>
> I think the question that Dennis needs answered is what to use as callback
> values when authenticating using Kerberos, SASL and GSSAPI
Hmm, I think he needs a way to pass the Authen::SASL object
to the Net::POP3 module.
Net::LDAP simply uses the Authen::SASL interface of the SASL object
passed to bind().
How can that "use the sasl-objetcs interface only" be done with
Net::POP3?
Achim
> How can that "use the sasl-objetcs interface only" be done with
> Net::POP3?
I have no GSSAPI enabeled POP3 Server to test, but my idea is to add
a authsasl() method to Net::POP3 that accepts the Authen::SASL object.
Does that work? I have no chance to test it myself at the moment:
#------usage example--------------
use Authen::SASL 2.10;
use Net::POP3;
my $sasl = Authen::SASL->new( mechanism => 'GSSAPI' );
$pop = Net::POP3->new('pop3host');
$pop->authsasl($sasl);
my $msgnums = $pop->list; # hashref of msgnum => size
foreach my $msgnum (keys %$msgnums) {
my $msg = $pop->get($msgnum);
print @$msg;
}
$pop->quit;
#------end of usage example--------------
#--------changes to Net::POP3--------------------
# add this to Net::POP3 pm-file
#
sub authsasl {
my ($self, $sasl) = @_;
eval {
require MIME::Base64;
} or $self->set_status(500,["Need MIME::Base64 todo auth"]), return 0;
my $client = $sasl->client_new('pop3',${*$self}{'net_pop3_host'},0);
my $str = $client->client_start;
my @cmd = ("AUTH", $client->mechanism);
my $code;
push @cmd, MIME::Base64::encode_base64($str,'')
if defined $str and length $str;
while (($code = $self->command(@cmd)->response()) == CMD_MORE) {
@cmd = (MIME::Base64::encode_base64(
$client->client_step(
MIME::Base64::decode_base64(
($self->message)[0]
)
), ''
));
}
$code == CMD_OK;
}
#--------end of changes to Net::POP3--------------------
$pop3->auth($sasl); should work. Maybe the docs need updating.
Graham.
> $pop3->auth($sasl); should work. Maybe the docs need updating.
I'm reading the sources of Net::POP3 2.28 (actual CPAN version).
The Code is
#----------------------------------------------------------
sub auth {
my ($self, $username, $password) = @_;
eval {
require MIME::Base64;
require Authen::SASL;
} or $self->set_status(500,["Need MIME::Base64 and Authen::SASL todo
auth"]), return 0;
my $capa = $self->capa;
my $mechanisms = $capa->{SASL} || 'CRAM-MD5';
my $sasl;
if (ref($username) and UNIVERSAL::isa($username,'Authen::SASL')) {
$sasl = $username;
$sasl->mechanism($mechanisms);
}
else {
die "auth(username, password)" if not length $username;
$sasl = Authen::SASL->new(mechanism=> $mechanisms,
callback => { user => $username,
pass => $password,
authname => $username,
});
}
#----------------------------------------------------------
sub auth() does not accept a SASL object as parameter, it creates it's own
SASL object inside.
> if (ref($username) and UNIVERSAL::isa($username,'Authen::SASL')) {
> $sasl = $username;
> $sasl->mechanism($mechanisms);
Yes, and that's the part of the code that accepts the SASL object.
Stupid me.
I am sorry!
Achim
a SASL object this should work:
#------usage example--------------
use Authen::SASL 2.10;
use Net::POP3;
my $sasl = Authen::SASL->new( mechanism => 'GSSAPI' );
$pop = Net::POP3->new('pop3host');
$pop->auth($sasl);
my $msgnums = $pop->list; # hashref of msgnum => size
foreach my $msgnum (keys %$msgnums) {
my $msg = $pop->get($msgnum);
print @$msg;
}
$pop->quit;
#------end of usage example--------------
Dennis, please try and let us know if this works!
Achim
Thanks,
Don
The core GSSAPI module is writte in XS.
That means you need the C-compiler the AS Perl
was build with do build the GSSAPI module.
(Like to compile all other modules that should
run with AS-Perl)
An alternative is to
- use cygwin and it's toolchain
- build Perl with cygwin
- Build MIT Kerberos or Heimdal with cygwin
- Build GSSAPI module with cygwin
- Install Authen::SASL::Perl::GSSAPI
Does that help?
Achim
Yes, Graham and anyone answered on Thursday.
Me wrote on
Thursday 22:07:08
If the Net::POP3 auth() method accepts
a SASL object this should work:
#------usage example--------------
use Authen::SASL 2.10;
use Net::POP3;
my $sasl = Authen::SASL->new( mechanism => 'GSSAPI' );
Note that this is OS X Server (10.4.6), if that matters.
Try if this works:
#------usage example--------------
use strict;
use Authen::SASL 2.10 qw(Perl);
use Net::POP3;
my $pop3host = 'pop3host';
my $sasl = Authen::SASL->new( mechanism => 'GSSAPI' );
my $pop = Net::POP3->new( $pop3host ) || die "can not connect to $pop3host ";
if ( $pop->auth($sasl) ) {
my $msgnums = $pop->list; # hashref of msgnum => size
foreach my $msgnum (keys %$msgnums) {
my $msg = $pop->get($msgnum);
print @$msg;
}
}
else {
die "\n Authentication error from SASL: \n",
$sasl->error;
Dennis,
I have attached an example with more debugging output.
Please test and send back output.
Achim
#------usage example--------------
use strict;
use Authen::SASL 2.10;
use Net::POP3 2.28;
#----Adjust to your environment------
my $pop3host = 'moerbsen.grolmsnet.lan';
#----/Adjust to your environment------
my $sasl = Authen::SASL->new( mechanism => 'GSSAPI' )
|| die 'cannot create SASL object';
#----Just debugging, not needed-----
my $client = $sasl->client_new( 'pop3', $pop3host );
$client->client_start();
print $sasl->error();
#----/Just debugging, not needed-----
my $pop = Net::POP3->new( $pop3host ) || die "can not connect to $pop3host ";
if ( $pop->auth($sasl) ) {
my $msgnums = $pop->list; # hashref of msgnum => size
foreach my $msgnum (keys %$msgnums) {
my $msg = $pop->get($msgnum);
print @$msg;
}
}
else {
die "\n Authentication error from SASL: \n",
$sasl->error,
I would not expect it to, as-is. The structure is right, but it needs
authentication details to be added. But my knowledge of how GSSAPI works
and what parameters are needed for it to validate is very limited.
Graham.
The Authen::SASL::Perl::GSSAPI module needs
a properly confugurd Kerberosinstallation and a successfull kinit.
All work is done by the Kerberosimplementation.
What details are missing?
Achim
Ah, I was not aware it did all that behind the scenes.
> What details are missing?
In that case, nothing :-)
Graham.
[...Net::POP3...]
> I was able to use Authen::SASL to do GSSAPI authentication via finger &
> whois, using the Authen-SASL-GSSAPI-server package.
Net::POP3 2.28
accepts SASL objects for doing SASL authentication and plays
together with Authen::SASL::Perl::GSSAPI.
The problem was that Net::POP3 2.28 uses the wrong servivename 'pop3'
in
| my $client = $sasl->client_new('pop3',${*$self}{'net_pop3_host'},0);
what makes GSSAPI fail because the servivcename is part of the principal
( "pop3/theserver.domain.tld" for example) and a principal
"pop3/theserver.domain.tld" does not exist
in KDC database.
Correct is 'pop' instead as specified in
<http://www.iana.org/assignments/gssapi-service-names>.
That means only
| my $client = $sasl->client_new('pop',${*$self}{'net_pop3_host'},0);
works when connecting to a POP3 server.
Achim