This commit was manufactured by cvs2svn to create tag
[Samba.git] / source / script / mysql_convert.pl
blob1479ce62b7804e3eaae2d4fd4d0f54df24f7ad31
1 #!/bin/env perl
3 # MYSQL Convert - Creates and initialises mysql tables for use by samba
5 # Copyright (C) Benjamin Kuit 1999,
6 # Copyright (C) Andrew Tridgell 1992-1999,
7 # Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
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 of the License, or
12 # (at your option) any later version.
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.
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write to the Free Software
21 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 # Converts smbpasswd files into MySQL tables.
25 # Can understand Samba 1.19 and Samba 2.0 file formats.
26 # Assumes table structure:
27 # unix_name char(20) not null,
28 # unix_uid int(10) unsigned not null,
29 # nt_name char(20) not null,
30 # user_rid int(10) unsigned not null,
31 # smb_passwd char(32),
32 # smb_nt_passwd char(32),
33 # acct_ctrl int(10) unsigned not null,
34 # pass_last_set_time int(10) unsigned not null,
35 # unique (unix_name),
36 # unique (unix_uid)
37 # When given the --create option, mysql_convert will generate this
38 # statement.
40 # To move from flat file smbpasswd directly into a mysql table:
42 # mysql_convert.pl --db=samba --table=smbpasswd --user=samba --create --infile=smbpasswd
44 # Assumes mysql server on localhost, use --host if otherwise.
45 # To convert back to flat file:
47 # mysql_convert.pl --db=samba --table=smbpasswd --user=samba --outfile=smbpasswd
49 # If smbpasswd file already exists, use --file=append or --file=trash
50 # to determine whether to append or over-right the file.
52 # In converting from NT Server PDC to Samba PDC:
53 # Run pwdump on NT Server to generate an smbpasswd file (Samba 1.19 format),
54 # called say NTpasslist.
55 # then:
57 # mysql_convert.pl --db=samba --table=smbpasswd --user=samba --infile=NTpasslist --create --check
59 # The --check option will change the unix_uid field to the real uid
60 # value of respective users, also filter out users that dont exist on
61 # the system.
63 # If dont have mysql perl module:
65 # mysql_convert.pl --table=smbpasswd --infile=NTpasslist --outfile=mysql.txt
67 # Then use the mysql client:
69 # mysql -u samba < mysql.txt
72 $ACB_DISABLED=0x0001;
73 $ACB_HOMDIRREQ=0x0002;
74 $ACB_PWNOTREQ=0x0004;
75 $ACB_TEMPDUP=0x0008;
76 $ACB_NORMAL=0x0010;
77 $ACB_MNS=0x0020;
78 $ACB_DOMTRUST=0x0040;
79 $ACB_WSTRUST=0x0080;
80 $ACB_SVRTRUST=0x0100;
81 $ACB_PWNOEXP=0x0200;
82 $ACB_AUTOLOCK=0x0400;
84 sub getoptionval {
85 my ($option) = @_;
87 my ($value) = ($option =~ /^[^=]+=\s*(\S.*\S)\s*$/ );
89 return $value;
92 sub usage {
94 print <<EOUSAGE;
95 $0 [options]
96 options:
97 --infile=<filename> # smbpasswd style file to read entries from
98 --outfile=<filename> # file to dump results to, format depending
99 # on --infile:
100 # With --infile: Dump mysql script queries
101 # Without --infile: Dump smbpasswd format
102 # from reading mysql database
103 --host=<hostname> # Mysql Server name (default: localhost)
104 --db=<database> # Mysql Database name
105 --user=<user> # Mysql User
106 --password[=<password>] # Mysql password for --user
107 --table=<table> # Mysql table
108 --create # Generate 'create table' query
109 --file=[trash|append] # Action to take if --outfile file exists
110 --check # Do not alter or skip bad uids
112 EOUSAGE
113 exit 0;
116 sub getpass {
117 my($prompt)=@_;
118 my($ret);
120 print $prompt;
121 system "stty -echo";
122 chomp($ret=<STDIN>);
123 system "stty echo";
124 print "\n";
125 $ret;
128 sub next_entry {
129 my ($name,$uid,$lm,$nt,$f,$lct) = ();
131 $name="";
132 if ( not $infile ) {
133 ($name,$uid,$lm,$nt,$f,$lct) = $mysqlquery->fetchrow();
135 else {
136 my $line=<INFILE>;
138 return () if ( not $line );
140 chomp($line);
142 next if ( $line !~ /^[^: ]+:\d+:/ );
144 ($name,$uid,$lm,$nt,$f,$lct) = split(/:/,$line);
146 if ( $lct =~ /^LCT-/ ) {
147 # New Format smbpasswd file
148 my $flags=0;
150 $flags |= $ACB_PWNOTREQ if ( $f =~ /N/ );
151 $flags |= $ACB_DISABLED if ( $f =~ /D/ );
152 $flags |= $ACB_HOMDIRREQ if ( $f =~ /H/ );
153 $flags |= $ACB_TEMPDUP if ( $f =~ /T/ );
154 $flags |= $ACB_NORMAL if ( $f =~ /U/ );
155 $flags |= $ACB_MNS if ( $f =~ /M/ );
156 $flags |= $ACB_WSTRUST if ( $f =~ /W/ );
157 $flags |= $ACB_SVRTRUST if ( $f =~ /S/ );
158 $flags |= $ACB_AUTOLOCK if ( $f =~ /L/ );
159 $flags |= $ACB_PWNOEXP if ( $f =~ /X/ );
160 $flags |= $ACB_DOMTRUST if ( $f =~ /I/ );
162 $f = $flags;
164 $f = $ACB_NORMAL if ( not $f );
166 $lct =~ s/LCT-//;
167 $lct = (unpack("L",pack("H8",$lct)))[0];
169 else {
170 # Old Format smbpasswd file
171 $f = 0;
172 $lct = time();
173 if ( $lm =~ /^NO PASS/ ) {
174 $f |= $ACB_PWNOTREQ;
175 $lm = "";
176 $nt = "";
178 elsif ( $lm =~ /^XX/ ) {
179 $f |= $ACB_DISABLED;
181 $lm = "";
182 $nt = "";
185 if ( $name =~ /\$$/ ) {
186 $f |= $ACB_WSTRUST;
189 $f = $ACB_NORMAL if ( not $f );
192 return () if ( not $name );
193 ($name,$uid,$lm,$nt,$f,$lct);
196 sub do_query {
197 my ( $query ) = @_;
199 chomp($query);
200 if ( $outfile ) {
201 print OUTFILE "$query;\n";
203 else {
204 if ( not $mysqldb->query($query) ) {
205 print "$query: $Mysql::db_errstr\n";
210 sub do_file {
211 my ($file,$name,$uid,$lm,$nt,$f,$lct)=@_;
213 my $strings = "";
215 $strings .= "N" if ( $f & $ACB_PWNOTREQ );
216 $strings .= "D" if ( $f & $ACB_DISABLED );
217 $strings .= "H" if ( $f & $ACB_HOMDIRREQ );
218 $strings .= "T" if ( $f & $ACB_TEMPDUP );
219 $strings .= "U" if ( $f & $ACB_NORMAL );
220 $strings .= "M" if ( $f & $ACB_MNS );
221 $strings .= "W" if ( $f & $ACB_WSTRUST );
222 $strings .= "S" if ( $f & $ACB_SVRTRUST );
223 $strings .= "L" if ( $f & $ACB_AUTOLOCK );
224 $strings .= "X" if ( $f & $ACB_PWNOEXP );
225 $strings .= "I" if ( $f & $ACB_DOMTRUST );
227 $f = sprintf( "[%-11s]", $strings );
229 $lct=uc("LCT-".(unpack("H8",pack("L","$lct")))[0]);
231 $lm = "X"x32 if ( not $lm );
232 $nt = "X"x32 if ( not $nt );
234 print $file "$name:$uid:$lm:$nt:$f:$lct\n";
237 $dbhost = "localhost";
239 for $option ( @ARGV ) {
240 if ( $option =~ /--outfile=/ ) {
241 $outfile = getoptionval($option);
243 elsif ( $option =~ /--infile=/ ) {
244 $infile = getoptionval($option);
246 elsif ( $option =~ /--db=/ ) {
247 $dbname = getoptionval($option);
249 elsif ( $option =~ /--user=/ ) {
250 $dbuser = getoptionval($option);
252 elsif ( $option =~ /--host=/ ) {
253 $dbhost = getoptionval($option);
255 elsif ( $option =~ /--password/ ) {
256 $dbpasswd = getoptionval($option);
257 $need_password = "yes"
259 elsif ( $option =~ /--table=/ ) {
260 $dbtable = getoptionval($option);
262 elsif ( $option =~ /--create/ ) {
263 $create_table = "yes";
265 elsif ( $option =~ /--file=/ ) {
266 $file_action = getoptionval($option);
268 elsif ( $option =~ /--check/ ) {
269 $check = "yes";
271 else {
272 print "Unknown option: $option\n";
273 $unknown = "yes";
277 &usage if ( $unknown eq "yes" );
279 if ( ( not $infile ) && ( not $outfile ) && ( $create_table ne "yes" ) ) {
280 print "Need file to read from or write to\n";
281 &usage;
283 elsif ( $infile && $outfile ) {
284 if ( not $dbtable ) {
285 print "Need --table to create queries\n";
286 exit 1;
289 # Reading a smbpasswd file, dumping queries into an file which
290 # can be used for a mysql script
291 # --db* options are ignored.
293 $ignored = "";
294 $ignored .= " --db" if ( $dbname );
295 $ignored .= " --user" if ( $dbuser );
296 $ignored .= " --password" if ( $dbuser );
298 if ( $ignored ) {
299 print "Ignoring options: $ignored\n";
302 elsif ( (not $dbname) || (not $dbtable) || (not $dbuser) ) {
303 print "Missing database particulars:\n";
304 print " --db=??\n" if ( not $dbname );
305 print " --user=??\n" if ( not $dbuser );
306 print " --table=??\n" if ( not $dbtable );
307 &usage;
309 else {
310 use Mysql;
312 if ( ($need_password eq "yes") && ( not $dbpasswd )) {
313 $dbpasswd = getpass("Enter MySQL password for $dbuser: ");
315 $mysqldb = Connect Mysql($dbhost,$dbname,$dbuser,$dbpasswd);
317 if ( not $mysqldb ) {
318 print "Cannot connect to database: $Mysql::db_errstr\n";
319 exit 1;
322 if ( $outfile ) {
323 $mysqlquery = $mysqldb->query("select unix_name,unix_uid,smb_passwd,smb_nt_passwd,acct_ctrl,pass_last_set_time from $dbtable");
325 if ( not $mysqlquery ) {
326 print "MySQL Query failed: $Mysql::db_errstr\n";
327 exit 1;
332 if ( $create_table eq "yes" ) {
333 $create_table_query=<<EOSQL;
334 create table $dbtable (
335 unix_name char(20) not null,
336 unix_uid int(10) unsigned not null,
337 nt_name char(20) not null,
338 user_rid int(10) unsigned not null,
339 smb_passwd char(32),
340 smb_nt_passwd char(32),
341 acct_ctrl int(10) unsigned not null,
342 pass_last_set_time int(10) unsigned not null,
343 unique (unix_name),
344 unique (unix_uid)
346 EOSQL
347 print "$create_table_query\n";
349 if ( $infile ) {
350 if ( not open(INFILE,$infile) ) {
351 print "$infile: $!\n";
352 exit 1;
356 if ( $outfile ) {
357 if ( ! -f $outfile ) {
358 $open_string=">$outfile";
360 elsif ( not $file_action ) {
361 print "File $outfile exists:\n";
362 print "Please use --file=[trash|append] option to determine destiny of file\n";
363 exit 1;
365 elsif ( $file_action eq "append" ) {
366 $open_string = ">>$outfile";
368 else {
369 $open_string = ">$outfile";
372 if ( not open(OUTFILE,$open_string) ) {
373 print "$outfile: $!\n";
374 exit 1;
378 do_query($create_table_query) if ( $create_table_query );
380 $linenum=1;
381 while (($name,$uid,$lm,$nt,$f,$lct)=next_entry()) {
383 $| = 1;
384 print "\r$linenum ";
385 $linenum++;
387 $nuid = "";
389 $nuid = (getpwnam(lc($name)))[2];
391 if ( $check ) {
392 if ( not $nuid ) {
393 # print "Removing $name: Does not exist\n";
394 push(@removed,[$name,$uid,$lm,$nt,$f,$lct]);
395 next;
397 else {
398 # print "Changing uid of $name\n";
399 $uid = $nuid;
403 if ( $infile ) {
404 if ( $lm ) {
405 $lm = "'$lm'";
407 else {
408 $lm = "NULL";
410 if ( $nt ) {
411 $nt = "'$nt'";
413 else {
414 $nt = "NULL";
416 $rid=(4*$uid)+1000;
417 do_query("insert into $dbtable (unix_name,unix_uid,smb_passwd,smb_nt_passwd,acct_ctrl,pass_last_set_time,nt_name,user_rid) values ('$name',$uid,$lm,$nt,$f,$lct,'$name',$rid)");
419 else {
420 do_file(OUTFILE,$name,$uid,$lm,$nt,$f,$lct);
424 if ( @removed ) {
425 print "\n\nIgnored entries because usernames do not exist\n";
426 foreach $line ( @removed ) {
427 do_file(STDOUT,@{ $line });
431 close (OUTFILE) if ( $outfile );
432 close (INFILE) if ( $infile );
433 print "\n";