#============================================================================# # vHost - one-step solution for all virtual hosting needs # # V40mysql - mysql virtualization module # # # # Copyright(c) Chaogic Systems, LLC. http://chaogic.com # # Author: Jake Fan # # # # This is Free Software; permission to use, copy, modify, and distribute # # this software and its documentation for any purpose - with or without fee # # - is hereby granted, provided that the above copyright information and # # this permission notice appear in all copies and documentations. This # # software is provided "as is" without express or implied warranty. For # # more details, see GNU General Public License as published by the Free # # Software Foundation. # # # #============================================================================# $X eq "configuration" && do { ################################################ ### EDITABLE CONFIGURATIONS ################################################## ### mysql database directory name on virtual hosts. will be created under # "var/". # $mysqlDir = "mysql"; $mysqlDir = "mysql"; ### mysql database directory on the main host. when left blank, it will be # retrieved from $mysqlCf. # $mysqlRoot = ""; $mysqlRoot = ""; ### the user which mysqld runs as. when left blank, it will be retrieved from # $mysqlCf. # $mysqlUser = ""; $mysqlUser = ""; ### mysql configuration file. # $mysqlCf = "/etc/my.cnf"; $mysqlCf = "/etc/my.cnf"; ### command "mysql". # $mysql = "/usr/bin/mysql"; $mysql = "/usr/bin/mysql"; ### mysql superuser at localhost. # $mysqlSu = "superuser"; $mysqlSu = "superuser"; ### mysql superuser password at localhost. not allowed to be blank. note: # the permission attributes of this module are set to root readable only. # the password is invisible to others. # $mysqlPw = "password"; $mysqlPw = "password"; ### databases to be created for a virtual host, followed by each database's # initialization script. separate databases and scripts with white space. # vhost will replace "[HOST_NAME]" with the actual value, with "." in the # host name replaced by "_". database initialization will be done with # command "mysql database_name < script_name". use "/dev/null" as the # initialization script if a database does not actually have one. entries # with invalid or insecure databases/scripts will be silently ignored. # $mysqlC = <<"---eoc---eoc---eoc---"; $mysqlC = <<"---eoc---eoc---eoc---"; [HOST_NAME]_database /dev/null [HOST_NAME]_myforum /etc/myforum.sql [HOST_NAME]_myshop /etc/myshop.sql ---eoc---eoc---eoc--- ### DO NOT TOUCH ANYTHING BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING!! ### SanityChecking ########################################################### my $help = <<'#'; MySQL DB: vhost --addmydb host_name mydb_name [-f] vhost --delmydb host_name mydb_name [-f [-d]] # $HELP =~ s/^(\s*View Log:)/$help$1/m; if ($ARGV[0] =~ /^(addmydb|delmydb)$/ && !$ERR) { undef $HLP; $H = $ARGV[1]; $D = $ARGV[2]; $ERR = 1; $ERR = 0 if $#ARGV+1 > 2 && $#ARGV-1 < 3 && join ("\n", @ARGV) =~ /^addmydb\n[^-].*\n[^-].*(\n-[f\s-]+)?$/; $ERR = 0 if $#ARGV+1 > 2 && $#ARGV-1 < 4 && join ("\n", @ARGV) =~ /^delmydb\n[^-].*\n[^-].*(\n-[fd\s-]+)?$/; $ERR && print STDERR $HELP; $ERR && exit 2; $ERR = !CheckH ($H, 1) || $ERR if length $H; $ERR = $D !~ /\A[\w-]+\z/ && Error ("invalid mydb name '$D'") || $ERR if length $D; $ERR && exit 2; } /^\s*datadir[\s"'=]+([^\s"'=]+)/i && ($mysqlRoot ||= $1), /^\s*user[\s"'=]+([^\s"'=]+)/i && ($mysqlUser ||= $1) for !($mysqlRoot && $mysqlUser) && Cat $mysqlCf; $ERR = 1, Error "$MOD: \$mysqlDir = '$mysqlDir'" if !CheckN $mysqlDir; $ERR = 1, Error "$MOD: \$mysqlRoot = '$mysqlRoot'" if !-d $mysqlRoot; $ERR = 1, Error "$MOD: \$mysqlUser = '$mysqlUser'" if !getpwnam $mysqlUser; $ERR = 1, Error "$MOD: \$mysqlCf = '$mysqlCf'" if !-f $mysqlCf; $ERR = 1, Error "$MOD: \$mysql = '$mysql'" if $mysql !~ /^\// || !-x (split /[\s|&;]+/, $mysql)[0]; $ERR = 1, Error "$MOD: \$mysqlSu = '$mysqlSu'" if !CheckU $mysqlSu; $ERR = 1, Error "$MOD: \$mysqlPw = '$mysqlPw'" if !$mysqlPw; $mysqlH = $H, $mysqlH =~ s/\./_/g; $mysqlC =~ s/\[HOST_NAME\]/$mysqlH/g; $mydbRoot = "$VHOME/$H/var/$mysqlDir"; $EVAL{'$mysql;'} = 4; }; $X eq "initialization" && do { ############################################### Security 2 if $ARGV[0] eq "addmydb"; Security 2 if $ARGV[0] eq "delmydb"; $Db = $D; $D = $mysqlH."_$D" if length $D && $D !~ /\Q$mysqlH\E/; if ($ONCFG) { `chown 0:$GHID $MOD $NERR` if !-o $MOD; `chmod 0600 $MOD $NERR` if ((stat $MOD)[2] & 07777) != 0600; `chmod 0711 $mysqlRoot $NERR` if ((stat $mysqlRoot)[2] & 07777) != 0711; GroupAdd $mysqlUser; } if ($ARGV[0] =~ /^(addvroot|delvroot|addhost|delhost|addmydb|delmydb|passwd)$/) { my $pass = $mysqlPw; $pass =~ s/([\\\$"`])/\\$1/g; $mysqlCmd = "$mysql -u $mysqlSu -p\"$pass\""; $ERR = 1, Error ("$MOD: $mysql -u $mysqlSu -p" . "*" x length $mysqlPw), $ERR = 1, Error ("$MOD: invalid \$mysql/\$mysqlSu/\$mysqlPw") if !`(echo "show tables;" | $mysqlCmd mysql) $NERR`; $ERR && exit 1; Error5 "'$H' is not virtual" if !$QHOST{$H} && $D; sub MysqlPasswd { my $pass = $_[1]; $pass =~ s/([\\'])/\\$1/g; $pass =~ s/([\\\$"`])/\\$1/g; `(echo "GRANT USAGE ON *.* TO '$_[0]'\@localhost IDENTIFIED BY '$pass';" | $mysqlCmd) $NERR`; # `(echo "GRANT USAGE ON *.* TO '$_[0]' IDENTIFIED BY '$pass';" | $mysqlCmd) $NERR`; } sub MysqlCleanO { my $o = $_[0]; my @o = getpwnam $o; return if $o eq "root" || $o eq $mysqlSu || $o[3] == $GHID || $o[7] eq "$HOME{$USER{$o}}/home/$o"; `(echo "DELETE FROM mysql.user WHERE user='$o' AND host='localhost';" | $mysqlCmd) $NERR`; # `(echo "DELETE FROM mysql.user WHERE user='$o' AND host='%';" | $mysqlCmd) $NERR`; } sub MysqlAddDb { for (split /^/m, $_[0]) { my ($db, $ini); /^\s*([\w-]*\Q$mysqlH\E[\w-]*)\s+(\/[\/\w.-]+)\s*$/ && ($db = $1, $ini = $2, -e $ini) || next; `cp -Rp $mysqlRoot/$db/. $mydbRoot/$db $NERR`; `rm -r $mysqlRoot/$db $NERR`; `(echo "CREATE DATABASE \\\`$db\\\`;" | $mysqlCmd) $NERR`; `(echo "GRANT ALL ON \\\`$db\\\`.* TO '$O'\@localhost;" | $mysqlCmd) $NERR`; # `(echo "GRANT ALL ON \\\`$db\\\`.* TO '$O';" | $mysqlCmd) $NERR`; `$mysqlCmd $db < $ini $NERR` if !`ls $mydbRoot/$db/ $NERR`; `cp -Rp $mysqlRoot/$db/. $mydbRoot/$db $NERR`; `rm -r $mysqlRoot/$db $NERR`; `ln -s $mydbRoot/$db $mysqlRoot/$db $NERR`; } } sub MysqlDelDb { for (split /^/m, $_[0]) { my $db; /^\s*([\w-]*\Q$mysqlH\E[\w-]*)\s/ && ($db = $1) || next; `(echo "REVOKE ALL ON \\\`$db\\\`.* FROM '$O'\@localhost;" | $mysqlCmd) $NERR`; # `(echo "REVOKE ALL ON \\\`$db\\\`.* FROM '$O';" | $mysqlCmd) $NERR`; `rm -r $mysqlRoot/$db $NERR`; `rm -r $mydbRoot/$db $NERR` if $_d; } } } }; $X eq "addvroot" && do { ##################################################### MysqlPasswd $W, $PASS if defined $PASS; }; $X eq "delvroot" && do { ##################################################### MysqlCleanO $_ for $W || split /\s+/, $Ws; }; $X eq "addhost" && do { ###################################################### MysqlPasswd $O, $PASS if defined $PASS; `mkdir $mydbRoot $NERR`; MysqlAddDb $mysqlC; }; $X eq "delhost" && do { ###################################################### MysqlDelDb $mysqlC.`ls $mydbRoot/ $NERR`; }; $X eq "passwd" && do { ####################################################### MysqlPasswd $U, $PASS if ($U eq $O || $LOH && grep /^\Q$U\E$/, keys %USER) && defined $PASS; }; $X eq "addmydb" && do { ###################################################### Prompt "adding mydb '$D'"; $LOCAL = 1, Rexec "vhost --addmydb $H $Db $_f", "HOST", $HOSTs if !$LOCAL; `mkdir $mydbRoot $NERR`; MysqlAddDb "$D /dev/null\n"; }; $X eq "delmydb" && do { ###################################################### Prompt "deleting mydb '$D'"; Forced "mydb data"; my $_fd = $_d if $_f; $LOCAL = 1, Rexec "vhost --delmydb $H $Db $_f $_fd", "HOST", $HOSTs if !$LOCAL; MysqlDelDb "$D\n"; }; $X eq "finalization" && do { ################################################# if ($ARGV[0] eq "delhost" && $_d) { MysqlCleanO $O; } if ($ARGV[0] eq "addhost" || $ARGV[0] eq "addmydb") { my $muid = getpwnam $mysqlUser; `chown -Rh $O[2]:$GHID $mydbRoot $NERR`; `chcon -Rht mysqld_db_t $mydbRoot $NERR`; `chown $muid:$GUID $mydbRoot/* $NERR`; `chown $O[2]:$GUID $mydbRoot $NERR`; MysqlCleanO $OWNR{$H} if $OWNR{$H} ne $O; } }; 1;