added note about stripping comments from LDIF; bug 642
[bbaumbach/samba-autobuild/.git] / examples / LDAP / convertSambaAccount
1 #!/usr/bin/perl  -w
2 ##
3 ## Convert an LDIF file containing sambaAccount entries
4 ## to the new sambaSamAccount objectclass
5 ##
6 ## Copyright Gerald (Jerry) Carter      2003
7 ##
8 ## Usage: convertSambaAccount --sid=<Domain SID> \
9 ##       --input=<input ldif> --output=<output ldif> \
10 ##       --changetype=[modify|add]
11 ##
12 ## You can generate an input ldif file using:
13 ## $ ldapsearch -LL -x -h ldapsrv -D cn=root,dc=company,dc=com \
14 ##   -b dc=copmany,dc=com > /tmp/samba3.alpha23.ldif
15 ##
16 ## Note the "-LL" so no additional comments are generated
17 ##
18
19
20 use strict;
21 use Net::LDAP::LDIF;
22 use Getopt::Long;
23
24
25 ##############################################################################
26 ## local variables
27
28 my ( $domain, $domsid, $changetype );
29 my ( $ldif, $ldif2 );
30 my ( $entry, @objclasses, $obj );
31 my ( $is_samba_account, $is_samba_group );
32 my ( %attr_map, %group_attr_map, $key );
33 my ( @dels, $deletion, @adds, $addition );
34 my ( $result, %options );
35
36
37 ##############################################################################
38 ## Print the option usage
39
40 sub usage {
41
42         print "convertSambaAccount <options>\n";
43         print "Options:\n";
44         print "  --help         print this help message\n";
45         print "  --input        input LDIF filename\n";
46         print "  --output       output LDIF filename\n";
47         print "  --sid          domain SID\n";
48         print "  --changetype   [modify|add] (default is 'add')\n";
49 }
50
51
52 ##############################################################################
53 ##                               MAIN DRIVER                                ##
54 ##############################################################################
55
56 ##
57 ## hashes to map old attribute names to new ones 
58 ##
59
60 %attr_map = ( 
61         lmPassword      => 'sambaLMPassword',
62         ntPassword      => 'sambaNTPassword',
63         pwdLastSet      => 'sambaPwdLastSet',
64         pwdMustChange   => 'sambaPwdMustChange',
65         pwdCanChange    => 'sambaPwdCanChange',
66         homeDrive       => 'sambaHomeDrive',
67         smbHome         => 'sambaHomePath',
68         scriptPath      => 'sambaLogonScript',
69         profilePath     => 'sambaProfilePath',
70         kickoffTime     => 'sambaKickoffTime',
71         logonTime       => 'sambaLogonTime',
72         logoffTime      => 'sambaLogoffTime',
73         userWorkstations        => 'sambaUserWorkstations',
74         domain          => 'sambaDomainName',
75         acctFlags       => 'sambaAcctFlags',
76 );
77
78 %group_attr_map = (
79         ntSid           => 'sambaSID',
80         ntGroupType     => 'sambaGroupType',
81 );
82
83 ##
84 ## process command line args
85 ##
86
87 $result = GetOptions(\%options,
88                         "help", 
89                         "input=s", 
90                         "output=s", 
91                         "sid=s",
92                         "changetype=s");
93
94 if (!$result && ($#ARGV != -1)) {
95         usage();
96         exit 1;
97 }
98
99 if ( defined($options{'help'}) ) {
100         usage();
101         exit 0;
102 }
103
104
105 if ( !defined( $options{'sid'} ) ) {
106         print "You must provide a domain sid\n";
107         exit 1;
108 }
109
110 $domsid = $options{'sid'};
111
112 $changetype = 'add';
113 if ( defined( $options{'changetype'} ) ) {
114         $changetype = $options{'changetype'};
115 }
116
117 ##
118 ## open files
119 ##
120
121 $ldif = Net::LDAP::LDIF->new ($options{'input'}, "r") or die $!;
122
123 if ( "$changetype" eq "add" ) {
124         $ldif2 = Net::LDAP::LDIF->new ($options{'output'}, "w") or die $!;
125 }
126 elsif ( "$changetype" eq "modify" ) {
127         open( OUTPUT, ">$options{'output'}" ) or die $!;
128 }
129 else {
130         print "Bad changetype!\n";
131         exit 1;
132 }
133
134 ##
135 ## process LDIF 
136 ##
137
138 while ( !$ldif->eof ) {
139         undef ( $entry );
140         $entry = $ldif->read_entry();
141
142         ## skip entry if we find an error
143         if ( $ldif->error() ) {
144                 print "Error msg: ",$ldif->error(),"\n";
145                 print "Error lines:\n",$ldif->error_lines(),"\n";
146                 next;
147         }
148
149         ##
150         ## check to see if we have anything to do on this
151         ## entry.  If not just write it out
152         ##
153         @objclasses = $entry->get_value( "objectClass" );
154         undef ( $is_samba_account );
155         undef ( $is_samba_group );
156         @adds = ();
157         @dels = ();
158         foreach $obj ( @objclasses ) {
159                 if ( "$obj" eq "sambaAccount" ) {
160                         $is_samba_account = 1;
161                 } elsif ( "$obj" eq "sambaGroupMapping" ) {
162                         $is_samba_group = 1;
163                 }
164         }
165
166         if ( defined ( $is_samba_account ) ) {
167                 ##
168                 ## start editing the sambaAccount
169                 ##
170
171                 @dels = ( 'objectclass: sambaAccount', 'rid' );
172                 @adds = ('objectclass: sambaSamAccount', "sambaSID: " .  ${domsid} . "-" . ${entry}->get_value( 'rid' ) );
173                 $entry->delete( 'objectclass' => [ 'sambaAccount' ] );
174                 $entry->add( 'objectclass' => 'sambaSamAccount' );
175
176                 $entry->add( 'sambaSID' => $domsid."-".$entry->get_value( "rid" ) );
177                 $entry->delete( 'rid' );
178         
179                 if ( defined($entry->get_value( "primaryGroupID" )) ) {
180                         push @adds, "sambaPrimaryGroupSID: " . $domsid."-".$entry->get_value( "primaryGroupID" );
181                         push @dels, "primaryGroupID";
182                         $entry->add( 'sambaPrimaryGroupSID' => $domsid."-".$entry->get_value( "primaryGroupID" ) );
183                         $entry->delete( 'primaryGroupID' );
184                 }
185         
186
187                 foreach $key ( keys %attr_map ) {
188                         if ( defined($entry->get_value($key)) ) {
189                                 push @adds, "$attr_map{$key}: " . $entry->get_value($key);
190                                 push @dels, "$key";
191                                 $entry->add( $attr_map{$key} => $entry->get_value($key) );
192                                 $entry->delete( $key );
193                         }
194                 }
195         } elsif ( defined ( $is_samba_group ) ) {
196                 foreach $key ( keys %group_attr_map ) {
197                         if ( defined($entry->get_value($key)) ) {
198                                 push @adds, "$group_attr_map{$key}: " . $entry->get_value($key);
199                                 push @dels, "$key";
200                                 $entry->add( $group_attr_map{$key} => $entry->get_value($key) );
201                                 $entry->delete( $key );
202                         }
203                 }
204         }
205         
206         ## see if we should write full entries or only the changes
207         
208         if ( "$changetype" eq "add" ) {
209                 $ldif2->write_entry( $entry );
210         }
211         else {
212                 if ( defined ( $is_samba_account ) || defined ( $is_samba_group ) ){
213                         if ( @adds + @dels > 0 ) {
214                                 print OUTPUT "dn: " . $entry->dn . "\n";
215                                 foreach $addition (@adds) {
216                                         $addition =~ /(^\w+):/;
217                                         print OUTPUT "add: " . $1  . "\n";
218                                         print OUTPUT "$addition\n-\n";
219                                 }
220                                 foreach $deletion (@dels) {
221                                         if ( $deletion =~ /^(\w+):\s(.*)/ ) {
222                                                 print OUTPUT "delete: $1\n$1: $2\n-\n";
223                                         } else {
224                                                 print OUTPUT "delete: $deletion\n-\n"
225                                         }
226                                 }
227                                 print OUTPUT "\n"
228                         }
229                 }
230         }
231 }
232
233