1
by brian
clean slate |
1 |
#!@PERL@
|
2 |
# ****************************
|
|
3 |
package MySQLaccess;
|
|
4 |
#use strict;
|
|
5 |
use File::Temp qw(tempfile tmpnam); |
|
6 |
use Fcntl;
|
|
7 |
||
8 |
BEGIN {
|
|
9 |
# ****************************
|
|
10 |
# static information...
|
|
11 |
$VERSION = "2.06, 20 Dec 2000"; |
|
12 |
$0 =~ m%/([^/]+)$%o; |
|
13 |
$script = $1; |
|
14 |
$script = 'MySQLAccess' unless $script; |
|
15 |
$script_conf = "$script.conf"; |
|
16 |
$script_log = $ENV{'HOME'}."/$script.log"; |
|
17 |
||
18 |
# ****************************
|
|
19 |
# information on MySQL
|
|
20 |
$MYSQL = '@bindir@/mysql'; # path to mysql executable |
|
21 |
$SERVER = '3.21'; |
|
22 |
$MYSQL_OPT = ' --batch --unbuffered'; |
|
23 |
$ACCESS_DB = 'mysql'; # name of DB with grant-tables |
|
24 |
$ACCESS_H = 'host'; # |
|
25 |
$ACCESS_U = 'user'; # |
|
26 |
$ACCESS_D = 'db'; # |
|
27 |
# Add/Edit privileges
|
|
28 |
$ACCESS_H_TMP = 'host_tmp'; |
|
29 |
$ACCESS_U_TMP = 'user_tmp'; |
|
30 |
$ACCESS_D_TMP = 'db_tmp'; |
|
31 |
$ACCESS_H_BCK = 'host_backup'; |
|
32 |
$ACCESS_U_BCK = 'user_backup'; |
|
33 |
$ACCESS_D_BCK = 'db_backup'; |
|
34 |
$DIFF = '/usr/bin/diff'; |
|
35 |
$MYSQLDUMP = '@bindir@/mysqldump'; |
|
36 |
#path to mysqldump executable
|
|
37 |
||
38 |
$MYSQLADMIN= 'http://foobar.com/MySQLadmin'; |
|
39 |
#URL of CGI for manipulating
|
|
40 |
#the temporary grant-tables
|
|
41 |
}
|
|
42 |
||
43 |
END {
|
|
44 |
unlink $MYSQL_CNF if defined $MYSQL_CNF and not $DEBUG; |
|
45 |
}
|
|
46 |
||
47 |
$INFO = <<"_INFO"; |
|
48 |
-------------------------------------------------------------------------- |
|
49 |
mysqlaccess (Version $VERSION) |
|
50 |
~~~~~~~~~~~ |
|
51 |
Copyright (C) 1997,1998 Yves.Carlier\@rug.ac.be |
|
52 |
University of Ghent (RUG), Belgium |
|
53 |
Administratieve Informatieverwerking (AIV) |
|
54 |
||
55 |
report the access-privileges for a USER from a HOST to a DB
|
|
56 |
||
57 |
Many thanks go to <monty\@mysql.com> and <psmith\@BayNetworks.COM> |
|
58 |
for their suggestions, debugging and patches.
|
|
59 |
||
60 |
use `$script -?' to get more information on available options. |
|
61 |
||
62 |
From version 2.0x, $script can also be used through a WEB-browser
|
|
63 |
if it is ran as a CGI-script. (See the release-notes)
|
|
64 |
||
65 |
--------------------------------------------------------------------------
|
|
66 |
_INFO
|
|
67 |
||
68 |
$OPTIONS = <<_OPTIONS;
|
|
69 |
||
70 |
Usage: $script [host [user [db]]] OPTIONS
|
|
71 |
||
72 |
-?, --help display this helpscreen and exit
|
|
73 |
-v, --version print information on the program `$script'
|
|
74 |
||
75 |
-u, --user=# username for logging in to the db |
|
76 |
-p, --password=# validate password for user |
|
77 |
-h, --host=# name or IP-number of the host |
|
78 |
-d, --db=# name of the database |
|
79 |
||
80 |
-U, --superuser=# connect as superuser |
|
81 |
-P, --spassword=# password for superuser |
|
82 |
-H, --rhost=# remote MySQL-server to connect to |
|
83 |
--old_server connect to old MySQL-server (before v3.21) which |
|
84 |
does not yet know how to handle full where clauses. |
|
85 |
||
86 |
-b, --brief single-line tabular report |
|
87 |
-t, --table report in table-format |
|
88 |
||
89 |
--relnotes print release-notes |
|
90 |
--plan print suggestions/ideas for future releases
|
|
91 |
--howto some examples of how to run `$script' |
|
92 |
--debug=N enter debuglevel N (0..3)
|
|
93 |
||
94 |
--copy reload temporary grant-tables from original ones
|
|
95 |
--preview show differences in privileges after making
|
|
96 |
changes in (temporary) grant-tables
|
|
97 |
--commit copy grant-rules from temporary tables to grant-tables
|
|
98 |
(!don't forget to do an mysqladmin reload) |
|
99 |
--rollback undo the last changes to the grant-tables. |
|
100 |
||
101 |
Note: |
|
102 |
+ At least the user and the db must be given (even with wildcards) |
|
103 |
+ If no host is given, `localhost' is assumed |
|
104 |
+ Wilcards (*,?,%,_) are allowed for host, user and db, but be sure
|
|
105 |
to escape them from your shell!! (ie type \\* or '*') |
|
106 |
_OPTIONS
|
|
107 |
||
108 |
$RELEASE = <<'_RELEASE'; |
|
109 |
|
|
110 |
Release Notes:
|
|
111 |
-------------
|
|
112 |
0.1-beta1: internal
|
|
113 |
- first trial.
|
|
114 |
|
|
115 |
0.1-beta2: (1997-02-27)
|
|
116 |
- complete rewrite of the granting-rules, based on the documentation
|
|
117 |
found in de FAQ.
|
|
118 |
- IP-number and name for a host are equiv.
|
|
119 |
|
|
120 |
0.1-beta3: (1997-03-10)
|
|
121 |
- more information
|
|
122 |
- 'localhost' and the name/ip of the local machine are now equiv. |
|
123 |
||
124 |
0.1-beta4: (1997-03-11)
|
|
125 |
- inform the user if he has not enough priv. to read the mysql db
|
|
126 |
||
127 |
1.0-beta1: (1997-03-12)
|
|
128 |
suggestions by Monty:
|
|
129 |
- connect as superuser with superpassword.
|
|
130 |
- mysqlaccess could also notice if all tables are empty. This means
|
|
131 |
that all user have full access!
|
|
132 |
- It would be nice if one could optionally start mysqlaccess without
|
|
133 |
any options just the arguments 'user db' or 'host user db', where |
|
134 |
host is 'localhost' if one uses only two arguments. |
|
135 |
||
136 |
1.0-beta2: (1997-03-14)
|
|
137 |
- bugfix: translation to reg.expr of \_ and \%.
|
|
138 |
- bugfix: error in matching regular expression and string given
|
|
139 |
by user which resulted in
|
|
140 |
'test_123' being matched with 'test' |
|
141 |
||
142 |
1.0-beta3: (1997-03-14)
|
|
143 |
- bugfix: the user-field should not be treated as a sql-regexpr,
|
|
144 |
but as a plain string.
|
|
145 |
- bugfix: the host-table should not be used if the host isn't empty in db
|
|
146 |
or if the host isn't emty in user |
|
147 |
(Monty)
|
|
148 |
|
|
149 |
1.0-beta4: (1997-03-14)
|
|
150 |
- bugfix: in an expression "$i = $j or $k", the '=' binds tighter than the or |
|
151 |
which results in problems...
|
|
152 |
(by Monty)
|
|
153 |
- running mysqlaccess with "perl -w" gives less warnings... ;-)
|
|
154 |
||
155 |
1.0-beta5: (1997-04-04)
|
|
156 |
- bugfix: The table sorting was only being applied to the "user" table; all
|
|
157 |
the tables need to be sorted. Rewrote the sort algorithm, and
|
|
158 |
the table walk algorithm (no temp file anymore), and various
|
|
159 |
other cleanups. I believe the access calculation is 100% correct.
|
|
160 |
(by Paul D. Smith <psmith\@baynetworks.com>)
|
|
161 |
- Allow the debug level to be set on the cmd line with --debug=N.
|
|
162 |
(by Paul D. Smith <psmith\@baynetworks.com>)
|
|
163 |
- More -w cleanups; should be totally -w-clean.
|
|
164 |
(by Paul D. Smith <psmith\@baynetworks.com>)
|
|
165 |
|
|
166 |
1.1-beta1: (1997-04-xx)
|
|
167 |
1.1-beta2: (1997-04-11)
|
|
168 |
- new options:
|
|
169 |
--all_users : report access-rights for all possible users
|
|
170 |
--all_dbs : report access-rights for all possible dbs
|
|
171 |
--all_hosts : report access-rights for all possible hosts
|
|
172 |
--brief : as brief as possible, don't mention notes,warnings and rules
|
|
173 |
--password : validate password for user
|
|
174 |
- layout: long messages are wrapped on the report. |
|
175 |
- functionality: |
|
176 |
more descriptive notes and warnings |
|
177 |
wildcards (*,?) are allowed in the user,host and db options |
|
178 |
setting xxxx=* is equiv to using option --all_xxxx |
|
179 |
note: make sure you escape your wildcards, so they don't get
|
|
180 |
interpreted by the shell. use \* or '*' |
|
181 |
- bugfix: Fieldnames which should be skipped on the output can now have
|
|
182 |
a first capital letter.
|
|
183 |
- bugfix: any option with a '.' (eg ip-number) was interpreted as |
|
184 |
a wildcard-expression.
|
|
185 |
- bugfix: When no entry was found in the db-table, the default accessrights are
|
|
186 |
N, instead of the faulty Y in a previous version.
|
|
187 |
|
|
188 |
1.1-beta-3 : (1997-04-xx)
|
|
189 |
1.1-beta-4 : (1997-04-xx)
|
|
190 |
1.1-beta-5 : (1997-04-xx)
|
|
191 |
1.1 : (1997-04-28)
|
|
192 |
- new options:
|
|
193 |
--rhost : name of mysql-server to connect to
|
|
194 |
--plan : print suggestions/ideas for future releases
|
|
195 |
--relnotes : display release-notes
|
|
196 |
--howto : display examples on how to use mysqlaccess
|
|
197 |
--brief : single-line tabular output
|
|
198 |
- functionality/bugfix:
|
|
199 |
* removed options --all_users,--all_dbs,--all_hosts, which
|
|
200 |
were redundant with the wildcard-expressions for the corresponding
|
|
201 |
options. They made the processing of the commandline too painful
|
|
202 |
and confusing ;-)
|
|
203 |
(suggested by psmith)
|
|
204 |
* redefined the option --brief, which now gives a single-line
|
|
205 |
tabular output
|
|
206 |
* Now we check if the right version of the mysql-client is used,
|
|
207 |
since we might use an option not yet implemented in an
|
|
208 |
older version (--unbuffered, since 3.0.18)
|
|
209 |
Also the error-messages the mysql-client reports are
|
|
210 |
better interpreted ;-)
|
|
211 |
* Wildcards can now be given following the SQL-expression
|
|
212 |
(%,_) and the Regular-expression (*,?) syntax.
|
|
213 |
- speed: we now open a bidirectional pipe to the mysql-client, and keep
|
|
214 |
it open throughout the whole run. Queries are written to,
|
|
215 |
and the answers read from the pipe.
|
|
216 |
(suggested by monty)
|
|
217 |
- bugfixes:
|
|
218 |
* the Rules were not properly reset over iterations
|
|
219 |
* when in different tables the field-names were not identical,
|
|
220 |
eg. Select_priv and select_priv, they were considered as
|
|
221 |
definitions of 2 different access-rights.
|
|
222 |
* the IP-number of a host with a name containing wildcards should
|
|
223 |
not be searched for in Name2IP and IP2Name.
|
|
224 |
* various other small things, pointed out by <monty> and <psmith>
|
|
225 |
||
226 |
1.2 : (1997-05-13)
|
|
227 |
- bugfix:
|
|
228 |
* Fixed bug in acl with anonymous user: Now if one gets accepted by the
|
|
229 |
user table as a empty user name, the user name is set to '' when
|
|
230 |
checking against the 'db' and 'host' tables. (Bug fixed in MySQL3.20.19) |
|
231 |
||
232 |
1.2-1 : (1997-xx-xx)
|
|
233 |
- bugfix:
|
|
234 |
* hashes should be initialized with () instead of {} <psmith>
|
|
235 |
* "my" variable $name masks earlier declaration in same scope,
|
|
236 |
using perl 5.004 <????>
|
|
237 |
||
238 |
1.2-2 : (1997-06-10)
|
|
239 |
|
|
240 |
2.0p1-3 : (1997-10-xx)
|
|
241 |
- new
|
|
242 |
* packages
|
|
243 |
* log-file for debug-output : /tmp/mysqlaccess.log
|
|
244 |
* default values are read from a configuration file $script.conf
|
|
245 |
first this file is looked for in the current directory; if not
|
|
246 |
found it is looked for in /etc/
|
|
247 |
Note that when default-values are given, these can't get overriden
|
|
248 |
by empty (blanc) values! |
|
249 |
* CGI-BIN version with HTML and forms interface. Simply place the |
|
250 |
script in an ScriptAliased directory, make the configuration file |
|
251 |
available in the that directory or in /etc, and point your browser |
|
252 |
to the right URL. |
|
253 |
* copy the grant-rules to temporary tables, where you are safe to |
|
254 |
play with them. |
|
255 |
* preview changes in privileges after changing grant-rules, |
|
256 |
before taking them into production |
|
257 |
* copy the new grant-rules from the temporary tables back to the |
|
258 |
grant-tables. |
|
259 |
* Undo all changes made in the grant-tables (1-level undo). |
|
260 |
-new options: |
|
261 |
* --table : as opposite of the --brief option. |
|
262 |
* --copy : (re)load temporary grant-tables from original ones. |
|
263 |
* --preview : preview changes in privileges after changing |
|
264 |
some or more entries in the grant-tables. |
|
265 |
* --commit : copy grant-rules from temporary tables to grant-tables |
|
266 |
(!don't forget to do an mysqladmin reload) |
|
267 |
* --rollback: undo the last changes to the grant-tables.
|
|
268 |
||
269 |
- bugfix:
|
|
270 |
* if the table db is empty, mysqlaccess freezed
|
|
271 |
(by X Zhu <X.Zhu@Bradford.ac.uk>)
|
|
272 |
||
273 |
2.0 : (1997-10-09)
|
|
274 |
- fixed some "-w" warnings.
|
|
275 |
- complain when certain programs and paths can't be found.
|
|
276 |
||
277 |
2.01 : (1997-12-12) |
|
278 |
- bugfix: |
|
279 |
* rules for db-table where not calculated and reported correctly.
|
|
280 |
2.02 : (1998-01-xx) |
|
281 |
- bugfix: |
|
282 |
* Privileges of the user-table were not AND-ed properly with the |
|
283 |
other privileges. (reported by monty) |
|
284 |
- new option: |
|
285 |
* --old_server: mysqlaccess will now use a full where clause when |
|
286 |
retrieving information from the MySQL-server. If |
|
287 |
you are connecting to an old server (before v3.21) |
|
288 |
then use the option --old_server.
|
|
289 |
2.03 : (1998-02-27) |
|
290 |
- bugfix: |
|
291 |
* in Host::MatchTemplate: incorrect match if host-field was left empty.
|
|
292 |
||
293 |
2.04-alpha1 : (2000-02-11) |
|
294 |
Closes vulnerability due to former implementation requiring passwords |
|
295 |
to be passed on the command line.
|
|
296 |
- functionality |
|
297 |
Option values for --password -p -spassword -P may now be omitted from
|
|
298 |
command line, in which case the values will be prompted for. |
|
299 |
(fix supplied by Steve Harvey <sgh@vex.net>) |
|
300 |
||
301 |
2.05: (2000-02-17) Monty |
|
302 |
Moved the log file from /tmp to ~ |
|
303 |
||
304 |
2.06: Don't print '+++USING FULL WHERE CLAUSE+++' |
|
305 |
||
306 |
_RELEASE
|
|
307 |
||
308 |
$TODO = <<_TODO;
|
|
309 |
||
310 |
Plans:
|
|
311 |
-----
|
|
312 |
-a full where clause is use now. How can we handle older servers?
|
|
313 |
-add some more functionality for DNS.
|
|
314 |
-select the warnings more carefuly.
|
|
315 |
>> I think that the warnings should either be enhanced to _really_
|
|
316 |
>> understand and report real problems accurately, or restricted to
|
|
317 |
>> only printing things that it knows with 100% certainty. <psmith)
|
|
318 |
>> Why do I have both '%' and 'any_other_host' in there? Isn't that |
|
319 |
>> the same thing? I think it's because I have an actual host '%' in |
|
320 |
>> one of my tables. Probably the script should catch that and not
|
|
321 |
>> duplicate output. <psmith>
|
|
322 |
||
323 |
_TODO
|
|
324 |
||
325 |
# From the FAQ: the Grant-algorithm
|
|
326 |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
327 |
# The host table is mainly to maintain a list of "secure" servers.
|
|
328 |
# At TCX hosts contain a list of all machines on local network. These are granted
|
|
329 |
# all privileges.
|
|
330 |
# Technically the user grant is calculated by:
|
|
331 |
#
|
|
332 |
# 1.First sort all entries by host by putting host without wildcards first,
|
|
333 |
# after this host with wildcards and entries with host = ".
|
|
334 |
# Under each host sort user by the same criterias.
|
|
335 |
# 2.Get grant for user from the "db" table.
|
|
336 |
# 3.If hostname is "empty" for the found entry, AND the privileges with
|
|
337 |
# the privileges for the host in "host" table.
|
|
338 |
# (Remove all which is not "Y" in both)
|
|
339 |
# 4.OR (add) the privileges for the user from the "user" table.
|
|
340 |
# (add all privileges which is "Y" in "user")
|
|
341 |
#
|
|
342 |
# When matching, use the first found match.
|
|
343 |
#
|
|
344 |
# -----------------------------------------------------------------------------------
|
|
345 |
||
346 |
$HOWTO = <<_HOWTO;
|
|
347 |
||
348 |
Examples of how to call $script:
|
|
349 |
~~~~~~~~
|
|
350 |
1)Calling $script with 2 arguments:
|
|
351 |
||
352 |
\$ $script root mysql
|
|
353 |
->report rights of user root logged on at the local host in db mysql
|
|
354 |
||
355 |
Access-rights
|
|
356 |
for USER 'root', from HOST 'localhost', to DB 'mysql' |
|
357 |
+-----------------+---+ +-----------------+---+
|
|
358 |
| select_priv | Y | | drop_priv | Y |
|
|
359 |
| insert_priv | Y | | reload_priv | Y |
|
|
360 |
| update_priv | Y | | shutdown_priv | Y |
|
|
361 |
| delete_priv | Y | | process_priv | Y |
|
|
362 |
| create_priv | Y | | file_priv | Y |
|
|
363 |
+-----------------+---+ +-----------------+---+
|
|
364 |
BEWARE: Everybody can access your DB as user 'root' |
|
365 |
: WITHOUT supplying a password. Be very careful about it!!
|
|
366 |
||
367 |
The following rules are used:
|
|
368 |
db : 'No matching rule' |
|
369 |
host : 'Not processed: host-field is not empty in db-table.' |
|
370 |
user : 'localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y' |
|
371 |
||
372 |
2)Calling $script with 3 arguments:
|
|
373 |
||
374 |
\$ $script foo.bar nobody Foo
|
|
375 |
->report rights of user root logged in at machine foobar to db Foo
|
|
376 |
||
377 |
Access-rights
|
|
378 |
for USER 'nobody', from HOST 'foo.bar', to DB 'Foo' |
|
379 |
+-----------------+---+ +-----------------+---+
|
|
380 |
| select_priv | Y | | drop_priv | N |
|
|
381 |
| insert_priv | Y | | reload_priv | N |
|
|
382 |
| update_priv | Y | | shutdown_priv | N |
|
|
383 |
| delete_priv | Y | | process_priv | N |
|
|
384 |
| create_priv | N | | file_priv | N |
|
|
385 |
+-----------------+---+ +-----------------+---+
|
|
386 |
BEWARE: Everybody can access your DB as user 'nobody' |
|
387 |
: WITHOUT supplying a password. Be very careful about it!!
|
|
388 |
||
389 |
The following rules are used:
|
|
390 |
db : 'foo.bar','Foo','nobody','Y','Y','Y','N','N','N' |
|
391 |
host : 'Not processed: host-field is not empty in db-table.' |
|
392 |
user : 'foo.bar','nobody','','N','N','N','Y','N','N','N','N','N','N' |
|
393 |
||
394 |
3)Using wildcards:
|
|
395 |
||
396 |
\$ $script \\* nobody Foo --brief
|
|
397 |
->report access-rights of user nobody from all machines to db Foo,
|
|
398 |
and use a matrix-report.
|
|
399 |
||
400 |
Sel Ins Upd Del Crea Drop Reld Shut Proc File Host,User,DB
|
|
401 |
---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --------------------
|
|
402 |
Y Y Y Y N N N N N N localhost,nobody,Foo
|
|
403 |
N N N N N N N N N N %,nobody,Foo
|
|
404 |
N N N N N N N N N N any_other_host,nobody,Foo
|
|
405 |
||
406 |
_HOWTO
|
|
407 |
||
408 |
||
409 |
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #
|
|
410 |
# START OF THE PROGRAM #
|
|
411 |
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #
|
|
412 |
||
413 |
use Getopt::Long;
|
|
414 |
use Sys::Hostname;
|
|
415 |
use IPC::Open3;
|
|
416 |
||
417 |
||
418 |
# ****************************
|
|
419 |
# debugging flag
|
|
420 |
# can be set to 0,1,2,3
|
|
421 |
# a higher value gives more info
|
|
422 |
# ! this can also be set on the command-line
|
|
423 |
$DEBUG = 0;
|
|
424 |
||
425 |
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>8
|
|
426 |
# Normaly nothing should be changed beneeth this line
|
|
427 |
||
428 |
||
429 |
# ****************************
|
|
430 |
# no caching on STDOUT
|
|
431 |
$|=1;
|
|
432 |
||
433 |
$MYSQL_CNF = tmpnam();
|
|
434 |
%MYSQL_CNF = (client => { },
|
|
435 |
mysql => { },
|
|
436 |
mysqldump => { },
|
|
437 |
);
|
|
438 |
||
439 |
||
440 |
||
441 |
$NEW_USER = 'ANY_NEW_USER'; |
|
442 |
$NEW_DB = 'ANY_NEW_DB' ; |
|
443 |
||
444 |
||
445 |
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #
|
|
446 |
# mysqlaccess: #
|
|
447 |
# ~~~~~~~~~~~ #
|
|
448 |
# Lets get to it, #
|
|
449 |
# and start the program by processing the parameters #
|
|
450 |
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #
|
|
451 |
||
452 |
($CMD,$CGI) = GetMode();
|
|
453 |
||
454 |
# ****************************
|
|
455 |
# the copyright message should
|
|
456 |
# always be printed (once)
|
|
457 |
MySQLaccess::Report::Print_Header();
|
|
458 |
||
459 |
# *****************************
|
|
460 |
# Read configuration-file
|
|
461 |
MySQLaccess::Debug::Print(1, "Reading configuration file...");
|
|
462 |
if (-f "./$script_conf") {
|
|
463 |
require "./$script_conf";
|
|
464 |
}
|
|
465 |
elsif (-f "@sysconfdir@/$script_conf") {
|
|
466 |
require "@sysconfdir@/$script_conf";
|
|
467 |
}
|
|
468 |
elsif (-f "/etc/$script_conf") {
|
|
469 |
require "/etc/$script_conf";
|
|
470 |
}
|
|
471 |
||
472 |
# ****************************
|
|
473 |
# Read in all parameters
|
|
474 |
if ($MySQLaccess::CMD) { #command-line version
|
|
475 |
# ----------------------------
|
|
476 |
# Get options from commandline
|
|
477 |
$Getopt::Long::ignorecase=0; #case sensitive options
|
|
478 |
if ( grep(/\-\?/,@ARGV) ) { MySQLaccess::Report::Print_Usage(); exit 0; }
|
|
479 |
GetOptions("help" => \$Param{'help'} |
|
480 |
,"host|h=s" => \$Param{'host'} |
|
481 |
,"user|u=s" => \$Param{'user'} |
|
482 |
,"password|p:s" => \$Param{'password'} |
|
483 |
,"db|d=s" => \$Param{'db'} |
|
484 |
,"superuser|U=s" => \$Param{'superuser'} |
|
485 |
,"spassword|P:s" => \$Param{'spassword'} |
|
486 |
,"rhost|H=s" => \$Param{'rhost'} |
|
487 |
,"old_server" => \$Param{'old_server'} |
|
488 |
,"debug=i" => \$Param{'DEBUG'} |
|
489 |
,"brief|b" => \$Param{'brief'} |
|
490 |
,"table|t" => \$Param{'table'} |
|
491 |
,"relnotes" => \$Param{'relnotes'} |
|
492 |
,"plan" => \$Param{'plan'} |
|
493 |
,"howto" => \$Param{'howto'} |
|
494 |
,"version|v" => \$Param{'version'} |
|
495 |
,"preview" => \$Param{'preview'} |
|
496 |
,"copy" => \$Param{'copy'} |
|
497 |
,"commit" => \$Param{'commit'} |
|
498 |
,'rollback' => \$Param{'rollback'} |
|
499 |
);
|
|
500 |
||
501 |
# -----------------------------
|
|
502 |
# set DEBUG
|
|
503 |
$DEBUG = $Param{'DEBUG'} if ($Param{'DEBUG'}>=$DEBUG); |
|
504 |
||
505 |
# -----------------------------
|
|
506 |
# check for things which aren't
|
|
507 |
# declared as options:
|
|
508 |
# 2 arguments: (user,db) -> ('localhost','user','db')
|
|
509 |
if ($#ARGV == 1) { |
|
510 |
MySQLaccess::Debug::Print(2,"$script called with 2 arguments:"); |
|
511 |
$Param{'host'} = $Param{'host'} || 'localhost'; |
|
512 |
$Param{'user'} = $ARGV[0] || $Param{'user'}; |
|
513 |
$Param{'db'} = $ARGV[1] || $Param{'db'}; |
|
514 |
}
|
|
515 |
# 3 arguments: (host,user,db)
|
|
516 |
if ($#ARGV == 2) { |
|
517 |
MySQLaccess::Debug::Print(2,"$script called with 3 arguments:"); |
|
518 |
$Param{'host'} = $ARGV[0] || $Param{'host'}; |
|
519 |
$Param{'user'} = $ARGV[1] || $Param{'user'}; |
|
520 |
$Param{'db'} = $ARGV[2] || $Param{'db'}; |
|
521 |
}
|
|
522 |
||
523 |
# -------------------------------------
|
|
524 |
# prompt for user password if requested
|
|
525 |
if ( defined($Param{'password'}) && length($Param{'password'}) == 0 ) { |
|
526 |
$Param{'password'} = PromptPass( |
|
527 |
"Password for MySQL user $Param{'user'}: "); |
|
528 |
}
|
|
529 |
}
|
|
530 |
if ($MySQLaccess::CGI) { #CGI-version |
|
531 |
require CGI;
|
|
532 |
$Q = new CGI; |
|
533 |
$Param{'help'} = $Q->param('help') ; |
|
534 |
$Param{'host'} = $Q->param('host') || $Q->param('h') || $Param{'host'}; |
|
535 |
$Param{'user'} = $Q->param('user') || $Q->param('u') || $Param{'user'}; |
|
536 |
$Param{'db'} = $Q->param('db') || $Q->param('d') || $Param{'db'}; |
|
537 |
$Param{'password'} = $Q->param('password') || $Q->param('p') || $Param{'password'}; |
|
538 |
$Param{'superuser'} = $Q->param('superuser') || $Q->param('U') || $Param{'superuser'}; |
|
539 |
$Param{'spassword'} = $Q->param('spassword') || $Q->param('P') || $Param{'spassword'}; |
|
540 |
$Param{'rhost'} = $Q->param('rhost') || $Q->param('H') || $Param{'rhost'}; |
|
541 |
$Param{'old_server'}= $Q->param('old_server')|| $Param{'old_server'}; |
|
542 |
$Param{'debug'} = $Q->param('debug') || $Param{'debug'}; |
|
543 |
$Param{'brief'} = $Q->param('brief') || $Param{'brief'}; |
|
544 |
$Param{'table'} = $Q->param('table') || $Param{'table'}; |
|
545 |
$Param{'relnotes'} = $Q->param('relnotes'); |
|
546 |
$Param{'plan'} = $Q->param('plan'); |
|
547 |
$Param{'howto'} = $Q->param('howto'); |
|
548 |
$Param{'version'} = $Q->param('version') ? $Q->param('version') : $Q->param('v'); |
|
549 |
$Param{'edit'} = $Q->param('edit'); |
|
550 |
$Param{'preview'} = $Q->param('preview'); |
|
551 |
$Param{'copy'} = $Q->param('copy'); |
|
552 |
$Param{'commit'} = $Q->param('commit'); |
|
553 |
$Param{'rollback'} = $Q->param('rollback'); |
|
554 |
# -----------------------------
|
|
555 |
# set DEBUG
|
|
556 |
$DEBUG = $Q->param('debug') if ($Q->param('debug')>=$DEBUG); |
|
557 |
}
|
|
558 |
||
559 |
# ----------------------
|
|
560 |
# brief and table-format
|
|
561 |
# exclude each-other
|
|
562 |
# table-format is prefered
|
|
563 |
if (defined($Param{'table'})) { undef($Param{'brief'}); } |
|
564 |
if (defined($Param{'preview'}) or |
|
565 |
defined($Param{'copy'}) or |
|
566 |
defined($Param{'commit'}) or |
|
567 |
defined($Param{'rollback'}) ) { $Param{'edit'}='on'; } |
|
568 |
||
569 |
||
570 |
# ----------------------
|
|
571 |
# if no host is given
|
|
572 |
# assume we mean 'localhost'
|
|
573 |
if (!defined($Param{'host'})) { $Param{'host'}='localhost'; } |
|
574 |
||
575 |
# ----------------------
|
|
576 |
# perform some checks
|
|
577 |
# -> eliminate 'broken pipe' error
|
|
578 |
push(@MySQLaccess::Grant::Error,'not_found_mysql') if !(-x $MYSQL); |
|
579 |
push(@MySQLaccess::Grant::Error,'not_found_diff') if !(-x $DIFF); |
|
580 |
push(@MySQLaccess::Grant::Error,'not_found_mysqldump') if !(-x $MYSQLDUMP); |
|
581 |
if (@MySQLaccess::Grant::Error) { |
|
582 |
MySQLaccess::Report::Print_Error_Messages() ; |
|
583 |
exit 0; |
|
584 |
}
|
|
585 |
||
586 |
#-----------------------
|
|
587 |
# get info/help if necc.
|
|
588 |
$print_usage=1; |
|
589 |
if ( defined($Param{'version'}) ) { |
|
590 |
MySQLaccess::Report::Print_Version(); |
|
591 |
$print_usage=0; |
|
592 |
MySQLaccess::Report::Print_Footer(); |
|
593 |
MySQLaccess::DB::CloseConnection(); |
|
594 |
exit 0; |
|
595 |
# exit 0;
|
|
596 |
}
|
|
597 |
if ( defined($Param{'relnotes'}) ) { |
|
598 |
MySQLaccess::Report::Print_Relnotes(); |
|
599 |
$print_usage=0; |
|
600 |
MySQLaccess::Report::Print_Footer(); |
|
601 |
MySQLaccess::DB::CloseConnection(); |
|
602 |
exit 0; |
|
603 |
# exit 0;
|
|
604 |
}
|
|
605 |
if ( defined($Param{'plan'}) ) { |
|
606 |
MySQLaccess::Report::Print_Plans(); |
|
607 |
$print_usage=0; |
|
608 |
MySQLaccess::Report::Print_Footer(); |
|
609 |
MySQLaccess::DB::CloseConnection(); |
|
610 |
exit 0; |
|
611 |
# exit 0;
|
|
612 |
}
|
|
613 |
if ( defined($Param{'howto'}) ) { |
|
614 |
MySQLaccess::Report::Print_HowTo(); |
|
615 |
$print_usage=0; |
|
616 |
MySQLaccess::Report::Print_Footer(); |
|
617 |
MySQLaccess::DB::CloseConnection(); |
|
618 |
exit 0; |
|
619 |
# exit 0;
|
|
620 |
}
|
|
621 |
||
622 |
# -----------------------------
|
|
623 |
# generate a help-screen in CMD-mode
|
|
624 |
# or a blanc form in CGI-mode
|
|
625 |
if ( defined($Param{'help'}) |
|
626 |
or !defined($Param{'user'}) |
|
627 |
or !defined($Param{'host'}) |
|
628 |
or !defined($Param{'db'}) |
|
629 |
) { |
|
630 |
push(@MySQLaccess::Grant::Error,'user_required') unless defined($Param{'user'}); |
|
631 |
push(@MySQLaccess::Grant::Error,'db_required') unless defined($Param{'db'}); |
|
632 |
push(@MySQLaccess::Grant::Error,'host_required') unless defined($Param{'host'}); |
|
633 |
MySQLaccess::Report::Print_Usage() if $print_usage; |
|
634 |
exit 0; |
|
635 |
}
|
|
636 |
||
637 |
||
638 |
# ----------------------------
|
|
639 |
# get hostname and local-ip
|
|
640 |
# for localhost
|
|
641 |
$localhost = MySQLaccess::Host::LocalHost(); |
|
642 |
$local_ip = MySQLaccess::Host::Name2IP($localhost); |
|
643 |
$MySQLaccess::Host::localhost = MySQLaccess::Host::LocalHost(); |
|
644 |
$MySQLaccess::Host::local_ip = MySQLaccess::Host::Name2IP($localhost); |
|
645 |
MySQLaccess::Debug::Print(3, "localhost name=$localhost, ip=$local_ip"); |
|
646 |
||
647 |
#-----------------------------------
|
|
648 |
# version of MySQL-server to connect
|
|
649 |
# to determine use of full where clause
|
|
650 |
$MySQLaccess::Host::SERVER = $Param{'old_server'} ? '3.20' : $SERVER; |
|
651 |
||
652 |
#---------------------------------
|
|
653 |
# create the config file for mysql and mysqldump
|
|
654 |
# to avoid passing authentication info on the command line
|
|
655 |
#
|
|
656 |
MergeConfigFiles(); |
|
657 |
die "Unsafe config file found: $unsafeConfig\n" if $unsafeConfig; |
|
658 |
if (defined($Param{'superuser'})) { |
|
659 |
$MYSQL_CNF{'mysql'}{'user'} = $Param{'superuser'}; |
|
660 |
$MYSQL_CNF{'mysqldump'}{'user'} = $Param{'superuser'}; |
|
661 |
}
|
|
662 |
if (defined($Param{'spassword'})) { |
|
663 |
if ( $CMD && length($Param{'spassword'}) == 0 ) { |
|
664 |
$Param{'spassword'} = |
|
665 |
PromptPass("Password for MySQL superuser $Param{'superuser'}: "); |
|
666 |
}
|
|
667 |
if ( length($Param{'spassword'}) > 0 ) { |
|
668 |
$MYSQL_CNF{'mysql'}{'password'} = $Param{'spassword'}; |
|
669 |
$MYSQL_CNF{'mysqldump'}{'password'} = $Param{'spassword'}; |
|
670 |
}
|
|
671 |
}
|
|
672 |
WriteTempConfigFile(); |
|
673 |
||
674 |
#---------------------------------
|
|
675 |
# Inform user if he has not enough
|
|
676 |
# privileges to read the access-db
|
|
677 |
if ( $nerror=MySQLaccess::DB::OpenConnection() ) { |
|
678 |
MySQLaccess::Report::Print_Error_Access($nerror); |
|
679 |
exit 0; |
|
680 |
}
|
|
681 |
||
682 |
# -----------------------
|
|
683 |
# Read MySQL ACL-files
|
|
684 |
if ($nerror=MySQLaccess::Grant::ReadTables()) { |
|
685 |
MySQLaccess::Report::Print_Error_Access($nerror); |
|
686 |
exit 0; |
|
687 |
}; |
|
688 |
if ($Param{'edit'} and $nerror=MySQLaccess::Grant::ReadTables('tmp')) { |
|
689 |
MySQLaccess::Report::Print_Error_Access($nerror); |
|
690 |
exit 0; |
|
691 |
}
|
|
692 |
||
693 |
#---------------------------------
|
|
694 |
# reload temporay grant-tables
|
|
695 |
# with data from original ones
|
|
696 |
if ( defined($Param{'copy'}) ) { |
|
697 |
$nerror=MySQLaccess::DB::LoadTmpTables(); |
|
698 |
if ($nerror) { |
|
699 |
MySQLaccess::Report::Print_Error_Access($nerror); |
|
700 |
exit 0; |
|
701 |
}
|
|
702 |
my $msg = "The grant-rules are copied from the grant-tables to\n" |
|
703 |
. "the temporary tables."; |
|
704 |
MySQLaccess::Report::Print_Message([$msg]); |
|
705 |
# MySQLaccess::Report::Print_Footer();
|
|
706 |
# MySQLaccess::DB::CloseConnection();
|
|
707 |
# exit 0;
|
|
708 |
}
|
|
709 |
||
710 |
||
711 |
#---------------------------------
|
|
712 |
# preview result of changes in the
|
|
713 |
# grant-tables
|
|
714 |
if ( defined($Param{'preview'}) ) { |
|
715 |
$aref=MySQLaccess::Grant::Diff_Privileges(); |
|
716 |
MySQLaccess::Report::Print_Diff_ACL($aref); |
|
717 |
# MySQLaccess::Report::Print_Footer();
|
|
718 |
# MySQLaccess::DB::CloseConnection();
|
|
719 |
# exit 0;
|
|
720 |
}
|
|
721 |
||
722 |
||
723 |
#---------------------------------
|
|
724 |
# reload grant-tables
|
|
725 |
# with data from temporary tables
|
|
726 |
if ( defined($Param{'commit'}) ) { |
|
727 |
if ($nerror = MySQLaccess::DB::CommitGrantTables()) { |
|
728 |
MySQLaccess::Report::Print_Error_Access($nerror); |
|
729 |
exit 0; |
|
730 |
}
|
|
731 |
my $msg = "The grant-rules have been copied from the temporary tables\n" |
|
732 |
. "to the grant-tables."; |
|
733 |
my $msg1= "Don't forget to do an 'mysqladmin reload' before these\n" |
|
734 |
. "changes take effect."; |
|
735 |
my $msg2= "A backup-version of your original grant-rules are saved in the\n" |
|
736 |
. "backup-tables, so you can always perform a 1-level rollback."; |
|
737 |
MySQLaccess::Report::Print_Message([$msg,$msg1,$msg2]); |
|
738 |
# MySQLaccess::Report::Print_Footer();
|
|
739 |
# MySQLaccess::DB::CloseConnection();
|
|
740 |
# exit 0;
|
|
741 |
}
|
|
742 |
||
743 |
#---------------------------------
|
|
744 |
# restore previous grant-rules
|
|
745 |
# with data from backup tables
|
|
746 |
if ( defined($Param{'rollback'}) ) { |
|
747 |
if ($nerror = MySQLaccess::DB::RollbackGrantTables()) { |
|
748 |
MySQLaccess::Report::Print_Error_Access($nerror); |
|
749 |
exit 0; |
|
750 |
}
|
|
751 |
my $msg = "The old grant-rules have been copied back from the backup tables\n" |
|
752 |
. "to the grant-tables."; |
|
753 |
my $msg1= "Don't forget to do an 'mysqladmin reload' before these\n" |
|
754 |
. "changes take effect."; |
|
755 |
MySQLaccess::Report::Print_Message([$msg,$msg1]); |
|
756 |
# MySQLaccess::Report::Print_Footer();
|
|
757 |
# MySQLaccess::DB::CloseConnection();
|
|
758 |
# exit 0;
|
|
759 |
}
|
|
760 |
#----------------------------------
|
|
761 |
# show edit-taskbar
|
|
762 |
if ( defined($Param{'edit'})) { |
|
763 |
if ($MySQLaccess::CGI ) { |
|
764 |
MySQLaccess::Report::Print_Edit(); |
|
765 |
$print_usage=0; |
|
766 |
MySQLaccess::Report::Print_Footer(); |
|
767 |
MySQLaccess::DB::CloseConnection(); |
|
768 |
exit 0; |
|
769 |
}
|
|
770 |
else { |
|
771 |
MySQLaccess::Report::Print_Edit(); |
|
772 |
$print_usage=0; |
|
773 |
MySQLaccess::Report::Print_Footer(); |
|
774 |
MySQLaccess::DB::CloseConnection(); |
|
775 |
exit 0; |
|
776 |
}
|
|
777 |
}
|
|
778 |
||
779 |
||
780 |
# -----------------------------
|
|
781 |
# Build list of users,dbs,hosts
|
|
782 |
# to process...
|
|
783 |
@all_dbs = @{MySQLaccess::DB::Get_All_dbs($Param{'db'})}; |
|
784 |
@all_users = @{MySQLaccess::DB::Get_All_users($Param{'user'})}; |
|
785 |
@all_hosts = @{MySQLaccess::DB::Get_All_hosts($Param{'host'})}; |
|
786 |
#if EDIT-mode
|
|
787 |
#@all_dbs_tmp = @{MySQLaccess::DB::Get_All_dbs($Param{'db'},'tmp')};
|
|
788 |
#@all_users_tmp = @{MySQLaccess::DB::Get_All_users($Param{'user'},'tmp')};
|
|
789 |
#@all_hosts_tmp = @{MySQLaccess::DB::Get_All_hosts($Param{'host'},'tmp')};
|
|
790 |
||
791 |
# -----------------------------
|
|
792 |
# Report access-rights for each
|
|
793 |
# tuple (host,user,db)
|
|
794 |
#$headers=0;
|
|
795 |
my %Access = (); |
|
796 |
foreach $host (@all_hosts) { |
|
797 |
foreach $user (@all_users) { |
|
798 |
foreach $db (@all_dbs) { |
|
799 |
MySQLaccess::Grant::Initialize(); |
|
800 |
%Access = MySQLaccess::Grant::Get_Access_Rights($host,$user,$db); |
|
801 |
MySQLaccess::Report::Print_Access_rights($host,$user,$db,\%Access); |
|
802 |
}
|
|
803 |
}
|
|
804 |
}
|
|
805 |
||
806 |
# -----------------------------
|
|
807 |
# End script
|
|
808 |
MySQLaccess::Report::Print_Footer(); |
|
809 |
MySQLaccess::DB::CloseConnection(); |
|
810 |
exit 0; |
|
811 |
||
812 |
#############################################################
|
|
813 |
# FUNCTIONS #
|
|
814 |
###############
|
|
815 |
sub GetMode {
|
|
816 |
my $cmd=0; |
|
817 |
my $cgi=0; |
|
818 |
if (defined($ENV{'HTTP_HOST'})) { $cmd=0; $cgi=1; } |
|
819 |
else { $cmd=1; $cgi=0; } |
|
820 |
return ($cmd,$cgi); |
|
821 |
}
|
|
822 |
||
823 |
# ================================
|
|
824 |
# sub PromptPass
|
|
825 |
# prompt tty for a password
|
|
826 |
# ================================
|
|
827 |
sub PromptPass {
|
|
828 |
my ($prompt) = @_; |
|
829 |
my $password; |
|
830 |
$ENV{PATH} = "/bin:/usr/bin"; |
|
831 |
$ENV{IFS} = " \t\n"; |
|
832 |
$ENV{SHELL} = "/bin/sh"; |
|
833 |
system "stty -echo"; |
|
834 |
print $prompt; |
|
835 |
chomp($password = <STDIN>); |
|
836 |
print "\n"; |
|
837 |
system "stty echo"; |
|
838 |
$password; |
|
839 |
}
|
|
840 |
||
841 |
# =================================
|
|
842 |
# sub CheckUnsafeFile
|
|
843 |
# tell if a config file containing a password is unsafe
|
|
844 |
# =================================
|
|
845 |
sub CheckUnsafeFile {
|
|
846 |
my ($fname) = @_; |
|
847 |
my ($dev, $ino, $mode, $nlink, |
|
848 |
$uid, $gid, $rdev, $size, |
|
849 |
$atime, $mtime, $ctime, $blksize, $blocks) = stat($fname); |
|
850 |
||
851 |
if ( $uid != $< ) { # unsafe if owned by other than current user |
|
852 |
return 1; |
|
853 |
}
|
|
854 |
if ( $mode & 066 ) { # unsafe if accessible by other |
|
855 |
return 1; |
|
856 |
}
|
|
857 |
$fname =~ s#/[^/]+$##; |
|
858 |
if ( (length $fname) > 0 ) { |
|
859 |
return CheckUnsafeDir($fname); |
|
860 |
}
|
|
861 |
return 0; |
|
862 |
}
|
|
863 |
||
864 |
# =================================
|
|
865 |
# sub CheckUnsafeDir
|
|
866 |
# tell if a directory is unsafe
|
|
867 |
# =================================
|
|
868 |
sub CheckUnsafeDir {
|
|
869 |
my ($fname) = @_; |
|
870 |
my ($dev, $ino, $mode, $nlink, |
|
871 |
$uid, $gid, $rdev, $size, |
|
872 |
$atime, $mtime, $ctime, $blksize, $blocks) = stat($fname); |
|
873 |
||
874 |
# not owned by me or root
|
|
875 |
if ( ($uid != $<) && ($uid != 0) ) { |
|
876 |
return 1; |
|
877 |
}
|
|
878 |
if ( $mode & 022 ) { # unsafe if writable by other |
|
879 |
return 1 unless $mode & 01000; # but sticky bit ok |
|
880 |
}
|
|
881 |
$fname =~ s#/[^/]+$##; |
|
882 |
if ( (length $fname) > 0 ) { |
|
883 |
return CheckUnsafeDir($fname); |
|
884 |
}
|
|
885 |
return 0; |
|
886 |
}
|
|
887 |
||
888 |
# =================================
|
|
889 |
# sub MergeConfigFile
|
|
890 |
# merge data from .cnf file
|
|
891 |
# =================================
|
|
892 |
sub MergeConfigFile {
|
|
893 |
my ($fname) = @_; |
|
894 |
my ($group, $item, $value); |
|
895 |
if ( open CNF, $fname ) { |
|
896 |
while (<CNF>) { |
|
897 |
s/^\s+//; |
|
898 |
next if /^[#;]/; |
|
899 |
if ( /\[\s*(\w+)\s*]/ ) { |
|
900 |
$group = $1; |
|
901 |
$group =~ tr/A-Z/a-z/; |
|
902 |
if ( !exists $MYSQL_CNF{$group} ) { |
|
903 |
undef $group; |
|
904 |
}
|
|
905 |
} elsif ( defined $group ) { |
|
906 |
($item, $value) = /((?:\w|-)+)\s*=\s*(\S+)/; |
|
907 |
# don't unquote backslashes as we just write it back out
|
|
908 |
if ( defined $item ) { |
|
909 |
if ( $item =~ /^password$/ ) { |
|
910 |
if ( CheckUnsafeFile($fname) ) { |
|
911 |
$unsafeConfig = $fname; |
|
912 |
}
|
|
913 |
}
|
|
914 |
if ( $group eq 'client' ) { |
|
915 |
$MYSQL_CNF{'mysql'}{$item} = $value; |
|
916 |
$MYSQL_CNF{'mysqldump'}{$item} = $value; |
|
917 |
} else { |
|
918 |
$MYSQL_CNF{$group}{$item} = $value; |
|
919 |
}
|
|
920 |
}
|
|
921 |
}
|
|
922 |
}
|
|
923 |
close(CNF); |
|
924 |
}
|
|
925 |
}
|
|
926 |
||
927 |
# =================================
|
|
928 |
# sub MergeConfigFiles
|
|
929 |
# merge options from config files
|
|
930 |
# NOTE: really should do two separate merges for each
|
|
931 |
# client to exactly duplicate order of resulting argument lists
|
|
932 |
# =================================
|
|
933 |
sub MergeConfigFiles {
|
|
934 |
my ($name,$pass,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = getpwuid $<; |
|
935 |
MergeConfigFile("@sysconfdir@/my.cnf"); |
|
936 |
MergeConfigFile("/etc/my.cnf"); |
|
937 |
MergeConfigFile("$dir/.my.cnf"); |
|
938 |
}
|
|
939 |
||
940 |
# =================================
|
|
941 |
# sub WriteTempConfigFile
|
|
942 |
# write
|
|
943 |
# =================================
|
|
944 |
sub WriteTempConfigFile {
|
|
945 |
sysopen CNFFILE, $MYSQL_CNF, O_RDWR|O_CREAT|O_EXCL, 0700 |
|
946 |
or die "sysopen $MYSQL_CNF: $!"; |
|
947 |
||
948 |
# groups may be in any order, generic groups such as [client] assumed
|
|
949 |
# here to be empty
|
|
950 |
foreach $group (keys %MYSQL_CNF) { |
|
951 |
print CNFFILE "[$group]\n"; |
|
952 |
foreach $item (keys %{$MYSQL_CNF{$group}}) { |
|
953 |
if ( defined $MYSQL_CNF{$group}{$item} ) { |
|
954 |
print CNFFILE "$item=$MYSQL_CNF{$group}{$item}\n"; |
|
955 |
} else { |
|
956 |
print CNFFILE "$item\n"; |
|
957 |
}
|
|
958 |
}
|
|
959 |
print CNFFILE "\n"; |
|
960 |
}
|
|
961 |
close(CNFFILE); |
|
962 |
}
|
|
963 |
||
964 |
######################################################################
|
|
965 |
package MySQLaccess::DB;
|
|
966 |
###########
|
|
967 |
BEGIN {
|
|
968 |
$DEBUG = 2; |
|
969 |
$DEBUG = $MySQLaccess::DEBUG unless ($DEBUG); |
|
970 |
# Error-messages from the MySQL client
|
|
971 |
%ACCESS_ERR= ('Access_denied' => 'Access denied' |
|
972 |
,'Dbaccess_denied' => 'Access to database denied' |
|
973 |
,'Unrecognized_option' => 'unrecognized option' |
|
974 |
,'Unknown_table' => "Can't find file:" |
|
975 |
,'unknown_error' => '^ERROR:' |
|
976 |
); |
|
977 |
}
|
|
978 |
# ######################################
|
|
979 |
# Connecting to the MYSQL DB
|
|
980 |
# ======================================
|
|
981 |
# sub OpenConnection
|
|
982 |
# Open an connection to the mysql-db
|
|
983 |
# questions to MYSQL_Q
|
|
984 |
# answers from MYSQL_A
|
|
985 |
# ======================================
|
|
986 |
sub OpenConnection {
|
|
987 |
my $pid; |
|
988 |
MySQLaccess::Debug::Print(2,"OpenConnection:"); |
|
989 |
||
990 |
# check path to mysql-client executable
|
|
991 |
if (! -f $MySQLaccess::MYSQL) { |
|
992 |
if ($MySQLaccess::CMD) { die "Could not find MySQL-client '$MySQLaccess::MYSQL'"; } |
|
993 |
if ($MySQLaccess::CGI) { |
|
994 |
print "<center>\n<font color=Red>\n"; |
|
995 |
print "ERROR: Could not find MySQL-client '$MySQLaccess::MYSQL'"; |
|
996 |
print "</center>\n</font>\n"; |
|
997 |
exit 0; |
|
998 |
}
|
|
999 |
}
|
|
1000 |
||
1001 |
# path to mysql executable
|
|
1002 |
my $connect = "$MySQLaccess::MYSQL --defaults-file=$MySQLaccess::MYSQL_CNF"; |
|
1003 |
$connect .= " $MySQLaccess::MYSQL_OPT"; |
|
1004 |
# superuser, spassword transmitted via defaults-file
|
|
1005 |
if (defined($MySQLaccess::Param{'rhost'})) { $connect .= " --host=$MySQLaccess::Param{'rhost'}"; } |
|
1006 |
# other options??
|
|
1007 |
||
1008 |
# grant-database
|
|
1009 |
$connect .= " $MySQLaccess::ACCESS_DB"; |
|
1010 |
||
1011 |
# open connection (not using /bin/sh -c)
|
|
1012 |
MySQLaccess::Debug::Print(2,"Connecting to: $connect"); |
|
1013 |
$pid=IPC::Open3::open3(\*MYSQL_Q,\*MYSQL_A,"",split /\s+/,$connect); |
|
1014 |
MySQLaccess::Debug::Print(2,"PID of open pipe: $pid"); |
|
1015 |
||
1016 |
# check connection
|
|
1017 |
print MYSQL_Q "select 'ok';\n"; |
|
1018 |
$answer = <MYSQL_A>; #answer from mysql |
|
1019 |
MySQLaccess::Debug::Print(2,"Answer: $answer\n"); |
|
1020 |
foreach $nerror (sort(keys(%ACCESS_ERR))) { |
|
1021 |
MySQLaccess::Debug::Print(3,"check answer for error $ACCESS_ERR{$nerror}"); |
|
1022 |
if (grep(/$ACCESS_ERR{$nerror}/i,$answer)) { |
|
1023 |
MySQLaccess::Debug::Print(2,"Answer contain error [$nerror]"); |
|
1024 |
return $nerror; |
|
1025 |
}
|
|
1026 |
}
|
|
1027 |
||
1028 |
if (0) { |
|
1029 |
# check server-version
|
|
1030 |
print MYSQL_Q "select 'ok';\n"; |
|
1031 |
$answer = <MYSQL_A>; #answer from mysql |
|
1032 |
MySQLaccess::Debug::Print(2,"Answer: $answer\n"); |
|
1033 |
foreach $nerror (sort(keys(%ACCESS_ERR))) { |
|
1034 |
MySQLaccess::Debug::Print(3,"check answer for error $ACCESS_ERR{$nerror}"); |
|
1035 |
if (grep(/$ACCESS_ERR{$nerror}/i,$answer)) { |
|
1036 |
MySQLaccess::Debug::Print(2,"Answer contain error [$nerror]"); |
|
1037 |
return $nerror; |
|
1038 |
}
|
|
1039 |
}
|
|
1040 |
}
|
|
1041 |
||
1042 |
my $skip=<MYSQL_A>; |
|
1043 |
return 0; |
|
1044 |
}
|
|
1045 |
||
1046 |
# ======================================
|
|
1047 |
# sub CloseConnection
|
|
1048 |
# Close the connection to the mysql-db
|
|
1049 |
# ======================================
|
|
1050 |
sub CloseConnection {
|
|
1051 |
close MYSQL_Q;
|
|
1052 |
close MYSQL_A;
|
|
1053 |
}
|
|
1054 |
||
1055 |
# ===========================================================
|
|
1056 |
# sub CreateTable($table)
|
|
1057 |
# Create temporary/backup table
|
|
1058 |
# ===========================================================
|
|
1059 |
sub CreateTable {
|
|
1060 |
my $pid; |
|
1061 |
my ($table,$force) = @_; |
|
1062 |
my %tables = ( $MySQLaccess::ACCESS_U_TMP => $MySQLaccess::ACCESS_U, |
|
1063 |
$MySQLaccess::ACCESS_H_TMP => $MySQLaccess::ACCESS_H, |
|
1064 |
$MySQLaccess::ACCESS_D_TMP => $MySQLaccess::ACCESS_D, |
|
1065 |
$MySQLaccess::ACCESS_U_BCK => $MySQLaccess::ACCESS_U, |
|
1066 |
$MySQLaccess::ACCESS_H_BCK => $MySQLaccess::ACCESS_H, |
|
1067 |
$MySQLaccess::ACCESS_D_BCK => $MySQLaccess::ACCESS_D, |
|
1068 |
$MySQLaccess::ACCESS_U => $MySQLaccess::ACCESS_U_BCK, |
|
1069 |
$MySQLaccess::ACCESS_H => $MySQLaccess::ACCESS_H_BCK, |
|
1070 |
$MySQLaccess::ACCESS_D => $MySQLaccess::ACCESS_D_BCK, |
|
1071 |
); |
|
1072 |
my $tbl; |
|
1073 |
my $query=""; |
|
1074 |
my $delim; |
|
1075 |
my $skip; |
|
1076 |
my $create; |
|
1077 |
my @known_tables=(); |
|
1078 |
||
1079 |
# print STDERR "CreateTable($table)\n";
|
|
1080 |
MySQLaccess::Debug::Print(1,"CreateTable($table):"); |
|
1081 |
||
1082 |
## error-handling
|
|
1083 |
return 'Unknown_table' unless defined($tables{$table}); |
|
1084 |
||
1085 |
## build list of known/existing tables;
|
|
1086 |
## if 'force' existing table is dropped first
|
|
1087 |
if (defined($force) and $force) { |
|
1088 |
@known_tables = Show_Tables(); |
|
1089 |
if (grep(/^$table$/,@known_tables)) { |
|
1090 |
$query = "DROP TABLE $table;"; |
|
1091 |
}
|
|
1092 |
}
|
|
1093 |
||
1094 |
## path to mysqldump executable
|
|
1095 |
my $connect = $MySQLaccess::MYSQLDUMP; |
|
1096 |
$connect .= " --defaults-file=$MySQLaccess::MYSQL_CNF --no-data"; |
|
1097 |
# superuser, spassword transmitted via defaults-file
|
|
1098 |
if (defined($MySQLaccess::Param{'rhost'})) { $connect .= " --host=$MySQLaccess::Param{'rhost'}"; } |
|
1099 |
$connect .= " $MySQLaccess::ACCESS_DB"; |
|
1100 |
$connect .= " $tables{$table}"; |
|
1101 |
||
1102 |
||
1103 |
## get creation-data for original table
|
|
1104 |
$create = ''; |
|
1105 |
my $mysqldump = $connect; |
|
1106 |
$mysqldump =~ s/ \$TABLE / $tbl /; |
|
1107 |
||
1108 |
# open connection (not using /bin/sh -c)
|
|
1109 |
MySQLaccess::Debug::Print(2,"Connecting to: $connect"); |
|
1110 |
$pid=IPC::Open3::open3(\*DONTCARE,\*CREATE,"",split /\s+/,$mysqldump); |
|
1111 |
MySQLaccess::Debug::Print(2,"PID of open pipe: $pid"); |
|
1112 |
#open(CREATE,"$mysqldump");
|
|
1113 |
@create = <CREATE>; |
|
1114 |
$create = "@create"; |
|
1115 |
foreach $nerror (sort(keys(%ACCESS_ERR))) { |
|
1116 |
MySQLaccess::Debug::Print(3,"check answer for error $ACCESS_ERR{$nerror}"); |
|
1117 |
if (grep(/$ACCESS_ERR{$nerror}/i,$create)) { |
|
1118 |
MySQLaccess::Debug::Print(2,"Answer contain error [$nerror]"); |
|
1119 |
return $nerror; |
|
1120 |
}
|
|
1121 |
}
|
|
1122 |
close(CREATE); |
|
1123 |
close(DONTCARE); |
|
1124 |
||
1125 |
## manipulate result for creation-data for temporary table
|
|
1126 |
$create =~ s/CREATE TABLE $tables{$table} \(/CREATE TABLE $table \(/; |
|
1127 |
||
1128 |
## recreate temporary table
|
|
1129 |
$query .= "$create\n"; |
|
1130 |
$query .= "select 'ok';"; |
|
1131 |
||
1132 |
## execute query
|
|
1133 |
print MYSQL_Q "$query\n"; |
|
1134 |
# print STDERR $query;
|
|
1135 |
||
1136 |
$answer = <MYSQL_A>; #answer from mysql |
|
1137 |
# print STDERR "A>",$answer;
|
|
1138 |
MySQLaccess::Debug::Print(2,"Answer: $answer\n"); |
|
1139 |
foreach $nerror (sort(keys(%ACCESS_ERR))) { |
|
1140 |
# print STDERR "->$nerror?";
|
|
1141 |
MySQLaccess::Debug::Print(3,"check answer for error $ACCESS_ERR{$nerror}"); |
|
1142 |
if (grep(/$ACCESS_ERR{$nerror}/i,$answer)) { |
|
1143 |
# print STDERR "Yes!";
|
|
1144 |
MySQLaccess::Debug::Print(2,"Answer contain error [$nerror]"); |
|
1145 |
return $nerror; |
|
1146 |
}
|
|
1147 |
}
|
|
1148 |
||
1149 |
$delim = <MYSQL_A>; # read header |
|
1150 |
if ($delim ne "ok\n") { |
|
1151 |
while (($line=<MYSQL_A>) ne "ok\n") |
|
1152 |
{ MySQLaccess::Debug::Print(3," A> $line"); } |
|
1153 |
$skip = <MYSQL_A>; # skip result 'ok' |
|
1154 |
}
|
|
1155 |
# print STDERR "CreateTable done\n";
|
|
1156 |
return 0; |
|
1157 |
}
|
|
1158 |
||
1159 |
||
1160 |
# ===========================================================
|
|
1161 |
# sub CopyTable()
|
|
1162 |
# Copy the structure and the data of a table to another table
|
|
1163 |
# ===========================================================
|
|
1164 |
sub CopyTable {
|
|
1165 |
my ($from,$to,$force) = @_; |
|
1166 |
my @known_tables = Show_Tables(); |
|
1167 |
my $query = ""; |
|
1168 |
my $nerror= 0; |
|
1169 |
my $skip; |
|
1170 |
||
1171 |
# print STDERR "CopyTable($from,$to)\n";
|
|
1172 |
MySQLaccess::Debug::Print(1,"MySQLaccess::DB::CopyTable($from,$to)"); |
|
1173 |
||
1174 |
## error-handling
|
|
1175 |
if (!grep(/^$from$/,@known_tables)) { return 'Unknown_table'; } |
|
1176 |
||
1177 |
## copy structure
|
|
1178 |
## if forced
|
|
1179 |
if (defined($force) and $force) { |
|
1180 |
return $nerror if ($nerror=CreateTable($to,$force)); |
|
1181 |
# print STDERR "Structure copied\n";
|
|
1182 |
}
|
|
1183 |
||
1184 |
## copy data
|
|
1185 |
$query .= "DELETE FROM $to;"; |
|
1186 |
$query .= "INSERT INTO $to SELECT * FROM $from;"; |
|
1187 |
$query .= "SELECT 'ok';\n"; |
|
1188 |
MySQLaccess::Debug::Print(2,"Query: $query"); |
|
1189 |
||
1190 |
## execute query
|
|
1191 |
print MYSQL_Q "$query\n"; |
|
1192 |
# print STDERR $query;
|
|
1193 |
||
1194 |
## check for errors...
|
|
1195 |
my $answer = <MYSQL_A>; #answer from mysql |
|
1196 |
# print STDERR $answer;
|
|
1197 |
MySQLaccess::Debug::Print(2,"Answer: $answer\n"); |
|
1198 |
foreach $nerror (sort(keys(%ACCESS_ERR))) { |
|
1199 |
MySQLaccess::Debug::Print(3,"check answer for error $ACCESS_ERR{$nerror}"); |
|
1200 |
if (grep(/$ACCESS_ERR{$nerror}/i,$answer)) { |
|
1201 |
MySQLaccess::Debug::Print(2,"Answer contain error [$nerror]"); |
|
1202 |
return $nerror; |
|
1203 |
}
|
|
1204 |
}
|
|
1205 |
||
1206 |
my $delim = <MYSQL_A>; # read header |
|
1207 |
# print STDERR $delim;
|
|
1208 |
if ($delim ne "ok\n") { |
|
1209 |
while (($line=<MYSQL_A>) ne "ok\n") |
|
1210 |
{ MySQLaccess::Debug::Print(3," A> $line"); } |
|
1211 |
$skip = <MYSQL_A>; # skip result 'ok' |
|
1212 |
}
|
|
1213 |
||
1214 |
return 0; |
|
1215 |
}
|
|
1216 |
||
1217 |
# ===========================================================
|
|
1218 |
# sub LoadTmpTables()
|
|
1219 |
# (Re)load temporary tables with entries of ACL-tables
|
|
1220 |
# ===========================================================
|
|
1221 |
sub LoadTmpTables {
|
|
1222 |
my %tables = ( $MySQLaccess::ACCESS_U => $MySQLaccess::ACCESS_U_TMP, |
|
1223 |
$MySQLaccess::ACCESS_H => $MySQLaccess::ACCESS_H_TMP, |
|
1224 |
$MySQLaccess::ACCESS_D => $MySQLaccess::ACCESS_D_TMP, |
|
1225 |
); |
|
1226 |
my $tbl; |
|
1227 |
my $nerror; |
|
1228 |
||
1229 |
# print STDERR "LoadTmpTables:\n";
|
|
1230 |
MySQLaccess::Debug::Print(1,"LoadTmpTables():"); |
|
1231 |
foreach $tbl (keys(%tables)) { |
|
1232 |
# print STDERR "$tbl -> $tables{$tbl}\n";
|
|
1233 |
MySQLaccess::Debug::Print(2,"Loading table $tbl -> $tables{$tbl}."); |
|
1234 |
return $nerror if ($nerror=CopyTable($tbl,$tables{$tbl},'force')); |
|
1235 |
}
|
|
1236 |
return 0; |
|
1237 |
}
|
|
1238 |
||
1239 |
# ===========================================================
|
|
1240 |
# sub BackupGrantTables()
|
|
1241 |
# Make a backup of the original grant-tables
|
|
1242 |
# ===========================================================
|
|
1243 |
sub BackupGrantTables {
|
|
1244 |
my %tables = ( $MySQLaccess::ACCESS_U => $MySQLaccess::ACCESS_U_BCK, |
|
1245 |
$MySQLaccess::ACCESS_H => $MySQLaccess::ACCESS_H_BCK, |
|
1246 |
$MySQLaccess::ACCESS_D => $MySQLaccess::ACCESS_D_BCK, |
|
1247 |
); |
|
1248 |
my $tbl; |
|
1249 |
my $nerror; |
|
1250 |
||
1251 |
# print STDERR "BackupGrantTables:\n";
|
|
1252 |
MySQLaccess::Debug::Print(1,"BackupGrantTables():"); |
|
1253 |
foreach $tbl (keys(%tables)) { |
|
1254 |
# print STDERR "$tbl -> $tables{$tbl}\n";
|
|
1255 |
MySQLaccess::Debug::Print(2,"Backup table $tbl -> $tables{$tbl}."); |
|
1256 |
return $nerror if ($nerror=CopyTable($tbl,$tables{$tbl},'force')); |
|
1257 |
}
|
|
1258 |
return 0; |
|
1259 |
}
|
|
1260 |
||
1261 |
# ===========================================================
|
|
1262 |
# sub RollbackGrantTables()
|
|
1263 |
# Rollback the backup of the grant-tables
|
|
1264 |
# ===========================================================
|
|
1265 |
sub RollbackGrantTables {
|
|
1266 |
my %tables = ( $MySQLaccess::ACCESS_U_BCK => $MySQLaccess::ACCESS_U, |
|
1267 |
$MySQLaccess::ACCESS_H_BCK => $MySQLaccess::ACCESS_H, |
|
1268 |
$MySQLaccess::ACCESS_D_BCK => $MySQLaccess::ACCESS_D, |
|
1269 |
); |
|
1270 |
my $tbl; |
|
1271 |
my $nerror; |
|
1272 |
||
1273 |
# print STDERR "RollbackGrantTables:\n";
|
|
1274 |
MySQLaccess::Debug::Print(1,"RollbackGrantTables():"); |
|
1275 |
foreach $tbl (keys(%tables)) { |
|
1276 |
# print STDERR "$tbl -> $tables{$tbl}\n";
|
|
1277 |
MySQLaccess::Debug::Print(2,"Rollback table $tbl -> $tables{$tbl}."); |
|
1278 |
return $nerror if ($nerror=CopyTable($tbl,$tables{$tbl},'force')); |
|
1279 |
}
|
|
1280 |
return 0; |
|
1281 |
}
|
|
1282 |
||
1283 |
||
1284 |
# ===========================================================
|
|
1285 |
# sub CommitGrantTables()
|
|
1286 |
# Copy grant-rules from temporary tables to the ACL-tables
|
|
1287 |
# ===========================================================
|
|
1288 |
sub CommitGrantTables {
|
|
1289 |
my %tables = ( $MySQLaccess::ACCESS_U => $MySQLaccess::ACCESS_U_TMP, |
|
1290 |
$MySQLaccess::ACCESS_H => $MySQLaccess::ACCESS_H_TMP, |
|
1291 |
$MySQLaccess::ACCESS_D => $MySQLaccess::ACCESS_D_TMP, |
|
1292 |
); |
|
1293 |
my $tbl; |
|
1294 |
my $query; |
|
1295 |
my $delim; |
|
1296 |
my $skip; |
|
1297 |
my $create; |
|
1298 |
||
1299 |
print STDERR "CommitGrantTables()\n"; |
|
1300 |
MySQLaccess::Debug::Print(1,"CommitGrantTables():"); |
|
1301 |
||
1302 |
## Make backup of original grant-tables
|
|
1303 |
MySQLaccess::Debug::Print(2,"Making backup of original grant-tables..."); |
|
1304 |
BackupGrantTables(); |
|
1305 |
||
1306 |
## Copy data from temporay tables to grant-tables
|
|
1307 |
foreach $tbl (keys(%tables)) { |
|
1308 |
print STDERR "$tbl -> $tables{$tbl}\n"; |
|
1309 |
MySQLaccess::Debug::Print(2,"Loading data $tables{$tbl} -> $tbl."); |
|
1310 |
return $nerror if ($nerror=CopyTable($tables{$tbl},$tbl)); |
|
1311 |
}
|
|
1312 |
return 0; |
|
1313 |
}
|
|
1314 |
||
1315 |
||
1316 |
# ===========================================================
|
|
1317 |
# sub Show_Fields($table):
|
|
1318 |
# return (a reference to) a hash which holds the names
|
|
1319 |
# of all relevant grant-fields, with their index in the record,
|
|
1320 |
# and (a reference to) an array which holds the fieldnames.
|
|
1321 |
# ===========================================================
|
|
1322 |
sub Show_Fields {
|
|
1323 |
my ($table) = @_; |
|
1324 |
my %skip = ('host' => [0,1] |
|
1325 |
,'user' => [0,1,2] |
|
1326 |
,'db' => [0,1,2] |
|
1327 |
); |
|
1328 |
my %Struct = (); |
|
1329 |
my @Struct = (); |
|
1330 |
my $query = "show fields from $table;select 'ok';\n"; |
|
1331 |
my $i=0; |
|
1332 |
my $line; |
|
1333 |
||
1334 |
#print STDERR $query;
|
|
1335 |
MySQLaccess::Debug::Print(1,"Show_Fields($table):"); |
|
1336 |
MySQLaccess::Debug::Print(2,"SQL: $query"); |
|
1337 |
||
1338 |
print MYSQL_Q "$query"; |
|
1339 |
my $skip = <MYSQL_A>; #skip header |
|
1340 |
while (($line=<MYSQL_A>) ne "ok\n") |
|
1341 |
{
|
|
1342 |
#print STDERR ">",$line;
|
|
1343 |
chop($line); |
|
1344 |
MySQLaccess::Debug::Print(2," $table>: $line"); |
|
1345 |
my ($field,$type,$null,$key,$default,$extra) = split(' ',$line); |
|
1346 |
$field = ucfirst($field); |
|
1347 |
MySQLaccess::Debug::Print(3, " <split: $field - $type - $null - $key - $default - $extra"); |
|
1348 |
if (! grep(/$i/,@{$skip{$table}}) ){ |
|
1349 |
$Struct{$field} = $i; #hash |
|
1350 |
push(@Struct,$field); #array |
|
1351 |
MySQLaccess::Debug::Print(3," ==> added column[$i]: $field ($Struct{$field})"); |
|
1352 |
}
|
|
1353 |
else { |
|
1354 |
MySQLaccess::Debug::Print(3," ==> skipped column[$i], value=[$field]"); |
|
1355 |
}
|
|
1356 |
$i++; |
|
1357 |
}
|
|
1358 |
||
1359 |
$skip=<MYSQL_A>; # Get ok row (found already ok header) |
|
1360 |
||
1361 |
MySQLaccess::Debug::Print(2, "Array:"); |
|
1362 |
foreach $field (@Struct) { MySQLaccess::Debug::Print(2,"+ $field"); } |
|
1363 |
MySQLaccess::Debug::Print(2,"Hash:"); |
|
1364 |
foreach $field (keys(%Struct)) { MySQLaccess::Debug::Print(2,"+ $field -> $Struct{$field}"); } |
|
1365 |
||
1366 |
return (\%Struct,\@Struct); |
|
1367 |
}
|
|
1368 |
||
1369 |
# ===========================================================
|
|
1370 |
# sub Show_Tables():
|
|
1371 |
# return (a reference to) an array which holds all
|
|
1372 |
# known tables.
|
|
1373 |
# ===========================================================
|
|
1374 |
sub Show_Tables {
|
|
1375 |
my @Tables = (); |
|
1376 |
my $query = "show tables;select 'ok';\n"; |
|
1377 |
my $i=0; |
|
1378 |
my $line; |
|
1379 |
||
1380 |
MySQLaccess::Debug::Print(1,"Show_Tables():"); |
|
1381 |
MySQLaccess::Debug::Print(2,"SQL: $query"); |
|
1382 |
||
1383 |
print MYSQL_Q "$query"; |
|
1384 |
my $skip = <MYSQL_A>; #skip header |
|
1385 |
while (($line=<MYSQL_A>) ne "ok\n") |
|
1386 |
{
|
|
1387 |
chop($line); |
|
1388 |
push(@Tables,$line); #array |
|
1389 |
MySQLaccess::Debug::Print(3," ==> added table: $line"); |
|
1390 |
}
|
|
1391 |
||
1392 |
$skip=<MYSQL_A>; # Get ok row (found already ok header) |
|
1393 |
||
1394 |
MySQLaccess::Debug::Print(2, "Array:"); |
|
1395 |
foreach $tbl (@Tables) { MySQLaccess::Debug::Print(2,"+ $tbl"); } |
|
1396 |
||
1397 |
return @Tables; |
|
1398 |
}
|
|
1399 |
||
1400 |
# ======================================
|
|
1401 |
# sub Validate_Password($passwd,$host,$user,$encpw)
|
|
1402 |
# Validate the given password
|
|
1403 |
# for user '$user'
|
|
1404 |
# connecting from host '$host'
|
|
1405 |
# ======================================
|
|
1406 |
sub Validate_Password {
|
|
1407 |
my ($password,$host,$user,$encpw) = @_; |
|
1408 |
my $valid=0; |
|
1409 |
||
1410 |
MySQLaccess::Debug::Print(1,"Validate_Password($password,$host,$user,$encpw)"); |
|
1411 |
my $sql = "select host,user,password from user having " |
|
1412 |
."host='$host' and user='$user' and password='$encpw' " |
|
1413 |
."and password=PASSWORD('$password');\n"; |
|
1414 |
$sql .= "select 'ok';\n"; |
|
1415 |
MySQLaccess::Debug::Print(2,"SQL = $sql"); |
|
1416 |
print MYSQL_Q "$sql"; |
|
1417 |
||
1418 |
# if password is valid, at least 1 row returns before we read 'ok'
|
|
1419 |
while ( ($line=<MYSQL_A>) ne "ok\n") { |
|
1420 |
MySQLaccess::Debug::Print(2," A> $line"); |
|
1421 |
$valid = defined($line); |
|
1422 |
}
|
|
1423 |
my $skip = <MYSQL_A>; # read 'ok' |
|
1424 |
||
1425 |
return $valid; |
|
1426 |
}
|
|
1427 |
||
1428 |
||
1429 |
# ==========================================================
|
|
1430 |
# sub Sort_fields: (rewritten by psmith)
|
|
1431 |
# Build the query for an ordered list of entries
|
|
1432 |
# ==========================================================
|
|
1433 |
sub Sort_fields {
|
|
1434 |
my ($start, $end, $sofar, $this, @rest) = (@_); |
|
1435 |
my @where = ("((FIELD not like '\\%') AND (FIELD <> ''))", |
|
1436 |
"((FIELD like '%\\%%') OR (FIELD like '%\\_%'))",
|
|
1437 |
"(FIELD = '')"); |
|
1438 |
my $res = ''; |
|
1439 |
||
1440 |
$this or return ("$start $sofar $end"); |
|
1441 |
||
1442 |
$sofar .= ' AND ' if $sofar; |
|
1443 |
||
1444 |
foreach $w (@where) { |
|
1445 |
my $f = $w; |
|
1446 |
$f =~ s/FIELD/$this/g; |
|
1447 |
||
1448 |
$res .= Sort_fields($start, $end, "$sofar$f", @rest); |
|
1449 |
}
|
|
1450 |
||
1451 |
return ($res); |
|
1452 |
}
|
|
1453 |
||
1454 |
# ===========================================================
|
|
1455 |
# sub Sort_table: (rewritten by psmith)
|
|
1456 |
# return all entries in the given table,
|
|
1457 |
# in an ordered fashion
|
|
1458 |
# ===========================================================
|
|
1459 |
sub Sort_table {
|
|
1460 |
my ($tbl, @order) = @_; |
|
1461 |
my @res=(); |
|
1462 |
||
1463 |
# as long as there's no full where clause (Distrib 3.20)...
|
|
1464 |
# use having :-(
|
|
1465 |
# NOTE: this clause WILL NOT work on 3.21, because of the
|
|
1466 |
# order of 'ORDER BY' and 'HAVING'
|
|
1467 |
my $start = "SELECT *,UCASE(host) as ucase_host FROM $tbl "; |
|
1468 |
$start .= 'ORDER BY ' . join(',', @order) ." HAVING "; |
|
1469 |
my $end = ";\n"; |
|
1470 |
||
1471 |
# server version 3.21 has a full where clause :-)
|
|
1472 |
if ($MySQLaccess::Host::SERVER >= '3.21') { |
|
1473 |
# print "+++USING FULL WHERE CLAUSE+++\n";
|
|
1474 |
$start = "SELECT *,UCASE(host) as ucase_host FROM $tbl WHERE "; |
|
1475 |
$end = ' ORDER BY ' . join(',', @order) . ";\n"; |
|
1476 |
}
|
|
1477 |
||
1478 |
MySQLaccess::Debug::Print(1,"Sort_table():"); |
|
1479 |
MySQLaccess::Debug::Print(2,"Sorting table $tbl by `@order'"); |
|
1480 |
||
1481 |
my $tmp; |
|
1482 |
foreach $tmp (@order) |
|
1483 |
{
|
|
1484 |
$tmp="UCASE(host)" if ($tmp eq "ucase_host"); |
|
1485 |
}
|
|
1486 |
my $query = Sort_fields($start, $end, '', @order); |
|
1487 |
$query .= "select 'ok';\n"; |
|
1488 |
MySQLaccess::Debug::Print(2,"Query: $query"); |
|
1489 |
||
1490 |
print MYSQL_Q "$query\n"; |
|
1491 |
||
1492 |
my $delim = <MYSQL_A>; # read header |
|
1493 |
MySQLaccess::Debug::Print(3," A> $delim"); |
|
1494 |
if ($delim ne "ok\n") { |
|
1495 |
if ($delim =~ /^ERROR/) { |
|
1496 |
push(@MySQLaccess::Grant::Error,'use_old_server'); |
|
1497 |
MySQLaccess::Report::Print_Error_Messages() ; |
|
1498 |
exit 1; |
|
1499 |
}
|
|
1500 |
while (($line=<MYSQL_A>) ne "ok\n") |
|
1501 |
{
|
|
1502 |
MySQLaccess::Debug::Print(3," A> $line"); |
|
1503 |
push(@res,$line); |
|
1504 |
}
|
|
1505 |
}
|
|
1506 |
my $skip = <MYSQL_A>; # skip result 'ok' |
|
1507 |
||
1508 |
# remove columnheaders from output
|
|
1509 |
@res = grep(!/^\Q$delim\E$/, @res); |
|
1510 |
# remove trailing \n from each returned record
|
|
1511 |
chomp(@res); |
|
1512 |
# each record has 1 field to much : ucase_host
|
|
1513 |
@res = grep { /(.*)\t.*$/; $_ = $1; } @res; |
|
1514 |
||
1515 |
MySQLaccess::Debug::Print(2,"Result of sorted table $tbl:"); |
|
1516 |
foreach $line (@res) { MySQLaccess::Debug::Print(2," >>$line"); } |
|
1517 |
return @res; |
|
1518 |
}
|
|
1519 |
||
1520 |
# ===========================================================
|
|
1521 |
# sub Get_All_db(template):
|
|
1522 |
# return all db the grant-tables are working on,
|
|
1523 |
# which conform to the template
|
|
1524 |
# ===========================================================
|
|
1525 |
sub Get_All_dbs {
|
|
1526 |
my ($template,$tmp) = @_; |
|
1527 |
my @db=(); |
|
1528 |
my $aref; |
|
1529 |
||
1530 |
# working with temporary tables or production tables
|
|
1531 |
if (defined($tmp) and $tmp) { |
|
1532 |
$aref = \@MySQLaccess::Grant::sorted_db_tmp_table ; |
|
1533 |
}
|
|
1534 |
else { |
|
1535 |
$aref = \@MySQLaccess::Grant::sorted_db_table; |
|
1536 |
}
|
|
1537 |
||
1538 |
MySQLaccess::Debug::Print(1," template=[$template]"); |
|
1539 |
||
1540 |
# get all db for which access-rights can be calculated,
|
|
1541 |
# which conform to the template.
|
|
1542 |
# !! these db's don't have to exist yet, so it's not
|
|
1543 |
# enough to look which db already exist on the system
|
|
1544 |
$reg_expr = $template; |
|
1545 |
if ($template =~ /[\*\?]/) { |
|
1546 |
$reg_expr =~ tr/*?/%_/; |
|
1547 |
#$reg_expr = MySQLaccess::Wildcards::Wild2Reg($template);
|
|
1548 |
}
|
|
1549 |
$reg_expr = MySQLaccess::Wildcards::SQL2Reg("$reg_expr"); |
|
1550 |
||
1551 |
if ( ! ($template =~ /[\*\?%_]/) ) { |
|
1552 |
push(@db,$template); |
|
1553 |
return \@db; |
|
1554 |
}
|
|
1555 |
||
1556 |
MySQLaccess::Debug::Print(2,"#Reading db-table..."); |
|
1557 |
foreach $record (@{$aref}) { #MySQLaccess::Grant::sorted_db_table) { |
|
1558 |
my @record=split(/\t/,$record); |
|
1559 |
my $db = $record[1]; |
|
1560 |
MySQLaccess::Debug::Print(2,"> $db "); |
|
1561 |
if ( (!grep(/$db/i,@db)) and ($db =~/$reg_expr/i) ) { |
|
1562 |
push(@db,$db); |
|
1563 |
MySQLaccess::Debug::Print(2,"added"); |
|
1564 |
}
|
|
1565 |
else { |
|
1566 |
MySQLaccess::Debug::Print(2,"skipped"); |
|
1567 |
}
|
|
1568 |
}
|
|
1569 |
# if no rule is found for a certain db in the db-table,
|
|
1570 |
# the rights of the user are used, so we should inform
|
|
1571 |
# the user for
|
|
1572 |
if (!grep(/^%$/,@db)) { push(@db,"$MySQLaccess::NEW_DB"); } |
|
1573 |
return \@db; |
|
1574 |
}
|
|
1575 |
||
1576 |
# ===========================================================
|
|
1577 |
# sub Get_All_users(template):
|
|
1578 |
# return all users the grant-tables are working on,
|
|
1579 |
# which conform to the template
|
|
1580 |
# ===========================================================
|
|
1581 |
sub Get_All_users {
|
|
1582 |
($template,$tmp) = @_; # nog verder uitwerken!!! |
|
1583 |
my @user=(); |
|
1584 |
my $aref; |
|
1585 |
||
1586 |
# working with temporary tables or production tables
|
|
1587 |
if (defined($tmp) and $tmp) { |
|
1588 |
$aref = \@MySQLaccess::Grant::sorted_user_tmp_table ; |
|
1589 |
}
|
|
1590 |
else { |
|
1591 |
$aref = \@MySQLaccess::Grant::sorted_user_table; |
|
1592 |
}
|
|
1593 |
||
1594 |
MySQLaccess::Debug::Print(1,"Debug Get_All_users:"); |
|
1595 |
# get all db for which access-rights can be calculated.
|
|
1596 |
# !! these db's don't have to exist yet, so it's not
|
|
1597 |
# enough to look which db already exist on the system
|
|
1598 |
$reg_expr = $template; |
|
1599 |
if ($template =~ /[\*\?]/) { |
|
1600 |
$reg_expr =~ tr/*?/%_/; |
|
1601 |
#$reg_expr = MySQLaccess::Wildcards::Wild2Reg($template);
|
|
1602 |
}
|
|
1603 |
$reg_expr = MySQLaccess::Wildcards::SQL2Reg("$reg_expr"); |
|
1604 |
||
1605 |
if ( ! ($template =~ /[\*\?%_]/) ) { |
|
1606 |
push(@user,$template); |
|
1607 |
return \@user; |
|
1608 |
}
|
|
1609 |
||
1610 |
MySQLaccess::Debug::Print(2,"#Reading user-table..."); |
|
1611 |
foreach $record (@{$aref}) { #MySQLaccess::Grant::sorted_user_table) { |
|
1612 |
my @record=split(/\t/,$record); |
|
1613 |
my $user = $record[1]; |
|
1614 |
MySQLaccess::Debug::Print(2,"> $user "); |
|
1615 |
if ( (!grep(/$user/,@user)) and ($user=~/$reg_expr/)) { |
|
1616 |
push(@user,$user); |
|
1617 |
MySQLaccess::Debug::Print(2, "added"); |
|
1618 |
}
|
|
1619 |
else { |
|
1620 |
MySQLaccess::Debug::Print(2, "skipped"); |
|
1621 |
}
|
|
1622 |
}
|
|
1623 |
# Any user means also:
|
|
1624 |
# - the 'empty' user, ie without supplying a username
|
|
1625 |
# - any user still to be defined/created
|
|
1626 |
#push(@user,''); #without_suplying_a_username
|
|
1627 |
push(@user,"$MySQLaccess::NEW_USER"); |
|
1628 |
#push(@Warnings,'minimum_priv');
|
|
1629 |
return \@user; |
|
1630 |
}
|
|
1631 |
||
1632 |
# ===========================================================
|
|
1633 |
# sub Get_All_hosts(template):
|
|
1634 |
# return all hosts the grant-tables are working on,
|
|
1635 |
# which conform to the template
|
|
1636 |
# ===========================================================
|
|
1637 |
sub Get_All_hosts {
|
|
1638 |
my ($template,$tmp) = @_; |
|
1639 |
my @host=(); |
|
1640 |
my $aref; |
|
1641 |
my $aref1; |
|
1642 |
||
1643 |
# working with temporary tables or production tables
|
|
1644 |
if (defined($tmp) and $tmp) { |
|
1645 |
$aref = \@MySQLaccess::Grant::sorted_host_tmp_table ; |
|
1646 |
$aref1= \@MySQLaccess::Grant::sorted_db_tmp_table ; |
|
1647 |
}
|
|
1648 |
else { |
|
1649 |
$aref = \@MySQLaccess::Grant::sorted_host_table; |
|
1650 |
$aref1= \@MySQLaccess::Grant::sorted_db_table ; |
|
1651 |
}
|
|
1652 |
||
1653 |
MySQLaccess::Debug::Print(1, "Debug Get_All_hosts:"); |
|
1654 |
# get all db for which access-rights can be calculated.
|
|
1655 |
# !! these db's don't have to exist yet, so it's not
|
|
1656 |
# enough to look which db already exist on the system
|
|
1657 |
$reg_expr = $template; |
|
1658 |
if ($template =~ /[\*\?]/) { |
|
1659 |
$reg_expr =~ tr/*?/%_/; |
|
1660 |
#$reg_expr = MySQLaccess::Wildcards::Wild2Reg($template);
|
|
1661 |
}
|
|
1662 |
$reg_expr = MySQLaccess::Wildcards::SQL2Reg("$reg_expr"); |
|
1663 |
||
1664 |
if ( ! ($template =~ /[\*\?%_]/) ) { |
|
1665 |
push(@host,$template); |
|
1666 |
return \@host; |
|
1667 |
}
|
|
1668 |
||
1669 |
MySQLaccess::Debug::Print(1, "#Reading db-table..."); |
|
1670 |
foreach $record (@{$aref1}) { #MySQLaccess::Grant::sorted_db_table) { |
|
1671 |
my @record=split(/\t/,$record); |
|
1672 |
my $host = $record[0]; |
|
1673 |
MySQLaccess::Debug::Print(2, "> $host "); |
|
1674 |
if (! grep(/$host/i,@host)) { |
|
1675 |
push(@host,$host); |
|
1676 |
MySQLaccess::Debug::Print(2, "added"); |
|
1677 |
}
|
|
1678 |
else { |
|
1679 |
MySQLaccess::Debug::Print(2, "skipped"); |
|
1680 |
}
|
|
1681 |
}
|
|
1682 |
MySQLaccess::Debug::Print(1, "#Reading host-table..."); |
|
1683 |
foreach $record (@{$aref}) { |
|
1684 |
my @record=split(/\t/,$record); |
|
1685 |
my $host = $record[0]; |
|
1686 |
MySQLaccess::Debug::Print(2, "> $host "); |
|
1687 |
if ( (!grep(/$host/,@host)) and ($host=~/$reg_expr/)) { |
|
1688 |
push(@host,$host); |
|
1689 |
MySQLaccess::Debug::Print(2, "added"); |
|
1690 |
}
|
|
1691 |
else { |
|
1692 |
MySQLaccess::Debug::Print(2, "skipped"); |
|
1693 |
}
|
|
1694 |
}
|
|
1695 |
# DOUBT:
|
|
1696 |
#print "#Reading user-table...\n" if ($DEBUG>1);
|
|
1697 |
#foreach $record (@MySQLaccess::Grant::sorted_user_table) {
|
|
1698 |
# my @record=split(/\t/,$record);
|
|
1699 |
# my $host = $record[0];
|
|
1700 |
# print "> $host " if ($DEBUG>2);
|
|
1701 |
# if ( (!grep(/$host/,@host)) and ($host=~/$reg_expr/)) {
|
|
1702 |
# push(@host,$host);
|
|
1703 |
# print "added\n" if ($DEBUG>2);
|
|
1704 |
# }
|
|
1705 |
# else {
|
|
1706 |
# print "skipped\n" if ($DEBUG>2);
|
|
1707 |
# }
|
|
1708 |
#}
|
|
1709 |
# Any host also means:
|
|
1710 |
# - any host still to be defined/created
|
|
1711 |
#push(@host,"any_other_host");
|
|
1712 |
||
1713 |
@host = sort(@host); |
|
1714 |
return \@host; |
|
1715 |
}
|
|
1716 |
||
1717 |
||
1718 |
##########################################################################
|
|
1719 |
package MySQLaccess::Grant;
|
|
1720 |
##############
|
|
1721 |
BEGIN {
|
|
1722 |
$DEBUG = 0; |
|
1723 |
$DEBUG = $MySQLaccess::DEBUG unless ($DEBUG); |
|
1724 |
}
|
|
1725 |
||
1726 |
||
1727 |
||
1728 |
# ===========================================================
|
|
1729 |
# sub Diff_Privileges()
|
|
1730 |
# Calculate diff between temporary and original grant-tables
|
|
1731 |
# ===========================================================
|
|
1732 |
sub Diff_Privileges {
|
|
1733 |
my @before=(); |
|
1734 |
my @after =(); |
|
1735 |
my @diffs =(); |
|
1736 |
||
1737 |
# -----------------------------
|
|
1738 |
# Build list of users,dbs,hosts
|
|
1739 |
# to process...
|
|
1740 |
my @all_dbs = @{MySQLaccess::DB::Get_All_dbs('*')}; |
|
1741 |
my @all_users = @{MySQLaccess::DB::Get_All_users('*')}; |
|
1742 |
my @all_hosts = @{MySQLaccess::DB::Get_All_hosts('*')}; |
|
1743 |
#if EDIT-mode
|
|
1744 |
my @all_dbs_tmp = @{MySQLaccess::DB::Get_All_dbs('*','tmp')}; |
|
1745 |
my @all_users_tmp = @{MySQLaccess::DB::Get_All_users('*','tmp')}; |
|
1746 |
my @all_hosts_tmp = @{MySQLaccess::DB::Get_All_hosts('*','tmp')}; |
|
1747 |
||
1748 |
||
1749 |
my %Access;
|
|
1750 |
# ------------------------------------
|
|
1751 |
# Build list of priv. for grant-tables
|
|
1752 |
foreach $host (@all_hosts) { |
|
1753 |
foreach $user (@all_users) { |
|
1754 |
foreach $db (@all_dbs) { |
|
1755 |
MySQLaccess::Grant::Initialize(); |
|
1756 |
%Access = MySQLaccess::Grant::Get_Access_Rights($host,$user,$db); |
|
1757 |
push(@before,MySQLaccess::Report::Raw_Report($host,$user,$db,\%Access)); |
|
1758 |
}
|
|
1759 |
}
|
|
1760 |
}
|
|
1761 |
||
1762 |
# ----------------------------------
|
|
1763 |
# Build list of priv. for tmp-tables
|
|
1764 |
foreach $host (@all_hosts_tmp) { |
|
1765 |
foreach $user (@all_users_tmp) { |
|
1766 |
foreach $db (@all_dbs_tmp) { |
|
1767 |
MySQLaccess::Grant::Initialize('tmp'); |
|
1768 |
%Access = MySQLaccess::Grant::Get_Access_Rights($host,$user,$db,'tmp'); |
|
1769 |
push(@after,MySQLaccess::Report::Raw_Report($host,$user,$db,\%Access)); |
|
1770 |
}
|
|
1771 |
}
|
|
1772 |
}
|
|
1773 |
||
1774 |
# ----------------------------------
|
|
1775 |
# Write results to temp-file to make
|
|
1776 |
# DIFF
|
|
1777 |
@before = sort(@before); |
|
1778 |
@after = sort(@after); |
|
1779 |
||
1780 |
($hb, $before) = tempfile("$MySQLaccess::script.XXXXXX") or |
|
1781 |
push(@MySQLaccess::Report::Errors,"Can't create temporary file: $!"); |
|
1782 |
($ha, $after) = tempfile("$MySQLaccess::script.XXXXXX") or |
|
1783 |
push(@MySQLaccess::Report::Errors,"Can't create temporary file: $!"); |
|
1784 |
||
1785 |
print $hb join("\n",@before); |
|
1786 |
print $ha join("\n",@after); |
|
1787 |
close $hb; |
|
1788 |
close $ha; |
|
1789 |
||
1790 |
# ----------------------------------
|
|
1791 |
# compute difference
|
|
1792 |
my $cmd="$MySQLaccess::DIFF $before $after |"; |
|
1793 |
open(DIFF,"$cmd"); |
|
1794 |
@diffs = <DIFF>; |
|
1795 |
@diffs = grep(/[<>]/,@diffs); |
|
1796 |
chomp(@diffs); |
|
1797 |
close(DIFF); |
|
1798 |
||
1799 |
# ----------------------------------
|
|
1800 |
# cleanup temp. files
|
|
1801 |
unlink($before); |
|
1802 |
unlink($after); |
|
1803 |
||
1804 |
return \@diffs; |
|
1805 |
}
|
|
1806 |
||
1807 |
# ===========================================================
|
|
1808 |
# sub Initialize()
|
|
1809 |
#
|
|
1810 |
# ===========================================================
|
|
1811 |
sub Initialize {
|
|
1812 |
%MySQLaccess::Grant::Access = %{Default_Access_Rights()}; |
|
1813 |
@MySQLaccess::Grant::Errors = (); |
|
1814 |
@MySQLaccess::Grant::Warnings = (); |
|
1815 |
@MySQLaccess::Grant::Notes = (); |
|
1816 |
# -----
|
|
1817 |
# rules
|
|
1818 |
$MySQLaccess::Grant::Rules{'user'} = 'no_rule_found'; |
|
1819 |
$MySQLaccess::Grant::Rules{'db'} = 'no_rule_found'; |
|
1820 |
$MySQLaccess::Grant::Rules{'host'} = 'no_equiv_host'; |
|
1821 |
$MySQLaccess::Grant::full_access = 1; |
|
1822 |
||
1823 |
$MySQLaccess::Grant::process_host_table = 0; |
|
1824 |
return 1; |
|
1825 |
}
|
|
1826 |
||
1827 |
# ===========================================================
|
|
1828 |
# sub ReadTables()
|
|
1829 |
#
|
|
1830 |
# ===========================================================
|
|
1831 |
sub ReadTables {
|
|
1832 |
my ($tmp) = @_; |
|
1833 |
my ($HOST,$DB,$USER); |
|
1834 |
my @tables;
|
|
1835 |
||
1836 |
# build list of available tables
|
|
1837 |
@tables = MySQLaccess::DB::Show_Tables(); |
|
1838 |
||
1839 |
# reading production grant-tables or temporary tables?
|
|
1840 |
$tmp = (defined($tmp) and $tmp) ? 1 : 0; |
|
1841 |
if ($tmp) { #reading temporary tables |
|
1842 |
$HOST=$MySQLaccess::ACCESS_H_TMP; |
|
1843 |
$DB =$MySQLaccess::ACCESS_D_TMP; |
|
1844 |
$USER=$MySQLaccess::ACCESS_U_TMP; |
|
1845 |
||
1846 |
# ----------------------------
|
|
1847 |
# do tables exist?
|
|
1848 |
if (!grep(/$HOST/,@tables)) { MySQLaccess::DB::CreateTable($HOST); } |
|
1849 |
if (!grep(/$USER/,@tables)) { MySQLaccess::DB::CreateTable($USER); } |
|
1850 |
if (!grep(/$DB/,@tables)) { MySQLaccess::DB::CreateTable($DB); } |
|
1851 |
||
1852 |
MySQLaccess::Debug::Print(1,"Finding fields in tmp-ACL files:"); |
|
1853 |
# -----------------------------
|
|
1854 |
# Get record-layout
|
|
1855 |
my ($h1,$h2) = MySQLaccess::DB::Show_Fields($HOST); |
|
1856 |
my ($d1,$d2) = MySQLaccess::DB::Show_Fields($DB); |
|
1857 |
my ($u1,$u2) = MySQLaccess::DB::Show_Fields($USER); |
|
1858 |
%MySQLaccess::Grant::H_tmp = %{$h1}; @MySQLaccess::Grant::H_tmp = @{$h2}; |
|
1859 |
%MySQLaccess::Grant::D_tmp = %{$d1}; @MySQLaccess::Grant::D_tmp = @{$d2}; |
|
1860 |
%MySQLaccess::Grant::U_tmp = %{$u1}; @MySQLaccess::Grant::U_tmp = @{$u2}; |
|
1861 |
||
1862 |
# @MySQLaccess::Grant::Privileges_tmp=@{Make_Privlist()};
|
|
1863 |
#
|
|
1864 |
MySQLaccess::Debug::Print(1, "Reading sorted temp-tables:"); |
|
1865 |
@MySQLaccess::Grant::sorted_db_tmp_table = MySQLaccess::DB::Sort_table($DB, 'ucase_host', 'user', 'db'); |
|
1866 |
@MySQLaccess::Grant::sorted_host_tmp_table= MySQLaccess::DB::Sort_table($HOST, 'ucase_host', 'db'); |
|
1867 |
@MySQLaccess::Grant::sorted_user_tmp_table= defined($MySQLaccess::Param{'password'}) ? |
|
1868 |
MySQLaccess::DB::Sort_table($USER, 'ucase_host', 'user', 'password'): |
|
1869 |
MySQLaccess::DB::Sort_table($USER, 'ucase_host', 'user'); |
|
1870 |
}
|
|
1871 |
else { #reading production grant-tables |
|
1872 |
$HOST=$MySQLaccess::ACCESS_H; |
|
1873 |
$DB =$MySQLaccess::ACCESS_D; |
|
1874 |
$USER=$MySQLaccess::ACCESS_U; |
|
1875 |
||
1876 |
MySQLaccess::Debug::Print(1,"Finding fields in ACL files:"); |
|
1877 |
# -----------------------------
|
|
1878 |
# Get record-layout
|
|
1879 |
my ($h1,$h2) = MySQLaccess::DB::Show_Fields($HOST); |
|
1880 |
my ($d1,$d2) = MySQLaccess::DB::Show_Fields($DB); |
|
1881 |
my ($u1,$u2) = MySQLaccess::DB::Show_Fields($USER); |
|
1882 |
%MySQLaccess::Grant::H = %{$h1}; @MySQLaccess::Grant::H = @{$h2}; |
|
1883 |
%MySQLaccess::Grant::D = %{$d1}; @MySQLaccess::Grant::D = @{$d2}; |
|
1884 |
%MySQLaccess::Grant::U = %{$u1}; @MySQLaccess::Grant::U = @{$u2}; |
|
1885 |
||
1886 |
@MySQLaccess::Grant::Privileges=@{Make_Privlist()}; |
|
1887 |
||
1888 |
MySQLaccess::Debug::Print(1, "Reading sorted tables:"); |
|
1889 |
@MySQLaccess::Grant::sorted_db_table = MySQLaccess::DB::Sort_table($DB, 'ucase_host', 'user', 'db'); |
|
1890 |
@MySQLaccess::Grant::sorted_host_table= MySQLaccess::DB::Sort_table($HOST, 'ucase_host', 'db'); |
|
1891 |
@MySQLaccess::Grant::sorted_user_table= defined($MySQLaccess::Param{'password'}) ? |
|
1892 |
MySQLaccess::DB::Sort_table($USER, 'ucase_host', 'user', 'password'): |
|
1893 |
MySQLaccess::DB::Sort_table($USER, 'ucase_host', 'user'); |
|
1894 |
}
|
|
1895 |
||
1896 |
return 0; |
|
1897 |
}
|
|
1898 |
||
1899 |
# ===========================================================
|
|
1900 |
# sub Get_Access_Rights(host,user,db)
|
|
1901 |
# report the access_rights for the tuple ($host,$user,$db).
|
|
1902 |
# ===========================================================
|
|
1903 |
sub Get_Access_Rights {
|
|
1904 |
local ($host,$user,$db,$tmp) = @_; |
|
1905 |
||
1906 |
my $aref_user; |
|
1907 |
my $aref_host; |
|
1908 |
my $aref_db; |
|
1909 |
# working with temporary tables or production tables
|
|
1910 |
if (defined($tmp) and $tmp) { |
|
1911 |
$aref_user = \@MySQLaccess::Grant::sorted_user_tmp_table; |
|
1912 |
$aref_host = \@MySQLaccess::Grant::sorted_host_tmp_table; |
|
1913 |
$aref_db = \@MySQLaccess::Grant::sorted_db_tmp_table; |
|
1914 |
}
|
|
1915 |
else { |
|
1916 |
$aref_user = \@MySQLaccess::Grant::sorted_user_table; |
|
1917 |
$aref_host = \@MySQLaccess::Grant::sorted_host_table; |
|
1918 |
$aref_db = \@MySQLaccess::Grant::sorted_db_table; |
|
1919 |
}
|
|
1920 |
||
1921 |
||
1922 |
my ($refrecord,$refgrant); |
|
1923 |
my ($_host_,$_user_,$encpw_); |
|
1924 |
my %_Access_;
|
|
1925 |
||
1926 |
MySQLaccess::Debug::Print(1, "for ($host,$user,$db):"); |
|
1927 |
||
1928 |
# ******************************************************************************
|
|
1929 |
# Create default access-rights
|
|
1930 |
# default access-rights are no access at all!!
|
|
1931 |
||
1932 |
||
1933 |
# ******************************************************************************
|
|
1934 |
# get hostname for IP-address
|
|
1935 |
# get IP-address for hostname
|
|
1936 |
local $host_name = MySQLaccess::Host::IP2Name($host); |
|
1937 |
local $host_ip = MySQLaccess::Host::Name2IP($host); |
|
1938 |
||
1939 |
MySQLaccess::Debug::Print(3,"host=$host, hostname=$host_name, host-ip =$host_ip"); |
|
1940 |
MySQLaccess::Debug::Print(3,"user=$user"); |
|
1941 |
MySQLaccess::Debug::Print(3,"db =$db"); |
|
1942 |
||
1943 |
# ***********************************************************************
|
|
1944 |
# retrieve information on USER
|
|
1945 |
# check all records in mysql::user for matches with the tuple (host,user)
|
|
1946 |
# ***********************************************************************
|
|
1947 |
# 4.OR (add) the privileges for the user from the "user" table.
|
|
1948 |
# (add all privileges which is "Y" in "user")
|
|
1949 |
($refrecord,$refgrant) = Get_grant_from_user($host,$user,$aref_user); |
|
1950 |
($_host_,$_user_,$encpw_) = @{$refrecord}; |
|
1951 |
%_access_ = %{$refgrant}; |
|
1952 |
||
1953 |
foreach $field (keys(%U)) { ##only priv. set in user-table |
|
1954 |
$MySQLaccess::Grant::Access{$field} = ($MySQLaccess::Grant::Access{$field} or $_access_{$field}); |
|
1955 |
}
|
|
1956 |
||
1957 |
if ($_user_ eq $MySQLaccess::NEW_USER) { |
|
1958 |
push(@Warnings,'minimum_priv'); |
|
1959 |
}
|
|
1960 |
if ($_user_ ne $user) { |
|
1961 |
$user=$_user_; |
|
1962 |
push(@Warnings,'anonymous_access'); |
|
1963 |
}
|
|
1964 |
||
1965 |
# *******************************************************
|
|
1966 |
# Validate password if this has been asked to do
|
|
1967 |
# *******************************************************
|
|
1968 |
if (defined($password)) { |
|
1969 |
$valid = Validate_Password($password,$_host_,$_user_,$_encpw_,$aref_user); |
|
1970 |
if (!$valid) { push(@Errors,'invalid_password'); } |
|
1971 |
else { push(@Notes,'valid_password'); } |
|
1972 |
}
|
|
1973 |
||
1974 |
# ******************************************************************************
|
|
1975 |
# retrieve information on DB
|
|
1976 |
# check all records in mysql::db for matches with the triple (host,db,user)
|
|
1977 |
# first match is used.
|
|
1978 |
# ******************************************************************************
|
|
1979 |
# 2.Get grant for user from the "db" table.
|
|
1980 |
||
1981 |
($refrecord,$refgrant)=Get_grant_from_db($host,$db,$user,$aref_db); #set process_host_table |
|
1982 |
($_host_,$_user_,$encpw_) = @{$refrecord}; |
|
1983 |
%_access_ = %{$refgrant}; |
|
1984 |
||
1985 |
foreach $field (keys(%D)) { ##only priv. set in db-table |
|
1986 |
$MySQLaccess::Grant::Access{$field} = ($MySQLaccess::Grant::Access{$field} or $_access_{$field}); |
|
1987 |
}
|
|
1988 |
||
1989 |
# ***********************************************************************
|
|
1990 |
# retrieve information on HOST
|
|
1991 |
# check all records in mysql::host for matches with the tuple (host,db)
|
|
1992 |
#
|
|
1993 |
# ' The host table is mainly to maintain a list of "secure" servers. '
|
|
1994 |
# ***********************************************************************
|
|
1995 |
# 3.If hostname is "empty" for the found entry, AND the privileges with
|
|
1996 |
# the privileges for the host in "host" table.
|
|
1997 |
# (Remove all which is not "Y" in both)
|
|
1998 |
||
1999 |
if ($MySQLaccess::Grant::process_host_table) { |
|
2000 |
($refrecord,$refgrant)=Get_grant_from_host($host,$db,$aref_host); |
|
2001 |
($_host_,$_user_,$encpw_) = @{$refrecord}; |
|
2002 |
%_access_ = %{$refgrant}; |
|
2003 |
||
2004 |
foreach $field (keys(%H)) { ##only priv. set in host-table |
|
2005 |
$MySQLaccess::Grant::Access{$field} = ($MySQLaccess::Grant::Access{$field} and $_access_{$field}); |
|
2006 |
}
|
|
2007 |
}
|
|
2008 |
||
2009 |
MySQLaccess::Debug::Print(1,"done for ($host,$user,$db)"); |
|
2010 |
return %MySQLaccess::Grant::Access; |
|
2011 |
}
|
|
2012 |
||
2013 |
# ####################################
|
|
2014 |
# FINDING THE RIGHT GRANT-RULE
|
|
2015 |
# ==========================================================
|
|
2016 |
# sub Get_grant_from_user:
|
|
2017 |
# ==========================================================
|
|
2018 |
sub Get_grant_from_user {
|
|
2019 |
my ($host,$user,$aref) = @_; |
|
2020 |
||
2021 |
MySQLaccess::Debug::Print(1, ""); |
|
2022 |
MySQLaccess::Debug::Print(1, "(host=$host,user=$user)"); |
|
2023 |
||
2024 |
my %Access_user = %{Default_Access_Rights()}; |
|
2025 |
||
2026 |
my $rule_found=0; |
|
2027 |
my @record = (); |
|
2028 |
my $record; |
|
2029 |
||
2030 |
foreach $record (@{$aref}) { |
|
2031 |
$MySQLaccess::Grant::full_access=0; |
|
2032 |
MySQLaccess::Debug::Print(3, "Record= $record"); |
|
2033 |
@record=split(/\t/,$record); |
|
2034 |
||
2035 |
# check host and db
|
|
2036 |
# with possible wildcards in field
|
|
2037 |
# replace mysql-wildcards by reg-wildcards
|
|
2038 |
my $host_tpl = MySQLaccess::Wildcards::SQL2Reg($record[0]); |
|
2039 |
my $user_tpl = $record[1]; #user field isn't pattern-matched!! |
|
2040 |
my $passwd = $record[2]; |
|
2041 |
||
2042 |
MySQLaccess::Debug::Print(3, "=>host_tpl : read=$record[0] -> converted=$host_tpl"); |
|
2043 |
MySQLaccess::Debug::Print(3, "=>user_tpl : read=$record[1] -> $user_tpl"); |
|
2044 |
MySQLaccess::Debug::Print(3, "=>password : read=$record[2] -> $passwd"); |
|
2045 |
||
2046 |
||
2047 |
if ( MySQLaccess::Host::MatchTemplate($host,$host_tpl) and |
|
2048 |
MySQLaccess::Wildcards::MatchTemplate($user_tpl,$user) |
|
2049 |
)
|
|
2050 |
{
|
|
2051 |
MySQLaccess::Debug::Print(2, "FOUND!!"); |
|
2052 |
if ($passwd eq '') { push(@Warnings,'insecure_user'); } |
|
2053 |
else { push(@Notes,'password_required'); } |
|
2054 |
||
2055 |
foreach $field (keys(%U)) { |
|
2056 |
$Access_user{$field} = $MySQLaccess::Report::Answer{$record[$U{$field}]}; |
|
2057 |
}
|
|
2058 |
#print "\n" if $DEBUG;
|
|
2059 |
$MySQLaccess::Grant::Rules{'user'} = $record; |
|
2060 |
$rule_found=1; |
|
2061 |
last;
|
|
2062 |
}
|
|
2063 |
}
|
|
2064 |
||
2065 |
# -------------------------------
|
|
2066 |
# setting privileges to user-priv
|
|
2067 |
MySQLaccess::Debug::Print(2, "Rights after parsing user-table..:"); |
|
2068 |
if (! $rule_found ) { |
|
2069 |
@record=(); |
|
2070 |
MySQLaccess::Debug::Print(2, "NO record found in the user-table!!"); |
|
2071 |
}
|
|
2072 |
else { |
|
2073 |
MySQLaccess::Debug::Print(2, "Selected record=@record"); |
|
2074 |
MySQLaccess::Debug::Print(2, "<=?=> $record"); |
|
2075 |
}
|
|
2076 |
||
2077 |
MySQLaccess::Debug::Print(1, "returning @record"); |
|
2078 |
||
2079 |
return (\@record,\%Access_user); #matching record in user-table |
|
2080 |
}
|
|
2081 |
||
2082 |
# ==========================================================
|
|
2083 |
# sub Get_grant_from_db:
|
|
2084 |
# ==========================================================
|
|
2085 |
sub Get_grant_from_db {
|
|
2086 |
my ($host,$db,$user,$aref) = @_; |
|
2087 |
||
2088 |
MySQLaccess::Debug::Print(1, "(host=$host,user=$user,db=$db)"); |
|
2089 |
||
2090 |
my %Access_db = %{Default_Access_Rights()}; |
|
2091 |
my $rule_found=0; |
|
2092 |
||
2093 |
foreach $record (@{$aref}) { |
|
2094 |
$full_access=0; |
|
2095 |
MySQLaccess::Debug::Print(2, "Read db: $record"); |
|
2096 |
@record=split(/\t/,$record); |
|
2097 |
||
2098 |
# check host and db
|
|
2099 |
# with possible wildcards in field
|
|
2100 |
# replace mysql-wildcards by reg-wildcards
|
|
2101 |
my $host_tpl = MySQLaccess::Wildcards::SQL2Reg($record[0]); |
|
2102 |
my $db_tpl = MySQLaccess::Wildcards::SQL2Reg($record[1]); |
|
2103 |
my $user_tpl = $record[2]; #user field isn't pattern matched!! |
|
2104 |
MySQLaccess::Debug::Print(3, "=>host_tpl : read=$record[0] -> converted=$host_tpl"); |
|
2105 |
MySQLaccess::Debug::Print(3, "=>db_tpl : read=$record[1] -> $db_tpl"); |
|
2106 |
MySQLaccess::Debug::Print(3, "=>user_tpl : read=$record[2] -> $user_tpl"); |
|
2107 |
||
2108 |
if ( ( MySQLaccess::Host::Is_localhost($host_tpl) |
|
2109 |
or MySQLaccess::Wildcards::MatchTemplate($host_tpl,$host_name) |
|
2110 |
or MySQLaccess::Wildcards::MatchTemplate($host_tpl,$host_ip) ) |
|
2111 |
and ( MySQLaccess::Wildcards::MatchTemplate($db_tpl,$db) ) |
|
2112 |
and ( MySQLaccess::Wildcards::MatchTemplate($user_tpl,$user) ) ) { |
|
2113 |
||
2114 |
$MySQLaccess::Grant::process_host_table = ($record[0] eq ''); |
|
2115 |
||
2116 |
if ($user_tpl eq '') { push(@Warnings,'public_database'); } |
|
2117 |
||
2118 |
foreach $field (keys(%D)) { |
|
2119 |
$Access_db{$field} = $MySQLaccess::Report::Answer{$record[$D{$field}]}; |
|
2120 |
}
|
|
2121 |
$rule_found=1; |
|
2122 |
$MySQLaccess::Grant::Rules{'db'} = $record; |
|
2123 |
last;
|
|
2124 |
}
|
|
2125 |
}
|
|
2126 |
||
2127 |
# -------------------------------
|
|
2128 |
# setting privileges to db-priv
|
|
2129 |
MySQLaccess::Debug::Print(2, "Rights after parsing db-table..:"); |
|
2130 |
if (! $rule_found ) { |
|
2131 |
MySQLaccess::Debug::Print(2, "NO rule found in db-table => no access granted!!"); |
|
2132 |
}
|
|
2133 |
||
2134 |
return (\@record,\%Access_db); |
|
2135 |
}
|
|
2136 |
||
2137 |
# ==========================================================
|
|
2138 |
# sub Get_grant_from_host:
|
|
2139 |
# ==========================================================
|
|
2140 |
sub Get_grant_from_host {
|
|
2141 |
my ($host,$db,$aref) = @_; |
|
2142 |
||
2143 |
MySQLaccess::Debug::Print(1, "Get_grant_from_host()"); |
|
2144 |
||
2145 |
my %Access_host = %{Default_Access_Rights()}; |
|
2146 |
||
2147 |
# the host-table doesn't have to be processed if the host-field
|
|
2148 |
# in the db-table isn't empty
|
|
2149 |
if (!$MySQLaccess::Grant::process_host_table) { |
|
2150 |
MySQLaccess::Debug::Print(2, ">> Host-table doesn't have to be processed!!"); |
|
2151 |
$MySQLaccess::Grant::Rules{'host'} = 'no_equiv_host'; |
|
2152 |
return ([],\%Access_host); |
|
2153 |
}
|
|
2154 |
||
2155 |
my $rule_found=0; |
|
2156 |
my @record = (); |
|
2157 |
||
2158 |
foreach $record (@{$aref}) { |
|
2159 |
$full_access=0; |
|
2160 |
MySQLaccess::Debug::Print(2, "host: $record"); |
|
2161 |
@record=split(/\t/,$record); |
|
2162 |
||
2163 |
# check host and db
|
|
2164 |
# with possible wildcards in field
|
|
2165 |
# replace mysql-wildcards by reg-wildcards
|
|
2166 |
my $host_tpl = MySQLaccess::Wildcards::SQL2Reg($record[0]); |
|
2167 |
my $db_tpl = MySQLaccess::Wildcards::SQL2Reg($record[1]); |
|
2168 |
MySQLaccess::Debug::Print(3, "=>host_tpl : $record[0] -> $host_tpl"); |
|
2169 |
MySQLaccess::Debug::Print(3, "=>db_tpl : $record[1] -> $db_tpl"); |
|
2170 |
||
2171 |
if ( ( MySQLaccess::Host::Is_localhost($host_tpl) |
|
2172 |
or MySQLaccess::Wildcards::MatchTemplate($host_tpl,$host_name) |
|
2173 |
or MySQLaccess::Wildcards::MatchTemplate($host_tpl,$host_ip) ) |
|
2174 |
and ( MySQLaccess::Wildcards::MatchTemplate($db_tpl,$db) ) ) { |
|
2175 |
||
2176 |
$MySQLaccess::Grant::Rules{'host'} = $record; |
|
2177 |
$rule_found=1; |
|
2178 |
foreach $field (keys(%H)) { |
|
2179 |
$Access_host{$field} = $MySQLaccess::Report::Answer{$record[$H{$field}]}; |
|
2180 |
}
|
|
2181 |
last;
|
|
2182 |
}
|
|
2183 |
}
|
|
2184 |
||
2185 |
# -------------------------------
|
|
2186 |
# setting privileges to host-priv
|
|
2187 |
MySQLaccess::Debug::Print(2, "Rights after parsing host-table..:"); |
|
2188 |
if (! $rule_found ) { |
|
2189 |
@record=(); |
|
2190 |
MySQLaccess::Debug::Print(2, "NO restrictions found in the host-table!!"); |
|
2191 |
}
|
|
2192 |
||
2193 |
# --------------------------------
|
|
2194 |
# debugging access-rights in db
|
|
2195 |
||
2196 |
return (\@record,\%Access_host); #matching record in host-table |
|
2197 |
}
|
|
2198 |
||
2199 |
||
2200 |
||
2201 |
# ===========================================================
|
|
2202 |
# sub Default_Access_Rights():
|
|
2203 |
# return (a reference to) a hash which holds all default
|
|
2204 |
# priviliges currently defined in the grant-tables.
|
|
2205 |
# ===========================================================
|
|
2206 |
sub Default_Access_Rights {
|
|
2207 |
my %right = (); |
|
2208 |
||
2209 |
MySQLaccess::Debug::Print(2, "Debug Default_Access_Rights():"); |
|
2210 |
# add entry for all fields in the HOST-table
|
|
2211 |
foreach $field (keys(%MySQLaccess::Grant::H)) { |
|
2212 |
$right{$field}='0' unless (defined($right{$field})); |
|
2213 |
}
|
|
2214 |
# add entry for all fields in the DB-table
|
|
2215 |
foreach $field (keys(%MySQLaccess::Grant::D)) { |
|
2216 |
$right{$field}='0' unless (defined($right{$field})); |
|
2217 |
}
|
|
2218 |
# add entry for all fields in the USER-table
|
|
2219 |
foreach $field (keys(%MySQLaccess::Grant::U)) { |
|
2220 |
$right{$field}='0' unless (defined($right{$field})); |
|
2221 |
}
|
|
2222 |
# --------------
|
|
2223 |
# debugging info
|
|
2224 |
foreach $field (keys(%right)) { MySQLaccess::Debug::Print(3, sprintf("> %15s : %1s",$field,$right{$field})); } |
|
2225 |
||
2226 |
return \%right; |
|
2227 |
}
|
|
2228 |
||
2229 |
# ======================================
|
|
2230 |
# sub Make_Privlist
|
|
2231 |
# Make an ordered list of the privileges
|
|
2232 |
# that should be reported
|
|
2233 |
# ======================================
|
|
2234 |
sub Make_Privlist {
|
|
2235 |
# layout:
|
|
2236 |
#'select_priv', 'create_priv',
|
|
2237 |
#'insert_priv', 'drop_priv',
|
|
2238 |
#'update_priv', 'reload_priv',
|
|
2239 |
#'delete_priv', 'process_priv',
|
|
2240 |
#'file_priv', 'shutdown_priv');
|
|
2241 |
my $right; |
|
2242 |
my @privlist=(); |
|
2243 |
foreach $right (@U) { |
|
2244 |
if (! grep(/$right/,@privlist)) { push(@privlist,$right); } |
|
2245 |
}; |
|
2246 |
foreach $right (@D) { |
|
2247 |
if (! grep(/$right/,@privlist)) { push(@privlist,$right); } |
|
2248 |
}; |
|
2249 |
foreach $right (@H) { |
|
2250 |
if (! grep(/$right/,@privlist)) { push(@privlist,$right); } |
|
2251 |
}; |
|
2252 |
# print "Privileges:\n";
|
|
2253 |
# foreach $field (@privlist) { print " > $field\n"; }
|
|
2254 |
return \@privlist; |
|
2255 |
}
|
|
2256 |
||
2257 |
||
2258 |
||
2259 |
########################################################################
|
|
2260 |
package MySQLaccess::Report;
|
|
2261 |
use Exporter (); |
|
2262 |
@EXPORT = qw(&Print_Header()); |
|
2263 |
BEGIN {
|
|
2264 |
$FORM = $ENV{'SCRIPT_NAME'}; |
|
2265 |
$DEBUG = 0; |
|
2266 |
$DEBUG = $MySQLaccess::DEBUG unless ($DEBUG); |
|
2267 |
||
2268 |
# translation-table for poss. answers
|
|
2269 |
%Answer = ('Y' => 1 , 'N' => 0 |
|
2270 |
, 1 => 'Y', 0 => 'N' |
|
2271 |
,'?' => '?', '' => '?' |
|
2272 |
); |
|
2273 |
$headers = 0; |
|
2274 |
$separator = 0; |
|
2275 |
||
2276 |
# ****************************
|
|
2277 |
# Notes and warnings
|
|
2278 |
%MESSAGES = ( |
|
2279 |
'insecure_user'
|
|
2280 |
=> "Everybody can access your DB as user `\$user' from host `\$host'\n" |
|
2281 |
."WITHOUT supplying a password.\n"
|
|
2282 |
."Be very careful about it!!"
|
|
2283 |
,'password_required'
|
|
2284 |
=> "A password is required for user `\$user' :-(" |
|
2285 |
,'invalid_password'
|
|
2286 |
=> "The password '\$password' for user `\$user' is invalid :-P" |
|
2287 |
, 'valid_password'
|
|
2288 |
=> "You supplied the right password for user `\$user' :-)" |
|
2289 |
,'public_database'
|
|
2290 |
=> "Any user with the appropriate permissions has access to your DB!\n" |
|
2291 |
."Check your users!"
|
|
2292 |
,'full_access'
|
|
2293 |
=> "All grant-tables are empty, which gives full access to ALL users !!" |
|
2294 |
,'no_rule_found'
|
|
2295 |
=> "No matching rule" |
|
2296 |
,'no_equiv_host'
|
|
2297 |
=> "Not processed: host-field is not empty in db-table." |
|
2298 |
,'least_priv'
|
|
2299 |
=> "If the final priveliges of the user are more then you gave the user,\n" |
|
2300 |
."check the priveliges in the db-table `\$db'."
|
|
2301 |
,'minimum_priv'
|
|
2302 |
=> "The privileges for any new user are AT LEAST\n" |
|
2303 |
."the ones shown in the table above,\n"
|
|
2304 |
."since these are the privileges of the db `\$db'.\n"
|
|
2305 |
,'not_found_mysql'
|
|
2306 |
=> "The MySQL client program <$MySQLaccess::MYSQL> could not be found.\n" |
|
2307 |
."+ Check your path, or\n"
|
|
2308 |
."+ edit the source of this script to point \$MYSQL to the mysql client.\n"
|
|
2309 |
,'not_found_mysqldump'
|
|
2310 |
=> "The MySQL dump program <$MySQLaccess::MYSQLDUMP> could not be found.\n" |
|
2311 |
."+ Check your path, or\n"
|
|
2312 |
."+ edit the source of this script to point \$MYSQLDUMP to the mysqldump program.\n"
|
|
2313 |
,'not_found_diff'
|
|
2314 |
=> "The diff program <$MySQLaccess::DIFF> could not be found.\n" |
|
2315 |
."+ Check your path, or\n"
|
|
2316 |
."+ edit the source of this script to point \$DIFF to the diff program.\n"
|
|
2317 |
,'Unrecognized_option'
|
|
2318 |
=> "Sorry,\n" |
|
2319 |
."You are using an old version of the mysql-program,\n"
|
|
2320 |
."which does not yet implement a neccessary option.\n"
|
|
2321 |
."\n"
|
|
2322 |
."You need at least Version 6.2 of the mysql-client,\n"
|
|
2323 |
."which was build in MySQL v3.0.18, to use this version\n"
|
|
2324 |
."of `$MySQLaccess::script'." |
|
2325 |
,'Access_denied'
|
|
2326 |
=> "Sorry,\n" |
|
2327 |
."An error occured when trying to connect to the database\n"
|
|
2328 |
."with the grant-tables:\n"
|
|
2329 |
."* Maybe YOU do not have READ-access to this database?\n"
|
|
2330 |
."* If you used the -U option, you may have supplied an invalid username?\n"
|
|
2331 |
." for the superuser?\n"
|
|
2332 |
."* If you used the -U option, it may be possible you have to supply\n"
|
|
2333 |
." a superuser-password to, with the -P option?\n"
|
|
2334 |
."* If you used the -P option, you may have supplied an invalid password?\n"
|
|
2335 |
,'Dbaccess_denied'
|
|
2336 |
=> "Sorry,\n" |
|
2337 |
."An error occured when trying to connect to the database\n"
|
|
2338 |
."with the grant-tables. (dbaccess denied)\n"
|
|
2339 |
,'Unknown_tmp_table'
|
|
2340 |
=> "Sorry,\n" |
|
2341 |
."An error occured when trying to work with the temporary tables in the database\n"
|
|
2342 |
."with the grant-tables. (One of the temporary tables does not exist)\n"
|
|
2343 |
,'Unknown_table'
|
|
2344 |
=> "Sorry,\n" |
|
2345 |
."An error occured when trying to work with some tables in the database\n"
|
|
2346 |
."with the grant-tables. (table does not exist)\n"
|
|
2347 |
,'use_old_server'
|
|
2348 |
=> "Sorry,\n" |
|
2349 |
."An error occured when executing an SQL statement.\n"
|
|
2350 |
."You might consider altering the use of the parameter `--old_server' when \n"
|
|
2351 |
."calling `$MySQLaccess::script'." |
|
2352 |
,'unknown_error'
|
|
2353 |
=> "Sorry,\n" |
|
2354 |
."An error occured when trying to connect to the database\n"
|
|
2355 |
."with the grant-tables. (unknown error)\n"
|
|
2356 |
,'anonymous_access'
|
|
2357 |
=> "Accessing the db as an anonymous user.\n" |
|
2358 |
."Your username has no relevance\n"
|
|
2359 |
,'user_required'
|
|
2360 |
=> "You have to supply a userid." |
|
2361 |
,'db_required'
|
|
2362 |
=> "You have to supply the name of a database." |
|
2363 |
,'host_required'
|
|
2364 |
=> "You have to supply the name of a host." |
|
2365 |
); |
|
2366 |
||
2367 |
||
2368 |
}
|
|
2369 |
# =====================================
|
|
2370 |
# sub Print_Header:
|
|
2371 |
# print header info
|
|
2372 |
# =====================================
|
|
2373 |
sub Print_Header {
|
|
2374 |
if ($MySQLaccess::CMD) { #command-line mode |
|
2375 |
print "$MySQLaccess::script Version $MySQLaccess::VERSION\n" |
|
2376 |
."By RUG-AIV, by Yves Carlier (Yves.Carlier\@rug.ac.be)\n"
|
|
2377 |
."Changes by Steve Harvey (sgh\@vex.net)\n"
|
|
2378 |
."This software comes with ABSOLUTELY NO WARRANTY.\n"; |
|
2379 |
}
|
|
2380 |
if ($MySQLaccess::CGI) { #CGI-BIN mode |
|
2381 |
print "content-type: text/html\n\n"
|
|
2382 |
. "<HTML>\n"
|
|
2383 |
."<HEAD>\n"
|
|
2384 |
."<TITLE>MySQLaccess</TITLE>\n"
|
|
2385 |
."</HEAD>\n"
|
|
2386 |
."<BODY>\n"
|
|
2387 |
."<H1>$MySQLaccess::script Version $MySQLaccess::VERSION</H1>\n" |
|
2388 |
."<CENTER>\n<ADDRESS>\n"
|
|
2389 |
."By RUG-AIV, by Yves Carlier (<a href=mailto:Yves.Carlier\@rug.ac.be>Yves.Carlier\@rug.ac.be</a>)<BR>\n"
|
|
2390 |
."Changes by Steve Harvey (<a href=mailto:sgh\@vex.net>sgh\@vex.net</a>)<BR>\n"
|
|
2391 |
."This software comes with ABSOLUTELY NO WARRANTY.<BR>\n"
|
|
2392 |
."</ADDRESS>\n</CENTER>\n"
|
|
2393 |
."<HR>\n"; |
|
2394 |
Print_Taskbar(); |
|
2395 |
print "<HR>\n"; |
|
2396 |
}
|
|
2397 |
return 1; |
|
2398 |
}
|
|
2399 |
||
2400 |
# =====================================
|
|
2401 |
# sub Print_Footer:
|
|
2402 |
# print footer info
|
|
2403 |
# =====================================
|
|
2404 |
sub Print_Footer {
|
|
2405 |
if ($MySQLaccess::CMD) { #command-line mode |
|
2406 |
print "\n"
|
|
2407 |
."BUGs can be reported by email to bugs\@mysql.com\n"; |
|
2408 |
}
|
|
2409 |
if ($MySQLaccess::CGI) { #CGI-BIN mode |
|
2410 |
if ($MySQLaccess::Param{'brief'}) { |
|
2411 |
print "</table>\n"; #close table in brief-output |
|
2412 |
}
|
|
2413 |
print "<HR>\n"
|
|
2414 |
."<ADDRESS>\n"
|
|
2415 |
."BUGs can be reported by email to <a href=mailto:bugs\@mysql.com>bugs\@mysql.com</a><BR>\n"
|
|
2416 |
# ."Don't forget to mention the version $VERSION!<BR>\n"
|
|
2417 |
."</ADDRESS>\n"
|
|
2418 |
."</BODY>\n"
|
|
2419 |
."</HTML>\n"; |
|
2420 |
}
|
|
2421 |
return 1; |
|
2422 |
}
|
|
2423 |
||
2424 |
# =====================================
|
|
2425 |
# sub Print_Taskbar:
|
|
2426 |
# print taskbar on STDOUT
|
|
2427 |
# =====================================
|
|
2428 |
sub Print_Taskbar {
|
|
2429 |
print "<CENTER>\n"
|
|
2430 |
."[<a href=$FORM?relnotes=on>Release Notes</a>] \n" |
|
2431 |
."[<a href=$FORM?version=on>Version</a>] \n" |
|
2432 |
."[<a href=$FORM?plan=on>Future Plans</a>] \n" |
|
2433 |
."[<a href=$FORM?howto=on>Examples</a>] \n" |
|
2434 |
."[<a href=$FORM?help=on>New check</a>] \n" |
|
2435 |
."[<a href=$FORM?edit=on>Change/edit ACL</a>] \n" |
|
2436 |
."</CENTER>\n"; |
|
2437 |
return 1; |
|
2438 |
}
|
|
2439 |
||
2440 |
# =====================================
|
|
2441 |
# sub Print_Form:
|
|
2442 |
# print CGI-form
|
|
2443 |
# =====================================
|
|
2444 |
sub Print_Form {
|
|
2445 |
print <<EOForm;
|
|
2446 |
<center>
|
|
2447 |
<!-- Quering -->
|
|
2448 |
<FORM method=POST action=$FORM>
|
|
2449 |
||
2450 |
<table border width="100%" >
|
|
2451 |
<tr>
|
|
2452 |
<th>MySQL server</th>
|
|
2453 |
<th>User information</th>
|
|
2454 |
<th>Reports</th>
|
|
2455 |
</tr>
|
|
2456 |
||
2457 |
<tr>
|
|
2458 |
<td valign=top>
|
|
2459 |
<table>
|
|
2460 |
<tr>
|
|
2461 |
<td halign=right><b>Host</b><br><font size=-2>(Host on which MySQL-server resides.)</font></td>
|
|
2462 |
<td valign=top><INPUT name=rhost type=text size=15 maxlength=15 value="$MySQLaccess::Param{'rhost'}"></td>
|
|
2463 |
</tr>
|
|
2464 |
<tr>
|
|
2465 |
<td halign=right><b>Superuser</b><br><font size=-2>(User which has <font color="Red">read-access</font> to grant-tables.)</font></td>
|
|
2466 |
<td valign=top><INPUT name=superuser type=text size=15 maxlength=15 value="$MySQLaccess::Param{'superuser'}"></td>
|
|
2467 |
</tr>
|
|
2468 |
<tr>
|
|
2469 |
<td halign=right><b>Password</b><br><font size=-2>(of Superuser.)</font></td>
|
|
2470 |
<td valign=top><INPUT name=spassword type=password size=15 maxlength=15 value="$MySQLaccess::Param{'spassword'}"></td>
|
|
2471 |
</tr>
|
|
2472 |
</table>
|
|
2473 |
</td>
|
|
2474 |
||
2475 |
<td valign=top>
|
|
2476 |
<table>
|
|
2477 |
<tr>
|
|
2478 |
<td halign=right><b><font color=Red>User</font></b><br><font size=-2>(Userid used to connect to MySQL-database.)</font></td>
|
|
2479 |
<td halign=top><INPUT name=user type=text size=15 maxlength=15 value="$MySQLaccess::Param{'user'}"></td>
|
|
2480 |
</tr>
|
|
2481 |
<tr>
|
|
2482 |
<td halign=right><b>Password</b><br><font size=-2>(Password user has to give to get access to MySQL-database.)</font></td>
|
|
2483 |
<td valign=top><INPUT name=password type=password size=15 maxlength=15 value="$MySQLaccess::Param{'password'}"></td>
|
|
2484 |
</tr>
|
|
2485 |
<tr>
|
|
2486 |
<td halign=right><b><font color=Red>Database</font></b><br><font size=-2>(Name of MySQL-database user tries to connect to.</font><br><font size=-2>Wildcards <font color="Green">(*,?,%,_)</font> are allowed.)</font></td>
|
|
2487 |
<td valign=top><INPUT name=db type=text size=15 maxlength=15 value="$MySQLaccess::Param{'db'}"></td>
|
|
2488 |
</tr>
|
|
2489 |
<tr>
|
|
2490 |
<td halign=right><b>Host</b><br><font size=-2>(Host from where the user is trying to connect to MySQL-database.</font><br><font size=-2>Wildcards <font color="Green">(*,?,%,_)</font> are allowed.)</font></td>
|
|
2491 |
<td valign=top><INPUT name=host type=text size=15 maxlength=15 value="$MySQLaccess::Param{'host'}"></td>
|
|
2492 |
</tr>
|
|
2493 |
</table>
|
|
2494 |
</td>
|
|
2495 |
||
2496 |
<td valign=center>
|
|
2497 |
<table cellspacing=5 cellpadding=2 cols=1 height="100%">
|
|
2498 |
<tr align=center>
|
|
2499 |
<td halign=right><INPUT type=submit name=brief value="Brief"><br>
|
|
2500 |
<INPUT type=submit name=table value="Tabular"></td>
|
|
2501 |
</tr>
|
|
2502 |
<tr align=center>
|
|
2503 |
<td></td>
|
|
2504 |
</tr>
|
|
2505 |
<tr align=center>
|
|
2506 |
<td halign=right><INPUT type=reset value="Clear"></td>
|
|
2507 |
</tr>
|
|
2508 |
</table>
|
|
2509 |
</td>
|
|
2510 |
</tr>
|
|
2511 |
||
2512 |
</table>
|
|
2513 |
</form>
|
|
2514 |
||
2515 |
||
2516 |
</BODY>
|
|
2517 |
</HTML>
|
|
2518 |
EOForm
|
|
2519 |
return 1; |
|
2520 |
}
|
|
2521 |
||
2522 |
# =====================================
|
|
2523 |
# sub Print_Usage:
|
|
2524 |
# print some information on STDOUT
|
|
2525 |
# =====================================
|
|
2526 |
sub Print_Usage {
|
|
2527 |
Print_Error_Messages(); |
|
2528 |
if ($MySQLaccess::CMD) { #command-line mode |
|
2529 |
Print_Options(); |
|
2530 |
}
|
|
2531 |
if ($MySQLaccess::CGI) { #CGI-BIN mode |
|
2532 |
Print_Form(); |
|
2533 |
}
|
|
2534 |
return 1; |
|
2535 |
}
|
|
2536 |
||
2537 |
# ======================================
|
|
2538 |
# sub Print_Version:
|
|
2539 |
# ======================================
|
|
2540 |
sub Print_Version {
|
|
2541 |
if ($MySQLaccess::CMD) { |
|
2542 |
print $MySQLaccess::INFO; |
|
2543 |
}
|
|
2544 |
if ($MySQLaccess::CGI) { |
|
2545 |
print "<PRE>\n"; |
|
2546 |
print $MySQLaccess::INFO; |
|
2547 |
print "</PRE>\n"; |
|
2548 |
}
|
|
2549 |
return 1; |
|
2550 |
}
|
|
2551 |
||
2552 |
# ======================================
|
|
2553 |
# sub Print_Relnotes:
|
|
2554 |
# ======================================
|
|
2555 |
sub Print_Relnotes {
|
|
2556 |
if ($MySQLaccess::CMD) { |
|
2557 |
print $MySQLaccess::RELEASE; |
|
2558 |
}
|
|
2559 |
if ($MySQLaccess::CGI) { |
|
2560 |
print "<PRE>\n"; |
|
2561 |
print $MySQLaccess::RELEASE; |
|
2562 |
print "</PRE>\n"; |
|
2563 |
}
|
|
2564 |
return 1; |
|
2565 |
}
|
|
2566 |
||
2567 |
# ======================================
|
|
2568 |
# sub Print_Plans:
|
|
2569 |
# ======================================
|
|
2570 |
sub Print_Plans {
|
|
2571 |
if ($MySQLaccess::CMD) { |
|
2572 |
print $MySQLaccess::TODO; |
|
2573 |
}
|
|
2574 |
if ($MySQLaccess::CGI) { |
|
2575 |
print "<PRE>\n"; |
|
2576 |
print $MySQLaccess::TODO; |
|
2577 |
print "</PRE>\n"; |
|
2578 |
}
|
|
2579 |
return 1; |
|
2580 |
}
|
|
2581 |
||
2582 |
# ======================================
|
|
2583 |
# sub Print_HowTo:
|
|
2584 |
# ======================================
|
|
2585 |
sub Print_HowTo {
|
|
2586 |
if ($MySQLaccess::CMD) { |
|
2587 |
print $MySQLaccess::HOWTO; |
|
2588 |
}
|
|
2589 |
if ($MySQLaccess::CGI) { |
|
2590 |
print "<PRE>\n"; |
|
2591 |
print $MySQLaccess::HOWTO; |
|
2592 |
print "</PRE>\n"; |
|
2593 |
}
|
|
2594 |
return 1; |
|
2595 |
}
|
|
2596 |
||
2597 |
# ======================================
|
|
2598 |
# sub Print_Options:
|
|
2599 |
# ======================================
|
|
2600 |
sub Print_Options {
|
|
2601 |
if ($MySQLaccess::CGI) { print "<PRE>\n"; } |
|
2602 |
print $MySQLaccess::OPTIONS; |
|
2603 |
if ($MySQLaccess::CGI) { print "</PRE>\n"; } |
|
2604 |
return 1; |
|
2605 |
}
|
|
2606 |
||
2607 |
# ======================================
|
|
2608 |
# sub Print_Error_Access:
|
|
2609 |
# ======================================
|
|
2610 |
sub Print_Error_Access {
|
|
2611 |
my ($error) = @_; |
|
2612 |
print "\n"; |
|
2613 |
if ($MySQLaccess::CGI) { print "<font color=Red>\n<PRE>\n"; } |
|
2614 |
print $MESSAGES{$error}; |
|
2615 |
if ($MySQLaccess::CGI) { print "</PRE>\n</font>\n"; } |
|
2616 |
print "\n"; |
|
2617 |
return 1; |
|
2618 |
}
|
|
2619 |
||
2620 |
# ======================================
|
|
2621 |
# sub Print_Error_Messages:
|
|
2622 |
# ======================================
|
|
2623 |
sub Print_Error_Messages {
|
|
2624 |
# my ($error) = @_;
|
|
2625 |
print "\n"; |
|
2626 |
if ($MySQLaccess::CGI) { print "<font color=Red>\n<center>\n"; } |
|
2627 |
foreach $error (@MySQLaccess::Grant::Error) { |
|
2628 |
print $MESSAGES{$error}; |
|
2629 |
print $MySQLaccess::CGI ? "<br>\n" : "\n"; |
|
2630 |
}
|
|
2631 |
if ($MySQLaccess::CGI) { print "</center>\n</font>\n"; } |
|
2632 |
print "\n"; |
|
2633 |
return 1; |
|
2634 |
}
|
|
2635 |
||
2636 |
# ======================================
|
|
2637 |
# sub Print_Message:
|
|
2638 |
# ======================================
|
|
2639 |
sub Print_Message {
|
|
2640 |
my ($aref) = @_; |
|
2641 |
my @messages = @{$aref}; |
|
2642 |
print "\n"; |
|
2643 |
if ($MySQLaccess::CGI) { print "<font color=DarkGreen>\n<center>\n"; } |
|
2644 |
foreach $msg (@messages) { |
|
2645 |
print $msg; |
|
2646 |
print $MySQLaccess::CGI ? "<br>\n" : "\n"; |
|
2647 |
}
|
|
2648 |
if ($MySQLaccess::CGI) { print "</center>\n</font>\n"; } |
|
2649 |
print "\n"; |
|
2650 |
return 1; |
|
2651 |
}
|
|
2652 |
||
2653 |
# ======================================
|
|
2654 |
# sub Print_Edit:
|
|
2655 |
# ======================================
|
|
2656 |
sub Print_Edit {
|
|
2657 |
print "\n"; |
|
2658 |
if (!$MySQLaccess::CGI) { |
|
2659 |
print "Note: Editing the temporary tables is NOT supported in CMD-line mode!\n"; |
|
2660 |
return 0; |
|
2661 |
}
|
|
2662 |
print "<CENTER>\n"
|
|
2663 |
."<form action=$FORM method=GET>\n" |
|
2664 |
."<table width=90% border>\n"
|
|
2665 |
."<tr>\n"
|
|
2666 |
." <td><input type=checkbox name=copy value=on> Copy grant-rules to temporary tables<br></td>\n"
|
|
2667 |
." <td rowspan=5 align=center valign=center><input type=submit value=Go></td>\n"
|
|
2668 |
."</tr>\n"
|
|
2669 |
."<tr>\n"
|
|
2670 |
." <td> Edit temporary tables with external application:<br>"
|
|
2671 |
." <a href=\"$MySQLaccess::MYSQLADMIN\">$MySQLaccess::MYSQLADMIN</a></td>\n" |
|
2672 |
."</tr>\n"
|
|
2673 |
."<tr>\n"
|
|
2674 |
." <td><input type=checkbox name=preview value=on> Preview changes made in temporary tables</td>\n"
|
|
2675 |
."</tr>\n"
|
|
2676 |
."<tr>\n"
|
|
2677 |
." <td><input type=checkbox name=commit value=on> Make changes permanent</td>\n"
|
|
2678 |
."</tr>\n"
|
|
2679 |
."<tr>\n"
|
|
2680 |
." <td><input type=checkbox name=rollback value=on> Restore previous grand-rules</td>\n"
|
|
2681 |
."</tr>\n"
|
|
2682 |
."<tr>\n"
|
|
2683 |
." <td colspan=2 align=center><font size=-2 color=Red>You need write,delete and drop-privileges to perform the above actions</font></td>\n"
|
|
2684 |
."</tr>\n"
|
|
2685 |
."</table>\n"
|
|
2686 |
."</form>\n"
|
|
2687 |
."</CENTER>\n"; |
|
2688 |
||
2689 |
return 1; |
|
2690 |
}
|
|
2691 |
||
2692 |
||
2693 |
# ======================================
|
|
2694 |
# sub Print_Access_rights:
|
|
2695 |
# print the access-rights on STDOUT
|
|
2696 |
# ======================================
|
|
2697 |
sub Print_Access_rights {
|
|
2698 |
my ($host,$user,$db,$refhash) = @_; |
|
2699 |
||
2700 |
if (defined($MySQLaccess::Param{'brief'})) { |
|
2701 |
# if ($MySQLaccess::CGI) { print "<PRE>\n"; }
|
|
2702 |
Matrix_Report($host,$user,$db,$refhash); |
|
2703 |
# if ($MySQLaccess::CGI) { print "</PRE>\n"; }
|
|
2704 |
}
|
|
2705 |
else { |
|
2706 |
Tabular_Report($host,$user,$db,$refhash); |
|
2707 |
$MySQLaccess::Report::separator = $MySQLaccess::CGI ? "<hr>" : "-"x80; |
|
2708 |
}
|
|
2709 |
return 1; |
|
2710 |
}
|
|
2711 |
||
2712 |
# ======================================
|
|
2713 |
# sub Print_Diff_ACL:
|
|
2714 |
# print the diff. in the grants before and after
|
|
2715 |
# ======================================
|
|
2716 |
sub Print_Diff_ACL {
|
|
2717 |
my ($aref) = @_; |
|
2718 |
my @diffs = @{$aref}; |
|
2719 |
my %block = ( '<' => 'Before', |
|
2720 |
'>' => 'After', |
|
2721 |
); |
|
2722 |
my %color = ( '<' => 'Green', |
|
2723 |
'>' => 'Red', |
|
2724 |
); |
|
2725 |
my $curblock = ''; |
|
2726 |
||
2727 |
# -----------------------------
|
|
2728 |
# create column-headers
|
|
2729 |
foreach $field (@MySQLaccess::Grant::Privileges) { |
|
2730 |
push(@headers,substr($field,0,4)); |
|
2731 |
}
|
|
2732 |
||
2733 |
if ($MySQLaccess::CMD) { |
|
2734 |
print "\n"; |
|
2735 |
print "Differences in access-rights BEFORE and AFTER changes in grant-tables\n"; |
|
2736 |
# print "---------------------------------------------------------------------\n";
|
|
2737 |
my $line1=""; |
|
2738 |
my $line2=""; |
|
2739 |
$line1 .= sprintf("| %-30s|",'Host,User,DB'); |
|
2740 |
$line2 .= sprintf("+-%-30s+",'-' x 30); |
|
2741 |
foreach $header (@headers) { |
|
2742 |
$line1 .= sprintf("%-4s|",$header); |
|
2743 |
$line2 .= sprintf("%s+",'----'); |
|
2744 |
}
|
|
2745 |
print "$line2\n"; |
|
2746 |
print "$line1\n"; |
|
2747 |
print "$line2\n"; |
|
2748 |
||
2749 |
$format = "format STDOUT = \n" |
|
2750 |
. "^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< " . " @|||" x 10 ."\n" |
|
2751 |
. '$host_user_db,@priv' . "\n" |
|
2752 |
. ".\n"; |
|
2753 |
#print $format;
|
|
2754 |
eval $format; |
|
2755 |
}
|
|
2756 |
if ($MySQLaccess::CGI) { |
|
2757 |
print "<table border width=100%>\n"; |
|
2758 |
print "<tr>\n"; |
|
2759 |
print "<th colspan=11>"; |
|
2760 |
print "Differences in access-rights <font color=$color{'<'}>BEFORE</font> " |
|
2761 |
."and <font color=$color{'>'}>AFTER</font> changes to grant-tables</font>\n"; |
|
2762 |
print "</th>"; |
|
2763 |
print "</tr>\n"; |
|
2764 |
print "<tr>\n"; |
|
2765 |
$line1 .= sprintf("<th>%-20s</th>",'Host, User, DB'); |
|
2766 |
foreach $header (@headers) { |
|
2767 |
$line1 .= sprintf("<th>%-4s</th>",$header); |
|
2768 |
}
|
|
2769 |
print "$line1</tr>\n"; |
|
2770 |
}
|
|
2771 |
||
2772 |
foreach $line (@diffs) { |
|
2773 |
$type = substr($line,0,1); |
|
2774 |
$line = substr($line,1); |
|
2775 |
($host,$user,$db,@priv) = split(/,/,$line); |
|
2776 |
if ($MySQLaccess::CMD) { |
|
2777 |
if ($type ne $curblock) { |
|
2778 |
$curblock = $type; |
|
2779 |
print $block{$curblock},":\n"; |
|
2780 |
}
|
|
2781 |
#print "$line\n";
|
|
2782 |
write;
|
|
2783 |
}
|
|
2784 |
if ($MySQLaccess::CGI) { |
|
2785 |
if ($type ne $curblock) { |
|
2786 |
$curblock = $type; |
|
2787 |
print "<tr><td><b>$block{$curblock}<b></td></tr>\n"; |
|
2788 |
}
|
|
2789 |
$line1="<td><font color=$color{$type}>$host, $user, $db</font></td>"; |
|
2790 |
foreach $field (@priv) { |
|
2791 |
$line1 .= sprintf("<td align=center><font color=$color{$type}>%-4s</font></td>",$field); |
|
2792 |
}
|
|
2793 |
print "<tr>$line1</tr>\n"; |
|
2794 |
}
|
|
2795 |
}
|
|
2796 |
print "\n"; |
|
2797 |
if ($MySQLaccess::CMD) { |
|
2798 |
print "---------------------------------------------------------------------\n"; |
|
2799 |
}
|
|
2800 |
if ($MySQLaccess::CGI) { |
|
2801 |
print "</table><br>"; |
|
2802 |
}
|
|
2803 |
||
2804 |
||
2805 |
return 1; |
|
2806 |
}
|
|
2807 |
||
2808 |
# ======================================
|
|
2809 |
# sub Tabular_Report
|
|
2810 |
# Tabular report,
|
|
2811 |
# suitable for 1 triple (host,db,user)
|
|
2812 |
# ======================================
|
|
2813 |
sub Tabular_Report {
|
|
2814 |
my ($host,$user,$db,$a) = @_; |
|
2815 |
my $column=2; |
|
2816 |
||
2817 |
# -----------------------------
|
|
2818 |
# separator
|
|
2819 |
if ($MySQLaccess::Report::separator) { print "$MySQLaccess::Report::separator\n"; } |
|
2820 |
||
2821 |
# -----------------------------
|
|
2822 |
# print table of access-rights
|
|
2823 |
my $rows = int(@MySQLaccess::Grant::Privileges/2); #round up |
|
2824 |
my @table=(); |
|
2825 |
$j=0; |
|
2826 |
for $i (0 .. $rows-1) { |
|
2827 |
$table[$j]=$MySQLaccess::Grant::Privileges[$i]; |
|
2828 |
$j = $j+2; |
|
2829 |
}
|
|
2830 |
$j=1; |
|
2831 |
for $i ($rows .. $#MySQLaccess::Grant::Privileges) { |
|
2832 |
$table[$j]=$MySQLaccess::Grant::Privileges[$i]; |
|
2833 |
$j = $j+2; |
|
2834 |
}
|
|
2835 |
if ($MySQLaccess::CMD) { |
|
2836 |
print "\n"; |
|
2837 |
print "Access-rights\n"; |
|
2838 |
print "for USER '$user', from HOST '$host', to DB '$db'\n"; |
|
2839 |
}
|
|
2840 |
if ($MySQLaccess::CGI) { |
|
2841 |
print "<table border width=100%>\n"; |
|
2842 |
print "<tr>\n"; |
|
2843 |
}
|
|
2844 |
if ($MySQLaccess::CGI) { |
|
2845 |
print "<th colspan=5>"; |
|
2846 |
print "<font color=Red>Access-rights</font>\n"; |
|
2847 |
print "for USER '<font color=Green>$user</font>', from HOST '<font color=Green>$host</font>', to DB '<font color=Green>$db</font>'\n"; |
|
2848 |
print "</th>"; |
|
2849 |
print "</tr>\n"; |
|
2850 |
print "<tr>\n"; |
|
2851 |
}
|
|
2852 |
if ($MySQLaccess::CMD) { |
|
2853 |
print "\t+-----------------+---+\t+-----------------+---+"; |
|
2854 |
}
|
|
2855 |
foreach $field (@table) { |
|
2856 |
if ($MySQLaccess::CMD) { |
|
2857 |
if ($column==2) { print "\n\t"; $column=1;} |
|
2858 |
else { print "\t"; $column=2;} |
|
2859 |
printf "| %-15s | %s |",$field,$Answer{$a->{$field}}; |
|
2860 |
}
|
|
2861 |
if ($MySQLaccess::CGI) { |
|
2862 |
if ($column==2) { print "</tr>\n<tr>\n"; $column=1;} |
|
2863 |
else { print "<td width=10%></td>"; $column=2;} |
|
2864 |
printf " <td width=35%><b>%-15s</b></td><td width=10%>%s</td>\n",$field,$Answer{$a->{$field}}; |
|
2865 |
}
|
|
2866 |
}
|
|
2867 |
print "\n"; |
|
2868 |
if ($MySQLaccess::CMD) { |
|
2869 |
print "\t+-----------------+---+\t+-----------------+---+\n"; |
|
2870 |
}
|
|
2871 |
if ($MySQLaccess::CGI) { |
|
2872 |
print "</tr>\n</table><br>"; |
|
2873 |
}
|
|
2874 |
||
2875 |
# ---------------
|
|
2876 |
# print notes:
|
|
2877 |
foreach $note (@MySQLaccess::Grant::Notes) { |
|
2878 |
my $message = $MESSAGES{$note}; |
|
2879 |
$message =~ s/\$user/$user/g; |
|
2880 |
$message =~ s/\$db/$db/g; |
|
2881 |
$message =~ s/\$host/$host/g; |
|
2882 |
$message =~ s/\$password/$password/g; |
|
2883 |
$PREFIX='NOTE'; |
|
2884 |
if ($MySQLaccess::CMD) { |
|
2885 |
my @lines = split(/\n/,$message); |
|
2886 |
foreach $line (@lines) { |
|
2887 |
print "$PREFIX:\t $line\n"; |
|
2888 |
$PREFIX=' '; |
|
2889 |
}
|
|
2890 |
}
|
|
2891 |
if ($MySQLaccess::CGI) { |
|
2892 |
print "<b>$PREFIX:</b> $message<br>\n"; |
|
2893 |
}
|
|
2894 |
}
|
|
2895 |
||
2896 |
# ---------------
|
|
2897 |
# print warnings:
|
|
2898 |
foreach $warning (@MySQLaccess::Grant::Warnings) { |
|
2899 |
my $message = $MESSAGES{$warning}; |
|
2900 |
$message =~ s/\$user/$user/g; |
|
2901 |
$message =~ s/\$db/$db/g; |
|
2902 |
$message =~ s/\$host/$host/g; |
|
2903 |
$message =~ s/\$password/$password/g; |
|
2904 |
$PREFIX='BEWARE'; |
|
2905 |
if ($MySQLaccess::CMD) { |
|
2906 |
my @lines = split(/\n/,$message); |
|
2907 |
foreach $line (@lines) { |
|
2908 |
print "$PREFIX:\t $line\n"; |
|
2909 |
$PREFIX=' '; |
|
2910 |
}
|
|
2911 |
}
|
|
2912 |
if ($MySQLaccess::CGI) { |
|
2913 |
print "<b>$PREFIX:</b> $message<br>\n"; |
|
2914 |
}
|
|
2915 |
}
|
|
2916 |
||
2917 |
# ---------------
|
|
2918 |
# print errors:
|
|
2919 |
foreach $error (@MySQLaccess::Grant::Errors) { |
|
2920 |
my $message = $MESSAGES{$error}; |
|
2921 |
$message =~ s/\$user/$user/g; |
|
2922 |
$message =~ s/\$db/$db/g; |
|
2923 |
$message =~ s/\$host/$host/g; |
|
2924 |
$message =~ s/\$password/$password/g; |
|
2925 |
$PREFIX='ERROR'; |
|
2926 |
if ($MySQLaccess::CMD) { |
|
2927 |
my @lines = split(/\n/,$message); |
|
2928 |
foreach $line (@lines) { |
|
2929 |
print "$PREFIX:\t $line\n"; |
|
2930 |
$PREFIX=' '; |
|
2931 |
}
|
|
2932 |
}
|
|
2933 |
if ($MySQLaccess::CGI) { |
|
2934 |
print "<b>$PREFIX:</b> $message<br>\n"; |
|
2935 |
}
|
|
2936 |
}
|
|
2937 |
||
2938 |
# ---------------
|
|
2939 |
# inform if there are no rules ==> full access for everyone.
|
|
2940 |
if ($MySQLaccess::Grant::full_access) { print "$MESSAGES{'full_access'}\n"; } |
|
2941 |
||
2942 |
# ---------------
|
|
2943 |
# print the rules used
|
|
2944 |
print "\n"; |
|
2945 |
if ($MySQLaccess::CMD) { |
|
2946 |
print "The following rules are used:\n"; |
|
2947 |
foreach $field (sort(keys(%MySQLaccess::Grant::Rules))) { |
|
2948 |
my $rule = (defined($MESSAGES{$MySQLaccess::Grant::Rules{$field}}) ? $MESSAGES{$MySQLaccess::Grant::Rules{$field}} : $MySQLaccess::Grant::Rules{$field}); |
|
2949 |
$rule =~ s/\t/','/g; |
|
2950 |
printf " %-5s : '%s'\n",$field,$rule; |
|
2951 |
}
|
|
2952 |
}
|
|
2953 |
if ($MySQLaccess::CGI) { |
|
2954 |
print "<br>\n"; |
|
2955 |
print "<table border width=100%>\n"; |
|
2956 |
print "<tr><th colspan=2>The following rules are used:</th></tr>\n"; |
|
2957 |
foreach $field (sort(keys(%MySQLaccess::Grant::Rules))) { |
|
2958 |
my $rule = (defined($MESSAGES{$MySQLaccess::Grant::Rules{$field}}) ? $MESSAGES{$MySQLaccess::Grant::Rules{$field}} : $MySQLaccess::Grant::Rules{$field}); |
|
2959 |
$rule =~ s/\t/','/g; |
|
2960 |
printf "<tr><th>%-5s</th><td>'%s'</td></tr>\n",$field,$rule; |
|
2961 |
}
|
|
2962 |
print "</table>\n"; |
|
2963 |
}
|
|
2964 |
||
2965 |
return 1; |
|
2966 |
}
|
|
2967 |
||
2968 |
# ======================================
|
|
2969 |
# sub Matrix_Report:
|
|
2970 |
# single-line output foreach triple,
|
|
2971 |
# no notes,warnings,...
|
|
2972 |
# ======================================
|
|
2973 |
sub Matrix_Report {
|
|
2974 |
my ($host,$user,$db,$a) = @_; |
|
2975 |
my @headers = (); |
|
2976 |
||
2977 |
if (! $headers) { |
|
2978 |
# -----------------------------
|
|
2979 |
# create column-headers
|
|
2980 |
foreach $field (@MySQLaccess::Grant::Privileges) { |
|
2981 |
push(@headers,substr($field,0,4)); |
|
2982 |
}
|
|
2983 |
||
2984 |
# -----------------------------
|
|
2985 |
# print column-headers
|
|
2986 |
print "\n"; |
|
2987 |
if ($MySQLaccess::CMD) { |
|
2988 |
my $line1=""; |
|
2989 |
my $line2=""; |
|
2990 |
foreach $header (@headers) { |
|
2991 |
$line1 .= sprintf("%-4s ",$header); |
|
2992 |
$line2 .= sprintf("%s ",'----'); |
|
2993 |
}
|
|
2994 |
$line1 .= sprintf("| %-20s",'Host,User,DB'); |
|
2995 |
$line2 .= sprintf("+ %-20s",'-' x 20); |
|
2996 |
print "$line1\n"; |
|
2997 |
print "$line2\n"; |
|
2998 |
}
|
|
2999 |
if ($MySQLaccess::CGI) { |
|
3000 |
print "<table width=100% border>\n"; |
|
3001 |
my $line1="<tr>"; |
|
3002 |
foreach $header (@headers) { |
|
3003 |
$line1 .= sprintf("<th>%-4s</th>",$header); |
|
3004 |
}
|
|
3005 |
$line1 .= sprintf("<th>%-20s</th>",'Host, User, DB'); |
|
3006 |
print "$line1</tr>\n"; |
|
3007 |
}
|
|
3008 |
||
3009 |
# ----------------------------
|
|
3010 |
# column-headers should only be
|
|
3011 |
# printed once.
|
|
3012 |
$MySQLaccess::Report::headers=1; |
|
3013 |
}
|
|
3014 |
||
3015 |
# ------------------------
|
|
3016 |
# print access-information
|
|
3017 |
if ($MySQLaccess::CMD) { |
|
3018 |
foreach $field (@MySQLaccess::Grant::Privileges) { |
|
3019 |
printf " %-2s ",$Answer{$a->{$field}}; |
|
3020 |
}
|
|
3021 |
printf "| %-20s",join(',',$host,$user,$db); |
|
3022 |
print "\n"; |
|
3023 |
}
|
|
3024 |
if ($MySQLaccess::CGI) { |
|
3025 |
print "<tr>"; |
|
3026 |
foreach $field (@MySQLaccess::Grant::Privileges) { |
|
3027 |
printf "<td align=center>%-2s</td>",$Answer{$a->{$field}}; |
|
3028 |
}
|
|
3029 |
printf "<td><b>%-20s</b></td>",join(', ',$host,$user,$db); |
|
3030 |
print "</tr>\n"; |
|
3031 |
}
|
|
3032 |
||
3033 |
return 1; |
|
3034 |
}
|
|
3035 |
||
3036 |
||
3037 |
# ======================================
|
|
3038 |
# sub Raw_Report:
|
|
3039 |
# single-line output foreach triple,
|
|
3040 |
# no notes,warnings,...
|
|
3041 |
# ======================================
|
|
3042 |
sub Raw_Report {
|
|
3043 |
my ($host,$user,$db,$a) = @_; |
|
3044 |
my @headers = (); |
|
3045 |
my $string = ""; |
|
3046 |
||
3047 |
# ------------------------
|
|
3048 |
# print access-information
|
|
3049 |
$string = "$host,$user,$db,"; |
|
3050 |
foreach $field (@MySQLaccess::Grant::Privileges) { |
|
3051 |
$string .= $Answer{$a->{$field}} . ","; |
|
3052 |
}
|
|
3053 |
return $string; |
|
3054 |
}
|
|
3055 |
||
3056 |
||
3057 |
#######################################################################
|
|
3058 |
package MySQLaccess::Wildcards;
|
|
3059 |
BEGIN {
|
|
3060 |
$DEBUG = 0; |
|
3061 |
$DEBUG = $MySQLaccess::DEBUG unless ($DEBUG); |
|
3062 |
}
|
|
3063 |
# ############################################
|
|
3064 |
# SQL, WILDCARDS and REGULAR EXPRESSIONS
|
|
3065 |
# ============================================
|
|
3066 |
# translage SQL-expressions to Reg-expressions
|
|
3067 |
# ============================================
|
|
3068 |
sub SQL2Reg {
|
|
3069 |
my ($expr) = @_; |
|
3070 |
my $expr_o = $expr; |
|
3071 |
$expr =~ s/\./\\./g; |
|
3072 |
$expr =~ s/\\%/\002/g; |
|
3073 |
$expr =~ s/%/.*/g; |
|
3074 |
$expr =~ s/\002/%/g; |
|
3075 |
$expr =~ s/\\_/\002/g; |
|
3076 |
$expr =~ s/_/.+/g; |
|
3077 |
$expr =~ s/\002/_/g; |
|
3078 |
MySQLaccess::Debug::Print(2,"$expr_o --> $expr"); |
|
3079 |
return $expr; |
|
3080 |
}
|
|
3081 |
||
3082 |
# translage WILDcards to Reg-expressions
|
|
3083 |
# ============================================
|
|
3084 |
sub Wild2Reg {
|
|
3085 |
my ($expr) = @_; |
|
3086 |
my $expr_o = $expr; |
|
3087 |
$expr =~ s/\./\\./g; |
|
3088 |
$expr =~ s/\\\*/\002/g; |
|
3089 |
$expr =~ s/\*/.*/g; |
|
3090 |
$expr =~ s/\002/*/g; |
|
3091 |
$expr =~ s/\\\?/\002/g; |
|
3092 |
$expr =~ s/\?/.+/g; |
|
3093 |
$expr =~ s/\002/?/g; |
|
3094 |
MySQLaccess::Debug::Print(2,"$expr_o --> $expr"); |
|
3095 |
return $expr; |
|
3096 |
}
|
|
3097 |
||
3098 |
# =============================================
|
|
3099 |
# match a given string with a template
|
|
3100 |
# =============================================
|
|
3101 |
sub MatchTemplate {
|
|
3102 |
my ($tpl,$string) = @_; |
|
3103 |
my $match=0; |
|
3104 |
if ($string=~ /^$tpl$/ or $tpl eq '') { $match=1; } |
|
3105 |
else { $match=0;} |
|
3106 |
MySQLaccess::Debug::Print(2,"($tpl,$string) --> $match"); |
|
3107 |
return $match; |
|
3108 |
}
|
|
3109 |
||
3110 |
#######################################################################
|
|
3111 |
package MySQLaccess::Host;
|
|
3112 |
BEGIN {
|
|
3113 |
$localhost = undef; |
|
3114 |
$DEBUG = 2; |
|
3115 |
$DEBUG = $MySQLaccess::DEBUG unless ($DEBUG); |
|
3116 |
}
|
|
3117 |
# ======================================
|
|
3118 |
# sub IP2Name
|
|
3119 |
# return the Name with the corr. IP-nmbr
|
|
3120 |
# (no aliases yet!!)
|
|
3121 |
# ======================================
|
|
3122 |
sub IP2Name {
|
|
3123 |
my ($ip) = @_; |
|
3124 |
my $ip_o = $ip; |
|
3125 |
if ($ip !~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/o) { |
|
3126 |
MySQLaccess::Debug::Print(3,"'$ip' is not an ip-number, returning IP=$ip"); |
|
3127 |
return $ip; |
|
3128 |
}
|
|
3129 |
MySQLaccess::Debug::Print(4,"IP=$ip split up => $1.$2.$3.$4"); |
|
3130 |
$ip = pack "C4",$1,$2,$3,$4; |
|
3131 |
MySQLaccess::Debug::Print(4,"IP packed -> >>$ip<<\n"); |
|
3132 |
my ($name,$aliases,$addrtype,$length,@addrs) = gethostbyaddr($ip, AF_INET); |
|
3133 |
MySQLaccess::Debug::Print(3,"IP=$ip_o => hostname=$name"); |
|
3134 |
MySQLaccess::Debug::Print(4,"aliases=$aliases"); |
|
3135 |
MySQLaccess::Debug::Print(4,"addrtype=$addrtype - length=$length"); |
|
3136 |
return ($name || $ip); |
|
3137 |
#return ($name || undef);
|
|
3138 |
}
|
|
3139 |
||
3140 |
# ======================================
|
|
3141 |
# sub Name2IP
|
|
3142 |
# return the IP-number of the host
|
|
3143 |
# ======================================
|
|
3144 |
sub Name2IP {
|
|
3145 |
my ($name) = @_; |
|
3146 |
if ($name =~ /[%_]/) { |
|
3147 |
MySQLaccess::Debug::Print(3,"'$name' contains SQL-wildcards, returning name=$name"); |
|
3148 |
return $name; |
|
3149 |
}
|
|
3150 |
my ($_name,$aliases,$addrtype,$length,@addrs) = gethostbyname($name); |
|
3151 |
my ($a,$b,$c,$d) = unpack('C4',$addrs[0]); |
|
3152 |
my $ip = "$a.$b.$c.$d"; |
|
3153 |
MySQLaccess::Debug::Print(3,"hostname=$name => IP=$ip"); |
|
3154 |
MySQLaccess::Debug::Print(4,"aliases=$aliases"); |
|
3155 |
MySQLaccess::Debug::Print(4,"addrtype=$addrtype - length=$length"); |
|
3156 |
#if ($ip ne "") { return "$ip"; }
|
|
3157 |
#else { return undef; }
|
|
3158 |
return ($ip || $name); |
|
3159 |
}
|
|
3160 |
||
3161 |
# ========================================
|
|
3162 |
# sub LocalHost
|
|
3163 |
# some special action has to be taken for
|
|
3164 |
# the localhost
|
|
3165 |
# ========================================
|
|
3166 |
sub LocalHost {
|
|
3167 |
if (!defined($MySQLaccess::Host::localhost)) { |
|
3168 |
$MySQLaccess::Host::localhost = Sys::Hostname::hostname(); |
|
3169 |
MySQLaccess::Debug::Print(3,"Setting package variable \$localhost=$MySQLaccess::Host::localhost"); |
|
3170 |
}
|
|
3171 |
my $host = $localhost; |
|
3172 |
MySQLaccess::Debug::Print(3,"localhost = $host"); |
|
3173 |
return $host; |
|
3174 |
}
|
|
3175 |
||
3176 |
# ========================================
|
|
3177 |
# check if the given hostname (or ip)
|
|
3178 |
# corresponds with the localhost
|
|
3179 |
# ========================================
|
|
3180 |
sub Is_localhost {
|
|
3181 |
my ($host_tpl) = @_; |
|
3182 |
my $isit = 0; |
|
3183 |
if (($MySQLaccess::host_name eq $localhost) or ($MySQLaccess::host_ip eq $local_ip)) { |
|
3184 |
MySQLaccess::Debug::Print(2,"Checking for localhost"); |
|
3185 |
MySQLaccess::Debug::Print(3,"because ($MySQLaccess::host_name EQ $localhost) AND ($MySQLaccess::host_ip EQ $local_ip)"); |
|
3186 |
$isit = ( 'localhost' =~ /$host_tpl/ ) ? 1 : 0; |
|
3187 |
MySQLaccess::Debug::Print(3," 'localhost' =?= $host_tpl -> $isit"); |
|
3188 |
return $isit; |
|
3189 |
}
|
|
3190 |
else { |
|
3191 |
MySQLaccess::Debug::Print(4,"Not checking for localhost"); |
|
3192 |
MySQLaccess::Debug::Print(4,"because ($MySQLaccess::host_name != $localhost) AND ($MySQLaccess::host_ip != $local_ip)"); |
|
3193 |
return 0; |
|
3194 |
}
|
|
3195 |
}
|
|
3196 |
||
3197 |
||
3198 |
# =========================================
|
|
3199 |
# check if host (IP or name) can be matched
|
|
3200 |
# on the template.
|
|
3201 |
# =========================================
|
|
3202 |
sub MatchTemplate {
|
|
3203 |
my ($host,$tpl) = @_; |
|
3204 |
my $match = 0; |
|
3205 |
||
3206 |
MySQLaccess::Debug::Print(1, "($host) =?= ($tpl)"); |
|
3207 |
||
3208 |
my $host_name = IP2Name($host); |
|
3209 |
my $host_ip = Name2IP($host); |
|
3210 |
||
3211 |
MySQLaccess::Debug::Print(2, "name=$host_name ; ip=$host_ip"); |
|
3212 |
$match = (MySQLaccess::Wildcards::MatchTemplate($tpl,$host_name) or |
|
3213 |
MySQLaccess::Wildcards::MatchTemplate($tpl,$host_ip)); |
|
3214 |
||
3215 |
MySQLaccess::Debug::Print(2, "($host_name,$host_ip) =?= ($tpl): $ncount"); |
|
3216 |
||
3217 |
return $match; |
|
3218 |
}
|
|
3219 |
||
3220 |
########################################################################
|
|
3221 |
package MySQLaccess::Debug;
|
|
3222 |
BEGIN {
|
|
3223 |
my $dbg_file = "$MySQLaccess::script_log"; |
|
3224 |
open(DEBUG,"> $dbg_file") or warn "Could not open outputfile $dbg_file for debugging-info\n"; |
|
3225 |
select DEBUG; |
|
3226 |
$| = 1; |
|
3227 |
select STDOUT; |
|
3228 |
}
|
|
3229 |
# =========================================
|
|
3230 |
# Print debugging information on STDERR
|
|
3231 |
# =========================================
|
|
3232 |
sub Print {
|
|
3233 |
my ($level,$mesg) = @_; |
|
3234 |
my ($pack,$file,$line,$subname,$hasargs,$wantarray) = caller(1); |
|
3235 |
my ($PACK) = split('::',$subname); |
|
3236 |
my $DEBUG = ${$PACK."::DEBUG"} ? ${$PACK."::DEBUG"} : $MySQLaccess::DEBUG ; |
|
3237 |
my ($sec,$min,$hour) = localtime(); |
|
3238 |
print DEBUG "[$hour:$min:$sec $subname] $mesg\n" if ($DEBUG>=$level); |
|
3239 |
}
|
|
3240 |