From 223c0148133b09418caab5b11cce37366835b2f0 Mon Sep 17 00:00:00 2001 From: JT Smith Date: Mon, 25 Nov 2002 07:43:41 +0000 Subject: [PATCH] Added Net::LDAP to the distribution for easier installs. --- docs/credits.txt | 4 + docs/install.txt | 2 - lib/Bundle/Net/LDAP.pm | 47 + lib/Convert/ASN1.pm | 372 ++++++++ lib/Convert/ASN1.pod | 443 +++++++++ lib/Convert/ASN1/Debug.pm | 228 +++++ lib/Convert/ASN1/IO.pm | 261 ++++++ lib/Convert/ASN1/_decode.pm | 613 +++++++++++++ lib/Convert/ASN1/_encode.pm | 364 ++++++++ lib/Convert/ASN1/parser.pm | 910 +++++++++++++++++++ lib/LWP/Protocol/ldap.pm | 143 +++ lib/Net/LDAP.pm | 822 +++++++++++++++++ lib/Net/LDAP.pod | 875 ++++++++++++++++++ lib/Net/LDAP/ASN.pm | 366 ++++++++ lib/Net/LDAP/Bind.pm | 55 ++ lib/Net/LDAP/Constant.pm | 108 +++ lib/Net/LDAP/Constant.pod | 347 +++++++ lib/Net/LDAP/Control.pm | 290 ++++++ lib/Net/LDAP/Control/Paged.pm | 165 ++++ lib/Net/LDAP/Control/ProxyAuth.pm | 134 +++ lib/Net/LDAP/Control/Sort.pm | 205 +++++ lib/Net/LDAP/Control/SortResult.pm | 178 ++++ lib/Net/LDAP/Control/VLV.pm | 403 +++++++++ lib/Net/LDAP/Control/VLVResponse.pm | 198 ++++ lib/Net/LDAP/DSML.pm | 340 +++++++ lib/Net/LDAP/DSML/Parser.pm | 72 ++ lib/Net/LDAP/Entry.pm | 293 ++++++ lib/Net/LDAP/Entry.pod | 295 ++++++ lib/Net/LDAP/Examples.pod | 556 ++++++++++++ lib/Net/LDAP/Extension.pm | 34 + lib/Net/LDAP/Extra.pm | 62 ++ lib/Net/LDAP/FAQ.pod | 1198 +++++++++++++++++++++++++ lib/Net/LDAP/Filter.pm | 273 ++++++ lib/Net/LDAP/Filter.pod | 112 +++ lib/Net/LDAP/LDIF.pm | 508 +++++++++++ lib/Net/LDAP/LDIF.pod | 141 +++ lib/Net/LDAP/Message.pm | 227 +++++ lib/Net/LDAP/Message.pod | 111 +++ lib/Net/LDAP/RFC.pod | 1295 +++++++++++++++++++++++++++ lib/Net/LDAP/Reference.pod | 63 ++ lib/Net/LDAP/Schema.pm | 631 +++++++++++++ lib/Net/LDAP/Schema.pod | 265 ++++++ lib/Net/LDAP/Search.pm | 174 ++++ lib/Net/LDAP/Search.pod | 117 +++ lib/Net/LDAP/Security.pod | 197 ++++ lib/Net/LDAP/Util.pm | 346 +++++++ lib/Net/LDAPS.pm | 219 +++++ 47 files changed, 15060 insertions(+), 2 deletions(-) create mode 100644 lib/Bundle/Net/LDAP.pm create mode 100644 lib/Convert/ASN1.pm create mode 100644 lib/Convert/ASN1.pod create mode 100644 lib/Convert/ASN1/Debug.pm create mode 100644 lib/Convert/ASN1/IO.pm create mode 100644 lib/Convert/ASN1/_decode.pm create mode 100644 lib/Convert/ASN1/_encode.pm create mode 100644 lib/Convert/ASN1/parser.pm create mode 100644 lib/LWP/Protocol/ldap.pm create mode 100644 lib/Net/LDAP.pm create mode 100644 lib/Net/LDAP.pod create mode 100644 lib/Net/LDAP/ASN.pm create mode 100644 lib/Net/LDAP/Bind.pm create mode 100644 lib/Net/LDAP/Constant.pm create mode 100644 lib/Net/LDAP/Constant.pod create mode 100644 lib/Net/LDAP/Control.pm create mode 100644 lib/Net/LDAP/Control/Paged.pm create mode 100644 lib/Net/LDAP/Control/ProxyAuth.pm create mode 100644 lib/Net/LDAP/Control/Sort.pm create mode 100644 lib/Net/LDAP/Control/SortResult.pm create mode 100644 lib/Net/LDAP/Control/VLV.pm create mode 100644 lib/Net/LDAP/Control/VLVResponse.pm create mode 100755 lib/Net/LDAP/DSML.pm create mode 100644 lib/Net/LDAP/DSML/Parser.pm create mode 100644 lib/Net/LDAP/Entry.pm create mode 100644 lib/Net/LDAP/Entry.pod create mode 100644 lib/Net/LDAP/Examples.pod create mode 100644 lib/Net/LDAP/Extension.pm create mode 100644 lib/Net/LDAP/Extra.pm create mode 100644 lib/Net/LDAP/FAQ.pod create mode 100644 lib/Net/LDAP/Filter.pm create mode 100644 lib/Net/LDAP/Filter.pod create mode 100644 lib/Net/LDAP/LDIF.pm create mode 100644 lib/Net/LDAP/LDIF.pod create mode 100644 lib/Net/LDAP/Message.pm create mode 100644 lib/Net/LDAP/Message.pod create mode 100644 lib/Net/LDAP/RFC.pod create mode 100644 lib/Net/LDAP/Reference.pod create mode 100644 lib/Net/LDAP/Schema.pm create mode 100644 lib/Net/LDAP/Schema.pod create mode 100644 lib/Net/LDAP/Search.pm create mode 100644 lib/Net/LDAP/Search.pod create mode 100644 lib/Net/LDAP/Security.pod create mode 100644 lib/Net/LDAP/Util.pm create mode 100644 lib/Net/LDAPS.pm diff --git a/docs/credits.txt b/docs/credits.txt index c68763194..63e7a8544 100644 --- a/docs/credits.txt +++ b/docs/credits.txt @@ -49,6 +49,8 @@ Perl.................................Larry Wall / O'Reilly Rich Edit............................interactivetools.com +Convert::ASN1........................Graham Barr + Data::Config.........................Sébastien Aperghis-Tramoni HTML::CalendarMonthSimple............Gregor Mosheh @@ -57,6 +59,8 @@ HTML::TagFilter......................William Ross HTML::Template.......................Sam Tregar +Net::LDAP............................Graham Barr + Tie::CPHash..........................Christopher J. Madsen Tie::IxHash..........................Gurusamy Sarathy diff --git a/docs/install.txt b/docs/install.txt index 539155241..f51f546e3 100644 --- a/docs/install.txt +++ b/docs/install.txt @@ -18,10 +18,8 @@ QnD INSTALL INSTRUCTIONS: DBI DBD::mysql Digest::MD5 - Net::LDAP Date::Calc Image::Magick - HTML::Parser 3. Install Apache (with or without mod_perl) and set up your config. diff --git a/lib/Bundle/Net/LDAP.pm b/lib/Bundle/Net/LDAP.pm new file mode 100644 index 000000000..3de96d0bc --- /dev/null +++ b/lib/Bundle/Net/LDAP.pm @@ -0,0 +1,47 @@ + +package Bundle::Net::LDAP; + +$VERSION = '0.02'; + +1; + +__END__ + +=head1 NAME + +Bundle::Net::LDAP - A bundle for Net::LDAP + +=head1 SYNOPSIS + +C + +=head1 CONTENTS + +Convert::ASN1 + +Digest::MD5 + +URI + +URI::ldap + +IO::Socket::SSL + +XML::Parser + +Net::LDAP + +=head1 DESCRIPTION + +This bundle all modules that Net::LDAP depends on. + +=head1 AUTHOR + +Graham Barr + +=for html
+ +I<$Id$> + +=cut + diff --git a/lib/Convert/ASN1.pm b/lib/Convert/ASN1.pm new file mode 100644 index 000000000..a64ae835e --- /dev/null +++ b/lib/Convert/ASN1.pm @@ -0,0 +1,372 @@ +# Copyright (c) 2000-2002 Graham Barr . All rights reserved. +# This program is free software; you can redistribute it and/or +# modify it under the same terms as Perl itself. + +package Convert::ASN1; + +# $Id$ + +use 5.004; +use strict; +use vars qw($VERSION @ISA @EXPORT_OK %EXPORT_TAGS @opParts @opName $AUTOLOAD); +use Exporter; + +BEGIN { + @ISA = qw(Exporter); + $VERSION = '0.15'; + + %EXPORT_TAGS = ( + io => [qw(asn_recv asn_send asn_read asn_write asn_get asn_ready)], + + debug => [qw(asn_dump asn_hexdump)], + + const => [qw(ASN_BOOLEAN ASN_INTEGER ASN_BIT_STR ASN_OCTET_STR + ASN_NULL ASN_OBJECT_ID ASN_REAL ASN_ENUMERATED + ASN_SEQUENCE ASN_SET ASN_PRINT_STR ASN_IA5_STR + ASN_UTC_TIME ASN_GENERAL_TIME ASN_RELATIVE_OID + ASN_UNIVERSAL ASN_APPLICATION ASN_CONTEXT ASN_PRIVATE + ASN_PRIMITIVE ASN_CONSTRUCTOR ASN_LONG_LEN ASN_EXTENSION_ID ASN_BIT)], + + tag => [qw(asn_tag asn_decode_tag2 asn_decode_tag asn_encode_tag asn_decode_length asn_encode_length)] + ); + + @EXPORT_OK = map { @$_ } values %EXPORT_TAGS; + $EXPORT_TAGS{all} = \@EXPORT_OK; + + @opParts = qw( + cTAG cTYPE cVAR cLOOP cOPT cCHILD + ); + + @opName = qw( + opUNKNOWN opBOOLEAN opINTEGER opBITSTR opSTRING opNULL opOBJID opREAL + opSEQUENCE opSET opUTIME opGTIME opUTF8 opANY opCHOICE opROID + ); + + foreach my $l (\@opParts, \@opName) { + my $i = 0; + foreach my $name (@$l) { + my $j = $i++; + no strict 'refs'; + *{__PACKAGE__ . '::' . $name} = sub () { $j } + } + } +} + +sub _internal_syms { + my $pkg = caller; + no strict 'refs'; + for my $sub (@opParts,@opName,'dump_op') { + *{$pkg . '::' . $sub} = \&{__PACKAGE__ . '::' . $sub}; + } +} + +sub ASN_BOOLEAN () { 0x01 } +sub ASN_INTEGER () { 0x02 } +sub ASN_BIT_STR () { 0x03 } +sub ASN_OCTET_STR () { 0x04 } +sub ASN_NULL () { 0x05 } +sub ASN_OBJECT_ID () { 0x06 } +sub ASN_REAL () { 0x09 } +sub ASN_ENUMERATED () { 0x0A } +sub ASN_RELATIVE_OID () { 0x0D } +sub ASN_SEQUENCE () { 0x10 } +sub ASN_SET () { 0x11 } +sub ASN_PRINT_STR () { 0x13 } +sub ASN_IA5_STR () { 0x16 } +sub ASN_UTC_TIME () { 0x17 } +sub ASN_GENERAL_TIME () { 0x18 } + +sub ASN_UNIVERSAL () { 0x00 } +sub ASN_APPLICATION () { 0x40 } +sub ASN_CONTEXT () { 0x80 } +sub ASN_PRIVATE () { 0xC0 } + +sub ASN_PRIMITIVE () { 0x00 } +sub ASN_CONSTRUCTOR () { 0x20 } + +sub ASN_LONG_LEN () { 0x80 } +sub ASN_EXTENSION_ID () { 0x1F } +sub ASN_BIT () { 0x80 } + + +sub new { + my $pkg = shift; + my $self = bless {}, $pkg; + + $self->configure(@_); + $self; +} + + +sub configure { + my $self = shift; + my %opt = @_; + + for my $type (qw(encode decode)) { + if (exists $opt{$type}) { + while(my($what,$value) = each %{$opt{$type}}) { + $self->{options}{"${type}_${what}"} = $value; + } + } + } +} + + + +sub find { + my $self = shift; + my $what = shift; + return unless exists $self->{tree}{$what}; + my %new = %$self; + $new{script} = $new{tree}->{$what}; + bless \%new, ref($self); +} + + +sub prepare { + my $self = shift; + my $asn = shift; + + $self = $self->new unless ref($self); + + my $tree = Convert::ASN1::parser::parse($asn); + + unless ($tree) { + $self->{error} = $@; + return; + } + + $self->{tree} = _pack_struct($tree); + $self->{script} = (values %$tree)[0]; + $self; +} + +# In XS the will convert the tree between perl and C structs + +sub _pack_struct { $_[0] } +sub _unpack_struct { $_[0] } + +## +## Encoding +## + +sub encode { + my $self = shift; + my $stash = @_ == 1 ? shift : { @_ }; + my $buf = ''; + local $SIG{__DIE__}; + eval { _encode($self->{options}, $self->{script}, $stash, [], $buf) } + or do { $self->{error} = $@; undef } +} + + + +# Encode tag value for encoding. +# We assume that the tag has been correclty generated with asn_tag() + +sub asn_encode_tag { + $_[0] >> 8 + ? $_[0] & 0x8000 + ? $_[0] & 0x800000 + ? pack("V",$_[0]) + : substr(pack("V",$_[0]),0,3) + : pack("v", $_[0]) + : chr($_[0]); +} + + +# Encode a length. If < 0x80 then encode as a byte. Otherwise encode +# 0x80 | num_bytes followed by the bytes for the number. top end +# bytes of all zeros are not encoded + +sub asn_encode_length { + + if($_[0] >> 7) { + my $lenlen = &num_length; + + return pack("Ca*", $lenlen | 0x80, substr(pack("N",$_[0]), -$lenlen)); + } + + return pack("C", $_[0]); +} + + +## +## Decoding +## + +sub decode { + my $self = shift; + my $stash = {}; + + local $SIG{__DIE__}; + eval { _decode($self->{options}, $self->{script}, $stash, 0, length $_[0], undef, [], $_[0]); $stash } + or do { + $self->{'error'} = $@; + undef; + }; +} + + +sub asn_decode_length { + return unless length $_[0]; + + my $len = ord substr($_[0],0,1); + + if($len & 0x80) { + $len &= 0x7f or return (1,-1); + + return if $len >= length $_[0]; + + return (1+$len, unpack("N", "\0" x (4 - $len) . substr($_[0],1,$len))); + } + return (1, $len); +} + + +sub asn_decode_tag { + return unless length $_[0]; + + my $tag = ord $_[0]; + my $n = 1; + + if(($tag & 0x1f) == 0x1f) { + my $b; + do { + return if $n >= length $_[0]; + $b = ord substr($_[0],$n,1); + $tag |= $b << (8 * $n++); + } while($b & 0x80); + } + ($n, $tag); +} + + +sub asn_decode_tag2 { + return unless length $_[0]; + + my $tag = ord $_[0]; + my $num = $tag & 0x1f; + my $len = 1; + + if($num == 0x1f) { + $num = 0; + my $b; + do { + return if $len >= length $_[0]; + $b = ord substr($_[0],$len++,1); + $num = ($num << 7) + ($b & 0x7f); + } while($b & 0x80); + } + ($len, $tag, $num); +} + + +## +## Utilities +## + +# How many bytes are needed to encode a number + +sub num_length { + $_[0] >> 8 + ? $_[0] >> 16 + ? $_[0] >> 24 + ? 4 + : 3 + : 2 + : 1 +} + +# Convert from a bigint to an octet string + +sub i2osp { + my($num, $biclass) = @_; + eval "use $biclass"; + $num = $biclass->new($num); + my $neg = $num < 0 + and $num = abs($num+1); + my $base = $biclass->new(256); + my $result = ''; + while($num != 0) { + my $r = $num % $base; + $num = ($num-$r) / $base; + $result .= chr($r); + } + $result ^= chr(255) x length($result) if $neg; + return scalar reverse $result; +} + +# Convert from an octet string to a bigint + +sub os2ip { + my($os, $biclass) = @_; + eval "require $biclass"; + my $base = $biclass->new(256); + my $result = $biclass->new(0); + my $neg = ord($os) >= 0x80 + and $os ^= chr(255) x length($os); + for (unpack("C*",$os)) { + $result = ($result * $base) + $_; + } + return $neg ? ($result + 1) * -1 : $result; +} + +# Given a class and a tag, calculate an integer which when encoded +# will become the tag. This means that the class bits are always +# in the bottom byte, so are the tag bits if tag < 30. Otherwise +# the tag is in the upper 3 bytes. The upper bytes are encoded +# with bit8 representing that there is another byte. This +# means the max tag we can do is 0x1fffff + +sub asn_tag { + my($class,$value) = @_; + + die sprintf "Bad tag class 0x%x",$class + if $class & ~0xe0; + + unless ($value & ~0x1f or $value == 0x1f) { + return (($class & 0xe0) | $value); + } + + die sprintf "Tag value 0x%08x too big\n",$value + if $value & 0xffe00000; + + $class = ($class | 0x1f) & 0xff; + + my @t = ($value & 0x7f); + unshift @t, (0x80 | ($value & 0x7f)) while $value >>= 7; + unpack("V",pack("C4",$class,@t,0,0)); +} + + +BEGIN { + # When we have XS &_encode will be defined by the XS code + # so will all the subs in these required packages + unless (defined &_encode) { + require Convert::ASN1::_decode; + require Convert::ASN1::_encode; + require Convert::ASN1::IO; + } + + require Convert::ASN1::parser; +} + +sub AUTOLOAD { + require Convert::ASN1::Debug if $AUTOLOAD =~ /dump/; + goto &{$AUTOLOAD} if defined &{$AUTOLOAD}; + require Carp; + my $pkg = ref($_[0]) || ($_[0] =~ /^[\w\d]+(?:::[\w\d]+)*$/)[0]; + if ($pkg and UNIVERSAL::isa($pkg, __PACKAGE__)) { # guess it was a method call + $AUTOLOAD =~ s/.*:://; + Carp::croak(sprintf q{Can't locate object method "%s" via package "%s"},$AUTOLOAD,$pkg); + } + else { + Carp::croak(sprintf q{Undefined subroutine &%s called}, $AUTOLOAD); + } +} + +sub DESTROY {} + +sub error { $_[0]->{error} } +1; diff --git a/lib/Convert/ASN1.pod b/lib/Convert/ASN1.pod new file mode 100644 index 000000000..ff7598518 --- /dev/null +++ b/lib/Convert/ASN1.pod @@ -0,0 +1,443 @@ +=head1 NAME + + Convert::ASN1 - ASN.1 Encode/Decode library + +=head1 SYNOPSYS + + use Convert::ASN1; + + $asn = Convert::ASN1->new; + $asn->prepare(q< + + [APPLICATION 7] SEQUENCE { + int INTEGER, + str OCTET STRING + } + + >); + + $pdu = $asn->encode( int => 7, str => "string"); + + $out = $asn->decode($pdu); + print $out->{int}," ",$out->{str},"\n"; + + use Convert::ASN1 qw(:io); + + $peer = asn_recv($sock,$buffer,0); + $nbytes = asn_read($fh, $buffer); + $nbytes = asn_send($sock, $buffer, $peer); + $nbytes = asn_send($sock, $buffer); + $nbytes = asn_write($fh, $buffer); + $buffer = asn_get($fh); + $yes = asn_ready($fh) + +=head1 DESCRIPTION + +Convert::ASN1 encodes and decodes ASN.1 data structures using BER/DER +rules. + +=head1 METHODS + +=head2 new + +Contructor, creates a new object. + +=head2 error + +Returns the last error. + +=head2 configure ( OPTIONS ) + +Configure options to control how Convert::ASN1 will perform various tasks. +Options are passed as name-value pairs. + +=over 4 + +=item encode + +Reference to a hash which contains various encode options. + +=item decode + +Reference to a hash which contains various decode options. + +=item encoding + +One of 'ber', 'der', 'per'. I + +=back + +Encode options + +=over 4 + +=item real + +Which encoding to use for real's. One of 'binary', 'nr1', 'nr2', 'nr3' + +=item time + +This controls how UTCTime and GeneralizedTime elements are encoded. The default +is C. + +=over 4 + +=item utctime + +The value passed will be encoded without a zone, ie a UTC value. + +=item withzone + +The value will be encoded with a zone. By default it will be encoded +using the local time offset. The offset may be set using the C +configure option. + +=item raw + +The value passed should already be in the correct format and will be copied +into the PDU as-is. + +=back + +=item timezone + +By default UTCTime and GeneralizedTime will be encoded using the local +time offset from UTC. This will over-ride that. It is an offset from UTC +in seconds. This option can be overriden by passing a reference to a +list of two values as the time value. The list should contain the time +value and the offset from UTC in seconds. + +=item bigint + +If during encoding an value greater than 32 bits is discovered and +is not already a big integer object, then the value will first be +converted into a big integer object. This option controls the big +integer class into which the objects will be blessed. The default +is to use Math::BigInt + +=back + +Decode options + +=over 4 + +=item time + +This controls how a UTCTime or a GeneralizedTime element will be decoded. The default +is C. + +=over 4 + +=item utctime + +The value returned will be a time value as returned by the C