Skip to content

Commit

Permalink
Fix sasl for DIGEST-MD5, PLAIN, and LOGIN mechanisms, which I don't t…
Browse files Browse the repository at this point in the history
…hink ever actually worked properly.

Add a sasluser argument if a specific identity is required for the
backend, which if unsupplied, tries to guess if a binddn is present.

(Uwe's previous commit fixed EXTERNAL and GSSAPI, which did work, but
randomly failed due to hash ordering.)


Minor style cleanups, remove duplicate/unecessary logic for anonymous
binds.
  • Loading branch information
mahlonsmith committed Oct 13, 2019
1 parent 23469d7 commit 3e5868c
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 20 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ Peter Marschall <peter@adpm.de>
Rick H. <rickh_shelldap@printstring.com>
Rong-En Fan <rafan@FreeBSD.org>
Salvatore Bonaccorso <carnil@debian.org>
Uwe Kleine-König <uwe@kleine-koenig.org>
Yann Cezard <yann.cezard@univ-pau.fr>

60 changes: 40 additions & 20 deletions shelldap
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,20 @@ credentials.
A space separated list of SASL mechanisms. Requires the Authen::SASL
module.
--sasl 'PLAIN CRAM-MD5 GSSAPI'
--sasl 'PLAIN DIGEST-MD5 EXTERNAL GSSAPI'
-Y 'PLAIN DIGEST-MD5 EXTERNAL GSSAPI'
=back
=over 4
=item B<sasluser>
SASL authorization identity, if one is explicitly required by your
backend mechanism.
--sasluser mahlon
-X mahlon
=back
Expand Down Expand Up @@ -709,18 +722,20 @@ sub ldap
You may try connecting insecurely, or install the module and try again.\n} if $@;
}

if ($conf->{'binddn'}) {
if($conf->{'promptpass'}) {
if ( $conf->{'binddn'} ) {
if ( $conf->{'promptpass'} ) {
# Prompt for a password after disabling local echo.
#
print "Bind password: ";
Term::ReadKey::ReadMode 2;
chomp( $conf->{'bindpass'} = <STDIN> );
Term::ReadKey::ReadMode 0;
print "\n";
} elsif($conf->{'pass'}) {
}
elsif ( $conf->{'pass'} ) {
$conf->{'bindpass'} = $conf->{'pass'}
} elsif($conf->{'passfile'}) {
}
elsif ( $conf->{'passfile'} ) {
chomp( $conf->{'bindpass'} = slurp($conf->{'passfile'}));
}
}
Expand Down Expand Up @@ -762,16 +777,20 @@ You may try connecting insecurely, or install the module and try again.\n} if $@
if ( $use_sasl ) {
my $serv = $conf->{'server'};
$serv =~ s!^ldap[si]?://!!;
$sasl = Authen::SASL->new( mechanism => $conf->{'sasl'} );
my $user = $1 if $conf->{'binddn'} && $conf->{'binddn'} =~ /uid=([^,]*),/i;
my $callback = {
pass => $conf->{'bindpass'},
user => $conf->{'sasluser'} || $user
};

$sasl = Authen::SASL->new( mechanism => $conf->{'sasl'}, callback => $callback );
$sasl_conn = $sasl->client_new( 'ldap', $serv );
}

# bind with sasl
#
if ( $sasl_conn ) {
$rv = $ldap->bind( $conf->{'binddn'},
sasl => $sasl_conn
);
$rv = $ldap->bind( $conf->{'binddn'}, sasl => $sasl_conn );
}

# simple bind as an authenticated dn
Expand All @@ -785,7 +804,7 @@ You may try connecting insecurely, or install the module and try again.\n} if $@
# bind anonymously
#
else {
$rv = $sasl_conn ? $ldap->bind( sasl => $sasl_conn ) : $ldap->bind();
$rv = $ldap->bind();
}

my $err = $rv->error();
Expand Down Expand Up @@ -2715,9 +2734,10 @@ Getopt::Long::GetOptions(
'passfile|y=s',
'timeout=i',
'sasl|Y=s',
'sasluser|X=s',
'simple|x!' => sub {
my($opt,$arg) = @_;
$conf->{sasl} = $arg ? undef : 'PLAIN CRAM-MD5 GSSAPI'
$conf->{sasl} = $arg ? undef : 'PLAIN DIGEST-MD5 GSSAPI'
},
'tls_cacert=s',
'tls_cert=s',
Expand Down Expand Up @@ -2755,8 +2775,8 @@ $conf->{'attributes'} ||= ['*'];

# Allow command line option --attributes to override settings from
# config file.
if($conf->{'cmdline_attributes'}) {
$conf->{'attributes'} = $conf->{'cmdline_attributes'}
if ( $conf->{'cmdline_attributes'} ) {
$conf->{'attributes'} = $conf->{'cmdline_attributes'};
}

# create and enter shell loop while also handling Ctrl+C correctly.
Expand All @@ -2774,9 +2794,9 @@ sub ctrl_c_handler {
}
my $sigaction = POSIX::SigAction->new( \&ctrl_c_handler, $sigset, 0);
my $old_action = POSIX::SigAction->new;
POSIX::sigaction(&POSIX::SIGINT, $sigaction, $old_action); # save default one
POSIX::sigaction( &POSIX::SIGINT, $sigaction, $old_action ); # save default one
$shell->cmdloop();
POSIX::sigaction(&POSIX::SIGINT, $old_action); # restore default one
POSIX::sigaction( &POSIX::SIGINT, $old_action ); # restore default one

### List of default config files
###
Expand Down Expand Up @@ -2813,13 +2833,13 @@ sub load_config
my $conf2 = eval { YAML::Syck::Load( $data ) };
die "Invalid YAML in $confpath\n" if $@;

if( $conf2->{'configfile'} and ($confpath eq $conf2->{'configfile'})) {
delete $conf2->{'configfile'}
if ( $conf2->{'configfile'} and ($confpath eq $conf2->{'configfile'}) ) {
delete $conf2->{'configfile'};
}

$conf2->{alias} ||= {};

return($confpath, $conf2);
return( $confpath, $conf2 );
}

### dump YAML config into conf file while making sure that
Expand All @@ -2833,8 +2853,8 @@ sub save_config
my %conf2 = %$conf;
# This check is currently unnecessary because the comparison will always
# be true, but is left here for effect of least surprise in the future.
if( $conf->{configfile} and ($confpath eq $conf->{configfile})) {
delete $conf2{'configfile'}
if ( $conf->{configfile} and ($confpath eq $conf->{configfile}) ) {
delete $conf2{'configfile'};
}
YAML::Syck::DumpFile( $confpath, \%conf2 );
chmod 0600, $confpath;
Expand Down

0 comments on commit 3e5868c

Please sign in to comment.