446 LDAP_BUSY |
459 LDAP_BUSY |
447 LDAP_UNAVAILABLE |
460 LDAP_UNAVAILABLE |
448 LDAP_OTHER |
461 LDAP_OTHER |
449 LDAP_TIMEOUT |
462 LDAP_TIMEOUT |
450 LDAP_NO_MEMORY |
463 LDAP_NO_MEMORY |
451 LDAP_CONNECT_ERROR /; |
464 LDAP_CONNECT_ERROR |
|
465 LDAP_CONTROL_PAGED /; |
452 use Net::LDAP::Util qw/ canonical_dn ldap_explode_dn /; |
466 use Net::LDAP::Util qw/ canonical_dn ldap_explode_dn /; |
453 use Net::LDAP::LDIF; |
467 use Net::LDAP::LDIF; |
|
468 use Net::LDAP::Extension::SetPassword; |
|
469 use Net::LDAP::Control::Paged; |
454 use Data::Dumper; |
470 use Data::Dumper; |
455 use File::Temp; |
471 use File::Temp; |
456 use Algorithm::Diff; |
472 use Algorithm::Diff; |
457 use Carp 'confess'; |
473 use Carp 'confess'; |
458 use base 'Term::Shell'; |
474 use base 'Term::Shell'; |
459 require Net::LDAP::Extension::SetPassword; |
|
460 |
475 |
461 my $conf = $main::conf; |
476 my $conf = $main::conf; |
462 |
477 |
463 # make 'die' backtrace in debug mode |
478 # make 'die' backtrace in debug mode |
464 $SIG{'__DIE__'} = \&Carp::confess if $conf->{'debug'}; |
479 $SIG{'__DIE__'} = \&Carp::confess if $conf->{'debug'}; |
504 if ( $conf->{'debug'} ) { |
519 if ( $conf->{'debug'} ) { |
505 my @versions = $self->{'root_dse'}->get_value('supportedLDAPVersion'); |
520 my @versions = $self->{'root_dse'}->get_value('supportedLDAPVersion'); |
506 print "Connected to $conf->{'server'}\n"; |
521 print "Connected to $conf->{'server'}\n"; |
507 print "Supported LDAP version: ", ( join ', ', @versions ), "\n"; |
522 print "Supported LDAP version: ", ( join ', ', @versions ), "\n"; |
508 print "Cipher in use: ", $self->ldap()->cipher(), "\n"; |
523 print "Cipher in use: ", $self->ldap()->cipher(), "\n"; |
|
524 } |
|
525 |
|
526 # check for the pagination extension on the server early, and bail |
|
527 # if necessary. |
|
528 if ( $conf->{'paginate'} && $conf->{'paginate'} =~ /^\d+$/ && $conf->{'paginate'} > 0 ) { |
|
529 my $has_pagination = ( grep $_ eq LDAP_CONTROL_PAGED, $self->{'root_dse'}->get_value('supportedControl') ); |
|
530 die "Server pagination is enabled, but the server doesn't seem to support it.\n" unless $has_pagination; |
|
531 } |
|
532 else { |
|
533 $conf->{'paginate'} = undef; |
509 } |
534 } |
510 |
535 |
511 # try an initial search and bail early if it doesn't work. (bad baseDN?) |
536 # try an initial search and bail early if it doesn't work. (bad baseDN?) |
512 my $s = $self->search(); |
537 my $s = $self->search(); |
513 die "LDAP baseDN error: ", $s->{'message'}, "\n" if $s->{'code'}; |
538 die "LDAP baseDN error: ", $s->{'message'}, "\n" if $s->{'code'}; |
871 } |
896 } |
872 return; |
897 return; |
873 } |
898 } |
874 |
899 |
875 |
900 |
876 ### Perform an LDAP search. |
901 ### Perform an LDAP search, optionally with the server side pager |
|
902 ### control. |
877 ### |
903 ### |
878 ### Returns a hashref containing the return code and |
904 ### Returns a hashref containing the return code and |
879 ### an arrayref of Net::LDAP::Entry objects. |
905 ### an arrayref of Net::LDAP::Entry objects. |
880 ### |
906 ### |
881 sub search |
907 sub search |
882 { |
908 { |
883 my $self = shift; |
909 my $self = shift; |
884 my $opts = shift || {}; |
910 my $opts = shift || {}; |
|
911 my $controls = []; |
885 |
912 |
886 $opts->{'base'} ||= $self->base(), |
913 $opts->{'base'} ||= $self->base(), |
887 $opts->{'filter'} ||= '(objectClass=*)'; |
914 $opts->{'filter'} ||= '(objectClass=*)'; |
888 $opts->{'scope'} ||= 'base'; |
915 $opts->{'scope'} ||= 'base'; |
|
916 |
|
917 my $pager; |
|
918 if ( $conf->{'paginate'} ) { |
|
919 $pager = Net::LDAP::Control::Paged->new( size => $conf->{'paginate'} ); |
|
920 push( @$controls, $pager ); |
|
921 } |
889 |
922 |
890 my $search = sub { |
923 my $search = sub { |
891 return $self->ldap->search( |
924 return $self->ldap->search( |
892 base => $opts->{'base'}, |
925 base => $opts->{'base'}, |
893 filter => $opts->{'filter'}, |
926 filter => $opts->{'filter'}, |
894 scope => $opts->{'scope'}, |
927 scope => $opts->{'scope'}, |
895 timelimit => $conf->{'timeout'}, |
928 timelimit => $conf->{'timeout'}, |
896 typesonly => ! $opts->{'vals'}, |
929 typesonly => ! $opts->{'vals'}, |
897 attrs => $opts->{'attrs'} || ['*'] |
930 attrs => $opts->{'attrs'} || ['*'], |
|
931 control => $controls |
898 ); |
932 ); |
899 }; |
933 }; |
900 |
934 |
901 my $s = $self->with_retry( $search ); |
935 my $s; |
|
936 my $entries = []; |
|
937 my $token = '-'; |
|
938 |
|
939 if ( $conf->{'paginate'} ) { |
|
940 while( $token ) { |
|
941 $s = $self->with_retry( $search ); |
|
942 push( @$entries, $s->entries() ); |
|
943 |
|
944 my $page_response = $s->control( LDAP_CONTROL_PAGED ) or last; |
|
945 $token = $page_response->cookie; |
|
946 $pager->cookie( $token ); |
|
947 } |
|
948 } |
|
949 else { |
|
950 $s = $self->with_retry( $search ); |
|
951 $entries = [ $s->entries() ]; |
|
952 } |
|
953 |
902 my $rv = { |
954 my $rv = { |
903 code => $s->code(), |
955 code => $s->code(), |
904 message => $s->error(), |
956 message => $s->error() |
905 entries => [] |
|
906 }; |
957 }; |
907 |
958 |
908 $rv->{'entries'} = |
959 if ( $opts->{'scope'} eq 'base' ) { |
909 $opts->{'scope'} eq 'base' ? [ $s->shift_entry() ] : [ $s->entries() ]; |
960 $rv->{'entries'} = [ $s->shift_entry() ] |
|
961 } |
|
962 else { |
|
963 $rv->{'entries'} = $entries; |
|
964 } |
910 |
965 |
911 return $rv; |
966 return $rv; |
912 } |
967 } |
913 |
968 |
914 |
969 |
2348 if ( $conf->{'configfile'} ) { |
2404 if ( $conf->{'configfile'} ) { |
2349 my $more_conf = load_config( $conf->{'configfile'} ); |
2405 my $more_conf = load_config( $conf->{'configfile'} ); |
2350 while ( my ($k, $v) = each %{$conf} ) { $conf->{ $k } = $v } |
2406 while ( my ($k, $v) = each %{$conf} ) { $conf->{ $k } = $v } |
2351 } |
2407 } |
2352 |
2408 |
2353 |
|
2354 # defaults |
2409 # defaults |
2355 $conf->{'configfile'} ||= "$ENV{'HOME'}/.shelldap.rc"; |
2410 $conf->{'configfile'} ||= "$ENV{'HOME'}/.shelldap.rc"; |
2356 $conf->{'cacheage'} ||= 300; |
2411 $conf->{'cacheage'} ||= 300; |
2357 $conf->{'timeout'} ||= 10; |
2412 $conf->{'timeout'} ||= 10; |
2358 |
2413 |