perl-ldap

 view release on metacpan or  search on metacpan

lib/Net/LDAP.pm  view on Meta::CPAN

  undef => sub { require Carp; Carp::carp(_err_msg(@_))  if $^W; undef },
);

sub _error {
  my ($ldap, $mesg) = splice(@_, 0, 2);

  $mesg->set_error(@_);
  $ldap->{net_ldap_onerror} && !$ldap->{net_ldap_async}
    ? scalar &{$ldap->{net_ldap_onerror}}($mesg)
    : $mesg;
}

sub new {
  my $self = shift;
  my $type = ref($self) || $self;
  my $host = shift  if @_ % 2;
  my $arg  = &_options;
  my $obj  = bless {}, $type;

  foreach my $uri (ref($host) ? @$host : ($host)) {
    my $scheme = $arg->{scheme} || 'ldap';
    my $h = $uri;
    if (defined($h)) {
      $h =~ s,^(\w+)://,, and $scheme = lc($1);
      $h =~ s,/.*,,; # remove path part
      $h =~ s/%([A-Fa-f0-9]{2})/chr(hex($1))/eg; # unescape
    }
    my $meth = $obj->can("connect_$scheme")  or next;
    if (&$meth($obj, $h, $arg)) {
      $obj->{net_ldap_uri} = $uri;
      $obj->{net_ldap_scheme} = $scheme;
      last;
    }
  }

  return undef  unless $obj->{net_ldap_socket};

  $obj->{net_ldap_socket}->setsockopt(SOL_SOCKET, SO_KEEPALIVE, $arg->{keepalive} ? 1 : 0)
    if (defined($arg->{keepalive}));

  $obj->{net_ldap_rawsocket} = $obj->{net_ldap_socket};
  $obj->{net_ldap_resp}    = {};
  $obj->{net_ldap_version} = $arg->{version} || $LDAP_VERSION;
  $obj->{net_ldap_async}   = $arg->{async} ? 1 : 0;
  $obj->{raw} = $arg->{raw}  if ($arg->{raw});

  if (defined(my $onerr = $arg->{onerror})) {
    $onerr = $onerror{$onerr}  if exists $onerror{$onerr};
    $obj->{net_ldap_onerror} = $onerr;
  }

  $obj->debug($arg->{debug} || 0 );

  $obj->outer;
}

sub connect_ldap {
  my ($ldap, $host, $arg) = @_;
  my $port = $arg->{port} || 389;
  my $class = (CAN_IPV6) ? CAN_IPV6 : 'IO::Socket::INET';
  my $domain = $arg->{inet4} ? AF_INET : ($arg->{inet6} ? AF_INET6 : AF_UNSPEC);

  # separate port from host overwriting given/default port
  $host =~ s/^([^:]+|\[.*\]):(\d+)$/$1/ and $port = $2;

  if ($arg->{inet6} && !CAN_IPV6) {
    $@ = 'unable to load IO::Socket::INET6; no IPv6 support';
    return undef;
  }

  $ldap->{net_ldap_socket} = $class->new(
    PeerAddr   => $host,
    PeerPort   => $port,
    LocalAddr  => $arg->{localaddr} || undef,
    Proto      => 'tcp',
    ($class eq 'IO::Socket::IP' ? 'Family' : 'Domain')     => $domain,
    MultiHomed => $arg->{multihomed},
    Timeout    => defined $arg->{timeout}
		 ? $arg->{timeout}
		 : 120
  ) or return undef;

  $ldap->{net_ldap_host} = $host;
  $ldap->{net_ldap_port} = $port;
}


# Different OpenSSL verify modes.
my %ssl_verify = qw(none 0 optional 1 require 3);

sub connect_ldaps {
  my ($ldap, $host, $arg) = @_;
  my $port = $arg->{port} || 636;
  my $domain = $arg->{inet4} ? AF_INET : ($arg->{inet6} ? AF_INET6 : AF_UNSPEC);

  if ($arg->{inet6} && !CAN_IPV6) {
    $@ = 'unable to load IO::Socket::INET6; no IPv6 support';
    return undef;
  }

  require IO::Socket::SSL;

  # separate port from host overwriting given/default port
  $host =~ s/^([^:]+|\[.*\]):(\d+)$/$1/ and $port = $2;

  $ldap->{net_ldap_socket} = IO::Socket::SSL->new(
    PeerAddr 	    => $host,
    PeerPort 	    => $port,
    LocalAddr       => $arg->{localaddr} || undef,
    Proto    	    => 'tcp',
    Domain          => $domain,
    Timeout  	    => defined $arg->{timeout} ? $arg->{timeout} : 120,
    _SSL_context_init_args({sslserver => $host, %$arg})
  ) or return undef;

  $ldap->{net_ldap_host} = $host;
  $ldap->{net_ldap_port} = $port;
}

sub _SSL_context_init_args {
  my $arg = shift;

  my $verify = 0;
  my %verifycn_ctx = ();
  my ($clientcert, $clientkey, $passwdcb);

  if (exists $arg->{verify}) {
      my $v = lc $arg->{verify};
      $verify = 0 + (exists $ssl_verify{$v} ? $ssl_verify{$v} : $verify);

      if ($verify) {
        $verifycn_ctx{SSL_verifycn_scheme} = 'ldap';
        $verifycn_ctx{SSL_verifycn_name} = $arg->{sslserver}
          if (defined $arg->{sslserver});
      }
  }

  if (exists $arg->{clientcert}) {
      $clientcert = $arg->{clientcert};
      if (exists $arg->{clientkey}) {
	  $clientkey = $arg->{clientkey};
      } else {
	  require Carp;
	  Carp::croak('Setting client public key but not client private key');
      }
  }

  if ($arg->{checkcrl} && !$arg->{capath}) {
      require Carp;
      Carp::croak('Cannot check CRL without having CA certificates');
  }

  if (exists $arg->{keydecrypt}) {
      $passwdcb = $arg->{keydecrypt};
  }



( run in 1.188 second using v1.01-cache-2.11-cpan-98e64b0badf )