~linuxjedi/drizzle/trunk-bug-667053

« back to all changes in this revision

Viewing changes to scripts/mysql_secure_installation.pl.in

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/perl
 
2
# -*- cperl -*-
 
3
#
 
4
# Copyright (C) 2002 MySQL AB and Jeremy Cole
 
5
#
 
6
# This program is free software; you can redistribute it and/or modify
 
7
# it under the terms of the GNU General Public License as published by
 
8
# the Free Software Foundation; version 2 of the License.
 
9
#
 
10
# This program is distributed in the hope that it will be useful,
 
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
# GNU General Public License for more details.
 
14
#
 
15
# You should have received a copy of the GNU General Public License
 
16
# along with this program; if not, write to the Free Software
 
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 
 
19
use Fcntl;
 
20
use strict;
 
21
 
 
22
my $config  = ".my.cnf.$$";
 
23
my $command = ".mysql.$$";
 
24
my $hadpass = 0;
 
25
 
 
26
# FIXME
 
27
# trap "interrupt" 2
 
28
 
 
29
my $rootpass = "";
 
30
 
 
31
sub echo_on {
 
32
  if ($^O eq 'MSWin32') {
 
33
    ReadMode('normal');
 
34
  } else {
 
35
    system("stty echo");
 
36
  }
 
37
}
 
38
 
 
39
sub echo_off {
 
40
  if ($^O eq 'MSWin32') {
 
41
    ReadMode('noecho');
 
42
  } else {
 
43
    system("stty -echo");
 
44
  }
 
45
}
 
46
 
 
47
sub write_file {
 
48
  my $file = shift;
 
49
  -f $file or die "ERROR: file is missing \"$file\": $!";
 
50
  open(FILE, ">$file") or die "ERROR: can't write to file \"$file\": $!";
 
51
  foreach my $line ( @_ ) {
 
52
    print FILE $line, "\n";             # Add EOL char
 
53
  }
 
54
  close FILE;
 
55
}
 
56
 
 
57
sub prepare {
 
58
  foreach my $file ( $config, $command ) {
 
59
    next if -f $file;                   # Already exists
 
60
    local *FILE;
 
61
    sysopen(FILE, $file, O_CREAT, 0600)
 
62
      or die "ERROR: can't create $file: $!";
 
63
    close FILE;
 
64
  }
 
65
}
 
66
 
 
67
sub do_query {
 
68
  my $query   = shift;
 
69
  write_file($command, $query);
 
70
  system("mysql --defaults-file=$config < $command");
 
71
  return $?;
 
72
}
 
73
 
 
74
sub make_config {
 
75
  my $password = shift;
 
76
 
 
77
  write_file($config,
 
78
             "# mysql_secure_installation config file",
 
79
             "[mysql]",
 
80
             "user=root",
 
81
             "password=$rootpass");
 
82
}
 
83
 
 
84
sub get_root_password {
 
85
  my $status = 1;
 
86
  while ( $status == 1 ) {
 
87
    echo_off();
 
88
    print "Enter current password for root (enter for none): ";
 
89
    my $password = <STDIN>;
 
90
    echo_on();
 
91
    if ( $password ) {
 
92
      $hadpass = 1;
 
93
    } else {
 
94
      $hadpass = 0;
 
95
    }
 
96
    $rootpass = $password;
 
97
    make_config($rootpass);
 
98
    do_query("");
 
99
    $status = $?;
 
100
  }
 
101
  print "OK, successfully used password, moving on...\n\n";
 
102
}
 
103
 
 
104
sub set_root_password {
 
105
  echo_off();
 
106
  print "New password: ";
 
107
  my $password1 = <STDIN>;
 
108
  print "\nRe-enter new password: ";
 
109
  my $password2 = <STDIN>;
 
110
  print "\n";
 
111
  echo_on();
 
112
 
 
113
  if ( $password1 eq $password2 ) {
 
114
    print "Sorry, passwords do not match.\n\n";
 
115
    return 1;
 
116
  }
 
117
 
 
118
  if ( !$password1 ) {
 
119
    print "Sorry, you can't use an empty password here.\n\n";
 
120
    return 1;
 
121
  }
 
122
 
 
123
  do_query("UPDATE mysql.user SET Password=PASSWORD('$password1') WHERE User='root';");
 
124
  if ( $? == 0 ) {
 
125
    print "Password updated successfully!\n";
 
126
    print "Reloading privilege tables..\n";
 
127
    if ( !reload_privilege_tables() ) {
 
128
      exit 1;
 
129
    }
 
130
    print "\n";
 
131
    $rootpass = $password1;
 
132
    make_config($rootpass);
 
133
  } else {
 
134
    print "Password update failed!\n";
 
135
    exit 1;
 
136
  }
 
137
 
 
138
  return 0;
 
139
}
 
140
 
 
141
sub remove_anonymous_users {
 
142
  do_query("DELETE FROM mysql.user WHERE User='';");
 
143
  if ( $? == 0 ) {
 
144
    print " ... Success!\n";
 
145
  } else {
 
146
    print " ... Failed!\n";
 
147
    exit 1;
 
148
  }
 
149
 
 
150
  return 0;
 
151
}
 
152
 
 
153
sub remove_remote_root {
 
154
  do_query("DELETE FROM mysql.user WHERE User='root' AND Host!='localhost';");
 
155
  if ( $? == 0 ) {
 
156
    print " ... Success!\n";
 
157
  } else {
 
158
    print " ... Failed!\n";
 
159
  }
 
160
}
 
161
 
 
162
sub remove_test_database {
 
163
  print " - Dropping test database...\n";
 
164
  do_query("DROP DATABASE test;");
 
165
  if ( $? == 0 ) {
 
166
    print " ... Success!\n";
 
167
  } else {
 
168
    print " ... Failed!  Not critical, keep moving...\n";
 
169
  }
 
170
 
 
171
  print " - Removing privileges on test database...\n";
 
172
  do_query("DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'");
 
173
  if ( $? == 0 ) {
 
174
    print " ... Success!\n";
 
175
  } else {
 
176
    print " ... Failed!  Not critical, keep moving...\n";
 
177
  }
 
178
 
 
179
  return 0;
 
180
}
 
181
 
 
182
sub reload_privilege_tables {
 
183
  do_query("FLUSH PRIVILEGES;");
 
184
  if ( $? == 0 ) {
 
185
    print " ... Success!\n";
 
186
    return 0;
 
187
  } else {
 
188
    print " ... Failed!\n";
 
189
    return 1;
 
190
  }
 
191
}
 
192
 
 
193
sub interrupt {
 
194
  print "\nAborting!\n\n";
 
195
  cleanup();
 
196
  echo_on();
 
197
  exit 1;
 
198
}
 
199
 
 
200
sub cleanup {
 
201
  print "Cleaning up...\n";
 
202
  unlink($config,$command);
 
203
}
 
204
 
 
205
 
 
206
# The actual script starts here
 
207
 
 
208
prepare();
 
209
 
 
210
print <<HERE;
 
211
 
 
212
 
 
213
 
 
214
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL
 
215
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!
 
216
 
 
217
In order to log into MySQL to secure it, we'll need the current
 
218
password for the root user.  If you've just installed MySQL, and
 
219
you haven't set the root password yet, the password will be blank,
 
220
so you should just press enter here.
 
221
 
 
222
HERE
 
223
 
 
224
get_root_password();
 
225
 
 
226
 
 
227
#
 
228
# Set the root password
 
229
#
 
230
 
 
231
print "Setting the root password ensures that nobody can log into the MySQL\n";
 
232
print "root user without the proper authorisation.\n\n";
 
233
 
 
234
if ( $hadpass == 0 ) {
 
235
  print "Set root password? [Y/n] ";
 
236
} else {
 
237
  print "You already have a root password set, so you can safely answer 'n'.\n\n";
 
238
  print "Change the root password? [Y/n] ";
 
239
}
 
240
 
 
241
my $reply = <STDIN>;
 
242
if ( $reply =~ /n/i ) {
 
243
  print " ... skipping.\n";
 
244
} else {
 
245
  my $status = 1;
 
246
  while ( $status == 1 ) {
 
247
    set_root_password();
 
248
    $status = $?;
 
249
  }
 
250
}
 
251
print "\n";
 
252
 
 
253
 
 
254
#
 
255
# Remove anonymous users
 
256
#
 
257
 
 
258
print <<HERE;
 
259
By default, a MySQL installation has an anonymous user, allowing anyone
 
260
to log into MySQL without having to have a user account created for
 
261
them.  This is intended only for testing, and to make the installation
 
262
go a bit smoother.  You should remove them before moving into a
 
263
production environment.
 
264
 
 
265
HERE
 
266
 
 
267
print "Remove anonymous users? [Y/n] ";
 
268
$reply = <STDIN>;
 
269
if ( $reply =~ /n/i ) {
 
270
  print " ... skipping.\n";
 
271
} else {
 
272
  remove_anonymous_users();
 
273
}
 
274
print "\n";
 
275
 
 
276
 
 
277
#
 
278
# Disallow remote root login
 
279
#
 
280
 
 
281
print <<HERE;
 
282
Normally, root should only be allowed to connect from 'localhost'.  This
 
283
ensures that someone cannot guess at the root password from the network.
 
284
 
 
285
HERE
 
286
 
 
287
print "Disallow root login remotely? [Y/n] ";
 
288
$reply = <STDIN>;
 
289
if ( $reply =~ /n/i ) {
 
290
  print " ... skipping.\n";
 
291
} else {
 
292
  remove_remote_root();
 
293
}
 
294
print "\n";
 
295
 
 
296
 
 
297
#
 
298
# Remove test database
 
299
#
 
300
 
 
301
print <<HERE;
 
302
By default, MySQL comes with a database named 'test' that anyone can
 
303
access.  This is also intended only for testing, and should be removed
 
304
before moving into a production environment.
 
305
 
 
306
HERE
 
307
 
 
308
print "Remove test database and access to it? [Y/n] ";
 
309
$reply = <STDIN>;
 
310
if ( $reply =~ /n/i ) {
 
311
  print " ... skipping.\n";
 
312
} else {
 
313
  remove_test_database();
 
314
}
 
315
print "\n";
 
316
 
 
317
 
 
318
#
 
319
# Reload privilege tables
 
320
#
 
321
 
 
322
print <<HERE;
 
323
Reloading the privilege tables will ensure that all changes made so far
 
324
will take effect immediately.
 
325
 
 
326
HERE
 
327
 
 
328
print "Reload privilege tables now? [Y/n] ";
 
329
$reply = <STDIN>;
 
330
if ( $reply =~ /n/i ) {
 
331
  print " ... skipping.\n";
 
332
} else {
 
333
  reload_privilege_tables();
 
334
}
 
335
print "\n";
 
336
 
 
337
cleanup();
 
338
 
 
339
print <<HERE;
 
340
 
 
341
 
 
342
 
 
343
All done!  If you've completed all of the above steps, your MySQL
 
344
installation should now be secure.
 
345
 
 
346
Thanks for using MySQL!
 
347
 
 
348
 
 
349
HERE
 
350
 
 
351
 
 
352