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