1#!@PERL_PATH@ 2## Emacs, this is -*- perl -*- mode? :-) 3 4# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 5# 6# This program is free software; you can redistribute it and/or 7# modify it under the terms of the GNU Library General Public 8# License as published by the Free Software Foundation; version 2 9# of the License. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14# Library General Public License for more details. 15# 16# You should have received a copy of the GNU Library General Public 17# License along with this library; if not, write to the Free 18# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 19# MA 02110-1301, USA 20 21## 22## Permission setter for MySQL 23## 24## mady by Luuk de Boer (luuk@wxs.nl) 1998. 25## it's made under GPL ...:-)) 26## 27## 28############################################################################ 29## History 30## 31## 1.0 first start of the program 32## 1.1 some changes from monty and after that 33## initial release in mysql 3.22.10 (nov 1998) 34## 1.2 begin screen now in a loop + quit is using 0 instead of 9 35## after ideas of Paul DuBois. 36## 1.2a Add Grant, References, Index and Alter privilege handling (Monty) 37## 1.3 Applied patch provided by Martin Mokrejs <mmokrejs@natur.cuni.cz> 38## (General code cleanup, use the GRANT statement instead of updating 39## the privilege tables directly, added option to revoke privileges) 40## 1.4 Remove option 6 which attempted to erroneously grant global privileges 41 42#### TODO 43# 44# empty ... suggestions ... mail them to me ... 45 46 47$version="1.4"; 48 49use DBI; 50use Getopt::Long; 51use strict; 52use vars qw($dbh $sth $hostname $opt_user $opt_password $opt_help $opt_host 53 $opt_socket $opt_port $host $version); 54 55my $sqlhost = ""; 56my $user = ""; 57 58$dbh=$host=$opt_user= $opt_password= $opt_help= $opt_host= $opt_socket= ""; 59$opt_port=0; 60 61read_my_cnf(); # Read options from ~/.my.cnf 62 63GetOptions("user=s","password=s","help","host=s","socket=s","port=i"); 64 65usage() if ($opt_help); # the help function 66 67if ($opt_host eq '') 68{ 69 $sqlhost = "localhost"; 70} 71else 72{ 73 $sqlhost = $opt_host; 74} 75 76# ask for a password if no password is set already 77if ($opt_password eq '') 78{ 79 system "stty -echo"; 80 print "Password for user $opt_user to connect to MySQL: "; 81 $opt_password = <STDIN>; 82 chomp($opt_password); 83 system "stty echo"; 84 print "\n"; 85} 86 87 88# make the connection to MySQL 89$dbh= DBI->connect("DBI:mysql:mysql:host=$sqlhost:port=$opt_port:mysql_socket=$opt_socket",$opt_user,$opt_password, {PrintError => 0}) || 90 die("Can't make a connection to the mysql server.\n The error: $DBI::errstr"); 91 92# the start of the program 93&q1(); 94exit(0); # the end... 95 96##### 97# below all subroutines of the program 98##### 99 100### 101# the beginning of the program 102### 103sub q1 { # first question ... 104 my ($answer,$end); 105 while (! $end) { 106 print "#"x70; 107 print "\n"; 108 print "## Welcome to the permission setter $version for MySQL.\n"; 109 print "## made by Luuk de Boer\n"; 110 print "#"x70; 111 print "\n"; 112 print "What would you like to do:\n"; 113 print " 1. Set password for an existing user.\n"; 114 print " 2. Create a database + user privilege for that database\n"; 115 print " and host combination (user can only do SELECT)\n"; 116 print " 3. Create/append user privilege for an existing database\n"; 117 print " and host combination (user can only do SELECT)\n"; 118 print " 4. Create/append broader user privileges for an existing\n"; 119 print " database and host combination\n"; 120 print " (user can do SELECT,INSERT,UPDATE,DELETE)\n"; 121 print " 5. Create/append quite extended user privileges for an\n"; 122 print " existing database and host combination (user can do\n"; 123 print " SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,\n"; 124 print " LOCK TABLES,CREATE TEMPORARY TABLES)\n"; 125 print " 6. Create/append full privileges for an existing database\n"; 126 print " and host combination (user has FULL privilege)\n"; 127 print " 7. Remove all privileges for for an existing database and\n"; 128 print " host combination.\n"; 129 print " (user will have all permission fields set to N)\n"; 130 print " 0. exit this program\n"; 131 print "\nMake your choice [1,2,3,4,5,6,7,0]: "; 132 while (<STDIN>) { 133 $answer = $_; 134 chomp($answer); 135 if ($answer =~ /^[1234567]$/) { 136 if ($answer == 1) { 137 setpwd(); 138 } elsif ($answer =~ /^[234567]$/) { 139 addall($answer); 140 } else { 141 print "Sorry, something went wrong. With such option number you should not get here.\n\n"; 142 $end = 1; 143 } 144 } elsif ($answer == 0) { 145 print "We hope we can help you next time \n\n"; 146 $end = 1; 147 } else { 148 print "Your answer was $answer\n"; 149 print "and that's wrong .... Try again\n"; 150 } 151 last; 152 } 153 } 154} 155 156### 157# set a password for a user 158### 159sub setpwd 160{ 161 my ($user,$pass,$host) = ""; 162 print "\n\nSetting a (new) password for a user.\n"; 163 164 $user = user(); 165 $pass = newpass($user); 166 $host = hosts($user); 167 168 print "#"x70; 169 print "\n\n"; 170 print "That was it ... here is an overview of what you gave to me:\n"; 171 print "The username : $user\n"; 172# print "The password : $pass\n"; 173 print "The host : $host\n"; 174 print "#"x70; 175 print "\n\n"; 176 print "Are you pretty sure you would like to implement this [yes/no]: "; 177 my $no = <STDIN>; 178 chomp($no); 179 if ($no =~ /n/i) 180 { 181 print "Okay .. that was it then ... See ya\n\n"; 182 return(0); 183 } 184 else 185 { 186 print "Okay ... let's go then ...\n\n"; 187 } 188 $user = $dbh->quote($user); 189 $host = $dbh->quote($host); 190 if ($pass eq '') 191 { 192 $pass = "''"; 193 } 194 else 195 { 196 $pass = "PASSWORD(". $dbh->quote($pass) . ")"; 197 } 198 my $sth = $dbh->prepare("update user set Password=$pass where User = $user and Host = $host") || die $dbh->errstr; 199 $sth->execute || die $dbh->errstr; 200 $sth->finish; 201 print "The password is set for user $user.\n\n"; 202 203} 204 205### 206# all things which will be added are done here 207### 208sub addall { 209 my ($todo) = @_; 210 my ($answer,$good,$db,$user,$pass,$host,$priv); 211 212 if ($todo == 2) { 213 $db = newdatabase(); 214 } else { 215 $db = database(); 216 } 217 218 $user = newuser(); 219 $pass = newpass("$user"); 220 $host = newhosts(); 221 222 print "#"x70; 223 print "\n\n"; 224 print "That was it ... here is an overview of what you gave to me:\n"; 225 print "The database name : $db\n"; 226 print "The username : $user\n"; 227# print "The password : $pass\n"; 228 print "The host(s) : $host\n"; 229 print "#"x70; 230 print "\n\n"; 231 print "Are you pretty sure you would like to implement this [yes/no]: "; 232 my $no = <STDIN>; 233 chomp($no); 234 if ($no =~ /n/i) { 235 print "Okay .. that was it then ... See ya\n\n"; 236 return(0); 237 } else { 238 print "Okay ... let's go then ...\n\n"; 239 } 240 241 if ($todo == 2) { 242 # create the database 243 if ($db) { 244 my $sth = $dbh->do("CREATE DATABASE $db") || $dbh->errstr; 245 } else { 246 print STDERR "What do you want? You wanted to create new database and add new user, right?\n"; 247 die "But then specify databasename, please\n"; 248 } 249 } 250 251 if ( ( !$todo ) or not ( $todo =~ m/^[2-7]$/ ) ) { 252 print STDERR "Sorry, select option $todo isn't known inside the program .. See ya\n"; 253 quit(); 254 } 255 256 my @hosts = split(/,/,$host); 257 if (!$user) { 258 die "username not specified: $user\n"; 259 } 260 if (!$db) { 261 die "databasename is not specified nor *\n"; 262 } 263 foreach $host (@hosts) { 264 # user privileges: SELECT 265 if (($todo == 2) || ($todo == 3)) { 266 $sth = $dbh->do("GRANT SELECT ON $db.* TO \'$user\'@\'$host\' IDENTIFIED BY \'$pass\'") || die $dbh->errstr; 267 } elsif ($todo == 4) { 268 # user privileges: SELECT,INSERT,UPDATE,DELETE 269 $sth = $dbh->do("GRANT SELECT,INSERT,UPDATE,DELETE ON $db.* TO \'$user\'@\'$host\' IDENTIFIED BY \'$pass\'") || die $dbh->errstr; 270 } elsif ($todo == 5) { 271 # user privileges: SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,LOCK TABLES,CREATE TEMPORARY TABLES 272 $sth = $dbh->do("GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,LOCK TABLES,CREATE TEMPORARY TABLES ON $db.* TO \'$user\'@\'$host\' IDENTIFIED BY \'$pass\'") || die $dbh->errstr; 273 } elsif ($todo == 6) { 274 # all privileges 275 $sth = $dbh->do("GRANT ALL ON $db.* TO \'$user\'\@\'$host\' IDENTIFIED BY \'$pass\'") || die $dbh->errstr; 276 } elsif ($todo == 7) { 277 # all privileges set to N 278 $sth = $dbh->do("REVOKE ALL ON $db.* FROM \'$user\'\@\'$host\'") || die $dbh->errstr; 279 } 280 } 281 $dbh->do("FLUSH PRIVILEGES") || print STDERR "Can't flush privileges\n"; 282 print "Everything is inserted and mysql privileges have been reloaded.\n\n"; 283} 284 285### 286# ask for a new database name 287### 288sub newdatabase { 289 my ($answer,$good,$db); 290 print "\n\nWhich database would you like to add: "; 291 while (<STDIN>) { 292 $answer = $_; 293 $good = 0; 294 chomp($answer); 295 if ($answer) { 296 my $sth = $dbh->prepare("SHOW DATABASES") || die $dbh->errstr; 297 $sth->execute || die $dbh->errstr; 298 while (my @r = $sth->fetchrow_array) { 299 if ($r[0] eq $answer) { 300 print "\n\nSorry, this database name is already in use; try something else: "; 301 $good = 1; 302 } 303 } 304 } else { 305 print "You must type something ...\nTry again: "; 306 next; 307 } 308 last if ($good == 0); 309 } 310 $db = $answer; 311 print "The new database $db will be created\n"; 312 return($db); 313} 314 315### 316# select a database 317### 318sub database { 319 my ($answer,$good,$db); 320 print "\n\nWhich database from existing databases would you like to select: \n"; 321 print "You can choose from: \n"; 322 my $sth = $dbh->prepare("show databases") || die $dbh->errstr; 323 $sth->execute || die $dbh->errstr; 324 while (my @r = $sth->fetchrow_array) { 325 print " - $r[0] \n"; 326 } 327 print "Which database will it be (case sensitive). Type * for any: \n"; 328 while (<STDIN>) { 329 $answer = $_; 330 $good = 0; 331 chomp($answer); 332 if ($answer) { 333 if ($answer eq "*") { 334 print "OK, the user entry will NOT be limited to any database"; 335 return("*"); 336 } 337 my $sth = $dbh->prepare("show databases") || die $dbh->errstr; 338 $sth->execute || die $dbh->errstr; 339 while (my @r = $sth->fetchrow_array) { 340 if ($r[0] eq $answer) { 341 $good = 1; 342 $db = $r[0]; 343 last; 344 } 345 } 346 } else { 347 print "Type either database name or * meaning any databasename. That means"; 348 print " any of those above but also any which will be created in future!"; 349 print " This option gives a user chance to operate on databse mysql, which"; 350 print " contains privilege settings. That is really risky!\n"; 351 next; 352 } 353 if ($good == 1) { 354 last; 355 } else { 356 print "You must select one from the list.\nTry again: "; 357 next; 358 } 359 } 360 print "The database $db will be used.\n"; 361 return($db); 362} 363 364### 365# ask for a new username 366### 367sub newuser 368{ 369 my $user = ""; 370 my $answer = ""; 371 372 print "\nWhat username is to be created: "; 373 while(<STDIN>) 374 { 375 $answer = $_; 376 chomp($answer); 377 if ($answer) 378 { 379 $user = $answer; 380 } 381 else 382 { 383 print "You must type something ...\nTry again: "; 384 next; 385 } 386 last; 387 } 388 print "Username = $user\n"; 389 return($user); 390} 391 392### 393# ask for a user which is already in the user table 394### 395sub user 396{ 397 my ($answer,$user); 398 399 print "\nFor which user do you want to specify a password: "; 400 while(<STDIN>) 401 { 402 $answer = $_; 403 chomp($answer); 404 if ($answer) 405 { 406 my $sth = $dbh->prepare("select User from user where User = '$answer'") || die $dbh->errstr; 407 $sth->execute || die $dbh->errstr; 408 my @r = $sth->fetchrow_array; 409 if ($r[0]) 410 { 411 $user = $r[0]; 412 } 413 else 414 { 415 print "Sorry, user $answer isn't known in the user table.\nTry again: "; 416 next; 417 } 418 } 419 else 420 { 421 print "You must type something ...\nTry again: "; 422 next; 423 } 424 last; 425 } 426 print "Username = $user\n"; 427 return($user); 428} 429 430### 431# ask for a new password 432### 433sub newpass 434{ 435 my ($user) = @_; 436 my ($pass,$answer,$good,$yes); 437 438 print "Would you like to set a password for $user [y/n]: "; 439 $yes = <STDIN>; 440 chomp($yes); 441 if ($yes =~ /y/) 442 { 443 system "stty -echo"; 444 print "What password do you want to specify for $user: "; 445 while(<STDIN>) 446 { 447 $answer = $_; 448 chomp($answer); 449 system "stty echo"; 450 print "\n"; 451 if ($answer) 452 { 453 system "stty -echo"; 454 print "Type the password again: "; 455 my $second = <STDIN>; 456 chomp($second); 457 system "stty echo"; 458 print "\n"; 459 if ($answer ne $second) 460 { 461 print "Passwords aren't the same; we begin from scratch again.\n"; 462 system "stty -echo"; 463 print "Password please: "; 464 next; 465 } 466 else 467 { 468 $pass = $answer; 469 } 470 } 471 else 472 { 473 print "You must type something ...\nTry again: "; 474 next; 475 } 476 last; 477 } 478# print "The password for $user is $pass.\n"; 479 } 480 else 481 { 482 print "We won't set a password so the user doesn't have to use it\n"; 483 $pass = ""; 484 } 485 return($pass); 486} 487 488### 489# ask for new hosts 490### 491sub newhosts 492{ 493 my ($host,$answer,$good); 494 495 print "We now need to know from what host(s) the user will connect.\n"; 496 print "Keep in mind that % means 'from any host' ...\n"; 497 print "The host please: "; 498 while(<STDIN>) 499 { 500 $answer = $_; 501 chomp($answer); 502 if ($answer) 503 { 504 $host .= ",$answer"; 505 print "Would you like to add another host [yes/no]: "; 506 my $yes = <STDIN>; 507 chomp($yes); 508 if ($yes =~ /y/i) 509 { 510 print "Okay, give us the host please: "; 511 next; 512 } 513 else 514 { 515 print "Okay we keep it with this ...\n"; 516 } 517 } 518 else 519 { 520 print "You must type something ...\nTry again: "; 521 next; 522 } 523 last; 524 } 525 $host =~ s/^,//; 526 print "The following host(s) will be used: $host.\n"; 527 return($host); 528} 529 530### 531# ask for a host which is already in the user table 532### 533sub hosts 534{ 535 my ($user) = @_; 536 my ($answer,$good,$host); 537 538 print "We now need to know which host for $user we have to change.\n"; 539 print "Choose from the following hosts: \n"; 540 $user = $dbh->quote($user); 541 my $sth = $dbh->prepare("select Host,User from user where User = $user") || die $dbh->errstr; 542 $sth->execute || die $dbh->errstr; 543 while (my @r = $sth->fetchrow_array) 544 { 545 print " - $r[0] \n"; 546 } 547 print "The host please (case sensitive): "; 548 while(<STDIN>) 549 { 550 $answer = $_; 551 chomp($answer); 552 if ($answer) 553 { 554 $sth = $dbh->prepare("select Host,User from user where Host = '$answer' and User = $user") || die $dbh->errstr; 555 $sth->execute || die $dbh->errstr; 556 my @r = $sth->fetchrow_array; 557 if ($r[0]) 558 { 559 $host = $answer; 560 last; 561 } 562 else 563 { 564 print "You have to select a host from the list ...\nTry again: "; 565 next; 566 } 567 } 568 else 569 { 570 print "You have to type something ...\nTry again: "; 571 next; 572 } 573 last; 574 } 575 print "The following host will be used: $host.\n"; 576 return($host); 577} 578 579### 580# a nice quit (first disconnect and then exit 581### 582sub quit 583{ 584 $dbh->disconnect; 585 exit(0); 586} 587 588### 589# Read variables password, port and socket from .my.cnf under the client 590# or perl groups 591### 592 593sub read_my_cnf 594{ 595 open(TMP,$ENV{'HOME'} . "/.my.cnf") || return 1; 596 while (<TMP>) 597 { 598 if (/^\[(client|perl)\]/i) 599 { 600 while ((defined($_=<TMP>)) && !/^\[\w+\]/) 601 { 602 print $_; 603 if (/^host\s*=\s*(\S+)/i) 604 { 605 $opt_host = $1; 606 } 607 elsif (/^user\s*=\s*(\S+)/i) 608 { 609 $opt_user = $1; 610 } 611 elsif (/^password\s*=\s*(\S+)/i) 612 { 613 $opt_password = $1; 614 } 615 elsif (/^port\s*=\s*(\S+)/i) 616 { 617 $opt_port = $1; 618 } 619 elsif (/^socket\s*=\s*(\S+)/i) 620 { 621 $opt_socket = $1; 622 } 623 } 624 } 625 } 626 close(TMP); 627} 628 629### 630# the help text 631### 632sub usage 633{ 634 print <<EOL; 635---------------------------------------------------------------------- 636 The permission setter for MySQL. 637 version: $version 638 639 made by: Luuk de Boer <luuk\@wxs.nl> 640---------------------------------------------------------------------- 641 642The permission setter is a little program which can help you add users 643or databases or change passwords in MySQL. Keep in mind that we don't 644check permissions which already been set in MySQL. So if you can't 645connect to MySQL using the permission you just added, take a look at 646the permissions which have already been set in MySQL. 647 648The permission setter first reads your .my.cnf file in your Home 649directory if it exists. 650 651Options for the permission setter: 652 653--help : print this help message and exit. 654 655The options shown below are used for making the connection to the MySQL 656server. Keep in mind that the permissions for the user specified via 657these options must be sufficient to add users / create databases / set 658passwords. 659 660--user : is the username to connect with. 661--password : the password of the username. 662--host : the host to connect to. 663--socket : the socket to connect to. 664--port : the port number of the host to connect to. 665 666If you don't give a password and no password is set in your .my.cnf 667file, then the permission setter will ask for a password. 668 669 670EOL 671exit(0); 672} 673