put categorycode also in department attribute
[virtual-ldap] / bin / ldap-rewrite.pl
index ebf25b2..9c57242 100755 (executable)
@@ -9,12 +9,46 @@ use warnings;
 
 use IO::Select;
 use IO::Socket;
+use IO::Socket::SSL;
 use warnings;
 use Data::Dump qw/dump/;
 use Convert::ASN1 qw(asn_read);
 use Net::LDAP::ASN qw(LDAPRequest LDAPResponse);
 our $VERSION = '0.2';
 use fields qw(socket target);
+use YAML qw/LoadFile/;
+
+my $config = {
+       yaml_dir => './yaml/',
+       listen => shift @ARGV || 'localhost:1389',
+       upstream_ldap => 'ldap.ffzg.hr',
+       upstream_ssl => 1,
+       overlay_prefix => 'ffzg-',
+       log_file => 'log',
+
+};
+
+my $log_fh;
+
+sub log {
+       if ( ! $log_fh ) {
+               open($log_fh, '>>', $config->{log_file}) || die "can't open ", $config->{log_file},": $!";
+               print $log_fh "# " . time;
+       }
+       $log_fh->autoflush(1);
+       print $log_fh join("\n", @_),"\n";
+}
+
+BEGIN {
+       $SIG{'__WARN__'} = sub { warn @_; main::log(@_); }
+}
+
+
+if ( ! -d $config->{yaml_dir} ) {
+       warn "DISABLE ", $config->{yaml_dir}," data overlay";
+}
+
+warn "# config = ",dump( $config );
 
 sub handle {
        my $clientsocket=shift;
@@ -46,40 +80,64 @@ sub handle {
 sub log_request {
        my $pdu=shift;
 
-       print '-' x 80,"\n";
-       print "Request ASN 1:\n";
-       Convert::ASN1::asn_hexdump(\*STDOUT,$pdu);
-       print "Request Perl:\n";
+#      print '-' x 80,"\n";
+#      print "Request ASN 1:\n";
+#      Convert::ASN1::asn_hexdump(\*STDOUT,$pdu);
+#      print "Request Perl:\n";
        my $request = $LDAPRequest->decode($pdu);
-       print dump($request);
+       warn "## request = ",dump($request);
 }
 
 sub log_response {
        my $pdu=shift;
 
-       print '-' x 80,"\n";
-       print "Response ASN 1:\n";
-       Convert::ASN1::asn_hexdump(\*STDOUT,$pdu);
-       print "Response Perl:\n";
+#      print '-' x 80,"\n";
+#      print "Response ASN 1:\n";
+#      Convert::ASN1::asn_hexdump(\*STDOUT,$pdu);
+#      print "Response Perl:\n";
        my $response = $LDAPResponse->decode($pdu);
-       print dump($response);
 
        if ( defined $response->{protocolOp}->{searchResEntry} ) {
                my $uid = $response->{protocolOp}->{searchResEntry}->{objectName};
-               warn "## SEARCH $uid";
+               warn "## objectName $uid";
+
+               my @attrs;
+
                map {
-                       if ( $_->{type} eq 'postalAddress' ) {
-                               $_->{vals} = [ 'foobar' ];
+                       if ( $_->{type} eq 'hrEduPersonUniqueNumber' ) {
+                               foreach my $val ( @{ $_->{vals} } ) {
+                                       next if $val !~ m{.+:.+};
+                                       my ( $n, $v ) = split(/\s*:\s*/, $val );
+                                       push @attrs, { type => $_->{type} . '_' . $n, vals => [ $v ] };
+                               }
                        }
                } @{ $response->{protocolOp}->{searchResEntry}->{attributes} };
 
-               push @{ $response->{protocolOp}->{searchResEntry}->{attributes} },
-                       { type => 'ffzg-datum_rodjenja', vals => [ '2009-01-01' ], }
-               ;
+               warn "# ++ attrs ",dump( @attrs );
+
+               push @{ $response->{protocolOp}->{searchResEntry}->{attributes} }, $_ foreach @attrs;
+
+               my $path = $config->{yaml_dir} . "$uid.yaml";
+               if ( -e $path ) {
+                       my $data = LoadFile($path);
+                       warn "# yaml = ",dump($data);
+
+                       foreach my $type ( keys %$data ) {
+
+                               my $vals = $data->{$type};
+
+                               push @{ $response->{protocolOp}->{searchResEntry}->{attributes} }, {
+                                       type => $config->{overlay_prefix} . $type,
+                                       vals => ref($vals) eq 'ARRAY' ? $vals : [ $vals ],
+                               };
+                       }
+               }
 
                $pdu = $LDAPResponse->encode($response);
        }
 
+       warn "## response = ", dump($response);
+
        return $pdu;
 }
 
@@ -116,15 +174,18 @@ my $listenersock = IO::Socket::INET->new(
        Listen => 5,
        Proto => 'tcp',
        Reuse => 1,
-       LocalPort => 1389
-);
-
-
-my $targetsock = new IO::Socket::INET (
-       Proto => 'tcp',
-       PeerAddr => 'ldap.ffzg.hr',
-       PeerPort => 389,
-);
+       LocalAddr => $config->{listen},
+) || die "can't open listen socket: $!";
+
+
+my $targetsock = $config->{upstream_ssl}
+       ? IO::Socket::INET->new(
+               Proto => 'tcp',
+               PeerAddr => $config->{upstream_ldap},
+               PeerPort => 389,
+       )
+       : IO::Socket::SSL->new( $config->{upstream_ldap} . ':ldaps')
+       || die "can't open upstream socket: $!";
 
 run_proxy($listenersock,$targetsock);