[hacking] Add Klammerw├╝sten validation tool.
[misc_tools.git] / LDAP / dump-ldap.pl
1 #!/usr/bin/perl -w
2 #
3 # dump-ldap.pl
4 #
5 # This tool dumps an LDAP database into a directory on your hard disk.
6 # Every LDAP object will become an ldif file, every (sub)tree will become
7 # a directory.
8 #
9 #  This program is free software; you can redistribute it and/or modify
10 #  it under the terms of the GNU General Public License as published by
11 #  the Free Software Foundation; either version 2, or (at your option)
12 #  any later version.
13 #
14 #  This program is distributed in the hope that it will be useful,
15 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 #  GNU General Public License for more details.
18 #
19 #
20 # Maximilian Wilhelm <max@rfc2324.org>
21 #  -- Fri, 18 Feb 2005 17:11:14 +0100
22 #
23
24 use strict;
25 use Net::LDAP;
26 use Net::LDAP::Entry;
27 use Net::LDAP::Util qw( ldap_error_name ldap_error_text );
28 use Net::LDAP::LDIF;
29 use File::Path;
30
31 END {ldap_disconnect()}
32
33 ##
34 # Configuration
35 my %ldap;
36  $ldap{server} = "localhost";                                   # LDAP-Server
37  $ldap{basedn} = "";                                            # LDAP Base-DN
38  $ldap{admindn} = "";                                           # LDAP bind DN (if required)
39  $ldap{adminpw} = "";                                           # password for ldap bind (if required)
40  $ldap{conn} = undef;                                           # Space for LDAP conn-ID
41  $ldap{filter} = "";                                            # basic search filter
42
43 # Specify the directory to which the LDAP database will be dumped
44 my $ldif_base_dir = ".";
45
46
47 ### End Configuration ###
48
49 ##
50 # Connect to the LDAP server
51
52 sub ldap_connect()
53 {
54         $ldap{conn} = Net::LDAP->new($ldap{server} )
55                 or die "Unable to connect to server \"$ldap{server}\": $! ";
56 }
57
58
59 ##
60 # Bind to the LDAP
61 sub ldap_bind
62 {
63         my $result = $ldap{conn}->bind( $ldap{admindn}, password => $ldap{adminpw} );
64
65         if ( $result->code ) {
66                 print( "Could not bind to ldap server! "
67                 . ldap_error_name( $result->code ) . ": "
68                 . ldap_error_text( $result->code ) . "\n" );
69         }
70 }
71
72
73 ##
74 # Close LDAP Connection
75 #
76 sub ldap_disconnect()
77 {
78         if ( $ldap{conn} ) {
79                 $ldap{conn}->unbind();
80         }
81 }
82
83
84 ##
85 # search_one
86 #
87 # Find subtrees / entries
88 sub search_one
89 {
90         my $base = shift;
91         my $result;
92
93         if ( $base ) {
94                 $result = $ldap{conn}->search( base => "$base",
95                         filter => "(objectClass=*)",
96                         scope => 'one',
97                         attrs => "[dn]");
98         }
99
100         if ( $result->count != 0 ) {
101                 foreach my $entry ( $result->all_entries ) {
102                         my $dn = $entry->dn;
103
104                         get_values( $entry );
105
106                         if ( has_children( $dn ) ) {
107                                 search_one( $dn );
108                         }
109                 }
110         }
111 }
112
113
114 ##
115 # get_values
116 #
117 # Save the object at the given $dn into a file
118 sub get_values()
119 {
120         my $entry = shift;
121
122         if ( $entry ) {
123                 my $dn = $entry->dn;
124
125                 my @dnArr = split(/,/, $dn);
126                 my $dnPath = "$ldif_base_dir";
127
128                 # Get the *directory* path
129                 for ( my $n = scalar(@dnArr)-1; $n > 0; $n-- ) {
130                         $dnPath .= "/$dnArr[$n]";
131                 }
132
133                 # Check if the directory we will be writing to, does exist
134                 # and create if not there.
135                 if ( ! -d "$dnPath") {
136                         mkpath( ["$dnPath"] ) or die "Cannot create directory $dnPath\n";
137                 }
138
139                 # Add last element (becomes file name) and add .ldif
140                 $dnPath = $dnPath . "/$dnArr[0].ldif";
141
142                 print "Writing: $dnPath\n";
143                 my $ldif = Net::LDAP::LDIF->new( "$dnPath" ,"w" ) or die "Cannot open $dnPath\n";
144                 $ldif->write_entry( $entry );
145                 $ldif->done();
146
147 #               Net::LDAP::LDIF->new( \*STDOUT,"w" )->write( $entry );
148         }
149 }
150
151
152 ##
153 # has_children
154 #
155 # Check if entry has children (true) or is a leaf (false)
156 sub has_children()
157 {
158         my $dn = shift;
159
160         if ( $dn ) {
161                 my $entry = $ldap{conn}->search(  base   => "$dn",
162                         filter => "(objectClass=*)",
163                         scope => 'one',
164                         attrs => "[dn]");
165
166                 return ( $entry->count > 0 );
167         }
168
169         warn "has_children => This should never happen";
170
171         return 0;
172 }
173
174 ##
175 # Check for server and basedn
176 if ( ! $ldap{server} ) {
177         print STDERR "Error: No LDAP server specified!\n";
178         exit 1;
179 }
180
181 if ( ! $ldap{basedn} ) {
182         print STDERR "Error: No LDAP Base DN specified!\n";
183         exit 1;
184 }
185
186 ##
187 # Let the show begin
188 ldap_connect();
189
190 ldap_bind() if ( $ldap{admin_dn} );
191
192 search_one $ldap{basedn};