Richard Marian Thomaiyar | 14fddef | 2018-07-13 23:55:56 +0530 | [diff] [blame] | 1 | package Bastille::API::ServiceAdmin; |
| 2 | use strict; |
| 3 | |
| 4 | use Bastille::API; |
| 5 | |
| 6 | use Bastille::API::HPSpecific; |
| 7 | use Bastille::API::FileContent; |
| 8 | |
| 9 | require Exporter; |
| 10 | our @ISA = qw(Exporter); |
| 11 | our @EXPORT_OK = qw( |
| 12 | B_chkconfig_on |
| 13 | B_chkconfig_off |
| 14 | B_service_start |
| 15 | B_service_stop |
| 16 | B_service_restart |
| 17 | B_is_service_off |
| 18 | checkServiceOnLinux |
| 19 | remoteServiceCheck |
| 20 | remoteNISPlusServiceCheck |
| 21 | B_create_nsswitch_file |
| 22 | ); |
| 23 | our @EXPORT = @EXPORT_OK; |
| 24 | |
| 25 | |
| 26 | ####### |
| 27 | # &B_chkconfig_on and &B_chkconfig_off() are great for systems that didn't use |
| 28 | # a more modern init system. This is a bit of a problem on Fedora, though, |
| 29 | # which used upstart from Fedora 9 to Fedora 14, then switched to a new |
| 30 | # Red Hat-created system called systemd for Fedora 15 and 16 (so far). |
| 31 | # OpenSUSE also moved to systemd, starting with 12.1. Version 11.4 did not |
| 32 | # use systemd. |
| 33 | # It is also a problem on Ubuntu, starting at version 6.10, where they also |
| 34 | # used upstart. |
| 35 | ##### |
| 36 | |
| 37 | |
| 38 | |
| 39 | |
| 40 | ########################################################################### |
| 41 | # &B_chkconfig_on ($daemon_name) creates the symbolic links that are |
| 42 | # named in the "# chkconfig: ___ _ _ " portion of the init.d files. We |
| 43 | # need this utility, in place of the distro's chkconfig, because of both |
| 44 | # our need to add revert functionality and our need to harden distros that |
| 45 | # are not mounted on /. |
| 46 | # |
| 47 | # It uses the following global variables to find the links and the init |
| 48 | # scripts, respectively: |
| 49 | # |
| 50 | # &getGlobal('DIR', "rcd") -- directory where the rc_.d subdirs can be found |
| 51 | # &getGlobal('DIR', "initd") -- directory the rc_.d directories link to |
| 52 | # |
| 53 | # Here an example of where you might use this: |
| 54 | # |
| 55 | # You'd like to tell the system to run the firewall at boot: |
| 56 | # B_chkconfig_on("bastille-firewall") |
| 57 | # |
| 58 | ########################################################################### |
| 59 | |
| 60 | # PW: Blech. Copied B_chkconfig_off() and changed a few things, |
| 61 | # then changed a few more things.... |
| 62 | |
| 63 | sub B_chkconfig_on { |
| 64 | |
| 65 | my $startup_script=$_[0]; |
| 66 | my $retval=1; |
| 67 | |
| 68 | my $chkconfig_line; |
| 69 | my ($runlevelinfo,@runlevels); |
| 70 | my ($start_order,$stop_order,$filetolink); |
| 71 | |
| 72 | &B_log("ACTION","# chkconfig_on enabling $startup_script\n"); |
| 73 | |
| 74 | # In Debian system there is no chkconfig script, run levels are checked |
| 75 | # one by one (jfs) |
| 76 | if (&GetDistro =~/^DB.*/) { |
| 77 | $filetolink = &getGlobal('DIR', "initd") . "/$startup_script"; |
| 78 | if (-x $filetolink) |
| 79 | { |
| 80 | foreach my $level ("0","1","2","3","4","5","6" ) { |
| 81 | my $link = ''; |
| 82 | $link = &getGlobal('DIR', "rcd") . "/rc" . "$level" . ".d/K50" . "$startup_script"; |
| 83 | $retval=symlink($filetolink,$link); |
| 84 | } |
| 85 | } |
| 86 | return $retval; |
| 87 | } |
| 88 | # |
| 89 | # On SUSE, chkconfig-based rc scripts have been replaced with a whole different |
| 90 | # system. chkconfig on SUSE is actually a shell script that does some stuff and then |
| 91 | # calls insserv, their replacement. |
| 92 | # |
| 93 | |
| 94 | if (&GetDistro =~ /^SE/) { |
| 95 | # only try to chkconfig on if init script is found |
| 96 | if ( -e (&getGlobal('DIR', "initd") . "/$startup_script") ) { |
| 97 | $chkconfig_line=&getGlobal('BIN','chkconfig'); |
| 98 | &B_System("$chkconfig_line $startup_script on", "$chkconfig_line $startup_script off"); |
| 99 | # chkconfig doesn't take affect until reboot, need to restart service also |
| 100 | B_service_restart("$startup_script"); |
| 101 | return 1; #success |
| 102 | } |
| 103 | return 0; #failure |
| 104 | } |
| 105 | |
| 106 | # |
| 107 | # Run through the init script looking for the chkconfig line... |
| 108 | # |
| 109 | $retval = open CHKCONFIG,&getGlobal('DIR', "initd") . "/$startup_script"; |
| 110 | unless ($retval) { |
| 111 | &B_log("ACTION","# Didn't chkconfig_on $startup_script because we couldn't open " . &getGlobal('DIR', "initd") . "/$startup_script\n"); |
| 112 | } |
| 113 | else { |
| 114 | |
| 115 | READ_LOOP: |
| 116 | while (my $line=<CHKCONFIG>) { |
| 117 | |
| 118 | # We're looking for lines like this one: |
| 119 | # # chkconfig: 2345 10 90 |
| 120 | # OR this |
| 121 | # # chkconfig: - 10 90 |
| 122 | |
| 123 | if ($line =~ /^#\s*chkconfig:\s*([-\d]+)\s*(\d+)\s*(\d+)/ ) { |
| 124 | $runlevelinfo = $1; |
| 125 | $start_order = $2; |
| 126 | $stop_order = $3; |
| 127 | # handle a run levels arg of '-' |
| 128 | if ( $runlevelinfo eq '-' ) { |
| 129 | &B_log("ACTION","chkconfig_on saw '-' for run levels for \"$startup_script\", is defaulting to levels 3,4,5\n"); |
| 130 | $runlevelinfo = '345'; |
| 131 | } |
| 132 | @runlevels = split(//,$runlevelinfo); |
| 133 | # make sure the orders have 2 digits |
| 134 | $start_order =~ s/^(\d)$/0$1/; |
| 135 | $stop_order =~ s/^(\d)$/0$1/; |
| 136 | last READ_LOOP; |
| 137 | } |
| 138 | } |
| 139 | close CHKCONFIG; |
| 140 | |
| 141 | # Do we have what we need? |
| 142 | if ( (scalar(@runlevels) < 1) || (! $start_order =~ /^\d{2}$/) || (! $stop_order =~ /^\d{2}$/) ) { |
| 143 | # problem |
| 144 | &B_log("ERROR","# B_chkconfig_on $startup_script failed -- no valid run level/start/stop info found\n"); |
| 145 | return(-1); |
| 146 | } |
| 147 | |
| 148 | # Now, run through creating symlinks... |
| 149 | &B_log("ACTION","# chkconfig_on will use run levels ".join(",",@runlevels)." for \"$startup_script\" with S order $start_order and K order $stop_order\n"); |
| 150 | |
| 151 | $retval=0; |
| 152 | # BUG: we really ought to readdir() on &getGlobal('DIR', "rcd") to get all levels |
| 153 | foreach my $level ( "0","1","2","3","4","5","6" ) { |
| 154 | my $link = ''; |
| 155 | # we make K links in run levels not specified in the chkconfig line |
| 156 | $link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/K$stop_order" . $startup_script; |
| 157 | my $klink = $link; |
| 158 | # now we see if this is a specified run level; if so, make an S link |
| 159 | foreach my $markedlevel ( @runlevels ) { |
| 160 | if ( $level == $markedlevel) { |
| 161 | $link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/S$start_order" . $startup_script; |
| 162 | } |
| 163 | } |
| 164 | my $target = &getGlobal('DIR', "initd") ."/" . $startup_script; |
| 165 | my $local_return; |
| 166 | |
| 167 | if ( (-e "$klink") && ($klink ne $link) ) { |
| 168 | # there's a K link, but this level needs an S link |
| 169 | unless ($GLOBAL_LOGONLY) { |
| 170 | $local_return = unlink("$klink"); |
| 171 | if ( ! $local_return ) { |
| 172 | # unlinking old, bad $klink failed |
| 173 | &B_log("ERROR","Unlinking $klink failed\n"); |
| 174 | } else { |
| 175 | &B_log("ACTION","Removed link $klink\n"); |
| 176 | # If we removed the link, add a link command to the revert file |
| 177 | &B_revert_log (&getGlobal('BIN','ln') . " -s $target $klink\n"); |
| 178 | } # close what to do if unlink works |
| 179 | } # if not GLOBAL_LOGONLY |
| 180 | } # if $klink exists and ne $link |
| 181 | |
| 182 | # OK, we've disposed of any old K links, make what we need |
| 183 | if ( (! ( -e "$link" )) && ($link ne '') ) { |
| 184 | # link doesn't exist and the start/stop number is OK; make it |
| 185 | unless ($GLOBAL_LOGONLY) { |
| 186 | # create the link |
| 187 | $local_return = &B_symlink($target,$link); |
| 188 | if ($local_return) { |
| 189 | $retval++; |
| 190 | &B_log("ACTION","Created link $link\n"); |
| 191 | } else { |
| 192 | &B_log("ERROR","Couldn't create $link when trying to chkconfig on $startup_script\n"); |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | } # link doesn't exist |
| 197 | } # foreach level |
| 198 | |
| 199 | } |
| 200 | |
| 201 | if ($retval < @runlevels) { |
| 202 | $retval=0; |
| 203 | } |
| 204 | |
| 205 | $retval; |
| 206 | |
| 207 | } |
| 208 | |
| 209 | |
| 210 | ########################################################################### |
| 211 | # &B_chkconfig_off ($daemon_name) deletes the symbolic links that are |
| 212 | # named in the "# chkconfig: ___ _ _ " portion of the init.d files. We |
| 213 | # need this utility, in place of the distro's chkconfig, because of both |
| 214 | # our need to add revert functionality and our need to harden distros that |
| 215 | # are not mounted on /. |
| 216 | # |
| 217 | # chkconfig allows for a REVERT of its work by writing to an executable |
| 218 | # file &getGlobal('BFILE', "removed-symlinks"). |
| 219 | # |
| 220 | # It uses the following global variables to find the links and the init |
| 221 | # scripts, respectively: |
| 222 | # |
| 223 | # &getGlobal('DIR', "rcd") -- directory where the rc_.d subdirs can be found |
| 224 | # &getGlobal('DIR', "initd") -- directory the rc_.d directories link to |
| 225 | # |
| 226 | # Here an example of where you might use this: |
| 227 | # |
| 228 | # You'd like to tell stop running sendmail in daemon mode on boot: |
| 229 | # B_chkconfig_off("sendmail") |
| 230 | # |
| 231 | ########################################################################### |
| 232 | |
| 233 | |
| 234 | |
| 235 | sub B_chkconfig_off { |
| 236 | |
| 237 | my $startup_script=$_[0]; |
| 238 | my $retval=1; |
| 239 | |
| 240 | my $chkconfig_line; |
| 241 | my @runlevels; |
| 242 | my ($start_order,$stop_order,$filetolink); |
| 243 | |
| 244 | if (&GetDistro =~/^DB.*/) { |
| 245 | $filetolink = &getGlobal('DIR', "initd") . "/$startup_script"; |
| 246 | if (-x $filetolink) |
| 247 | { |
| 248 | # Three ways to do this in Debian: |
| 249 | # 1.- have the initd script set to 600 mode |
| 250 | # 2.- Remove the links in rcd (re-installing the package |
| 251 | # will break it) |
| 252 | # 3.- Use update-rc.d --remove (same as 2.) |
| 253 | # (jfs) |
| 254 | &B_chmod(0600,$filetolink); |
| 255 | $retval=6; |
| 256 | |
| 257 | # The second option |
| 258 | #foreach my $level ("0","1","2","3","4","5","6" ) { |
| 259 | #my $link = ''; |
| 260 | #$link = &getGlobal('DIR', "rcd") . "/rc" . "$level" . ".d/K50" . "$startup_script"; |
| 261 | #unlink($link); |
| 262 | #} |
| 263 | } |
| 264 | } |
| 265 | |
| 266 | # |
| 267 | # On SUSE, chkconfig-based rc scripts have been replaced with a whole different |
| 268 | # system. chkconfig on SUSE is actually a shell script that does some stuff and then |
| 269 | # calls insserv, their replacement. |
| 270 | # |
| 271 | elsif (&GetDistro =~ /^SE/) { |
| 272 | # only try to chkconfig off if init script is found |
| 273 | if ( -e (&getGlobal('DIR', "initd") . "/$startup_script") ) { |
| 274 | $chkconfig_line=&getGlobal('BIN','chkconfig'); |
| 275 | &B_System("$chkconfig_line $startup_script on", "$chkconfig_line $startup_script off"); |
| 276 | # chkconfig doesn't take affect until reboot, need to stop service |
| 277 | # since expectation is that the daemons are disabled even without a reboot |
| 278 | B_service_stop("$startup_script"); |
| 279 | return 1; #success |
| 280 | } |
| 281 | return 0; #failure |
| 282 | } |
| 283 | else { |
| 284 | |
| 285 | # Run through the init script looking for the chkconfig line... |
| 286 | |
| 287 | |
| 288 | $retval = open CHKCONFIG,&getGlobal('DIR', "initd") . "/$startup_script"; |
| 289 | unless ($retval) { |
| 290 | &B_log("ACTION","Didn't chkconfig_off $startup_script because we couldn't open " . &getGlobal('DIR', "initd") . "/$startup_script\n"); |
| 291 | } |
| 292 | else { |
| 293 | |
| 294 | READ_LOOP: |
| 295 | while (my $line=<CHKCONFIG>) { |
| 296 | |
| 297 | # We're looking for lines like this one: |
| 298 | # # chkconfig: 2345 10 90 |
| 299 | |
| 300 | if ($line =~ /^#\s*chkconfig:\s*([-\d]+)\s*(\d+)\s*(\d+)/ ) { |
| 301 | @runlevels=split //,$1; |
| 302 | $start_order=$2; |
| 303 | $stop_order=$3; |
| 304 | |
| 305 | |
| 306 | # Change single digit run levels to double digit -- otherwise, |
| 307 | # the alphabetic ordering chkconfig depends on fails. |
| 308 | if ($start_order =~ /^\d$/ ) { |
| 309 | $start_order = "0" . $start_order; |
| 310 | &B_log("ACTION","chkconfig_off converted start order to $start_order\n"); |
| 311 | } |
| 312 | if ($stop_order =~ /^\d$/ ) { |
| 313 | $stop_order = "0" . $stop_order; |
| 314 | &B_log("ACTION","chkconfig_off converted stop order to $stop_order\n"); |
| 315 | } |
| 316 | |
| 317 | last READ_LOOP; |
| 318 | } |
| 319 | } |
| 320 | close CHKCONFIG; |
| 321 | |
| 322 | # If we never found a chkconfig line, can we just run through all 5 |
| 323 | # rcX.d dirs from 1 to 5...? |
| 324 | |
| 325 | # unless ( $start_order and $stop_order ) { |
| 326 | # @runlevels=("1","2","3","4","5"); |
| 327 | # $start_order = "*"; $stop_order="*"; |
| 328 | # } |
| 329 | |
| 330 | # Now, run through removing symlinks... |
| 331 | |
| 332 | |
| 333 | |
| 334 | $retval=0; |
| 335 | |
| 336 | # Handle the special case that the run level specified is solely "-" |
| 337 | if ($runlevels[0] =~ /-/) { |
| 338 | @runlevels = ( "0","1","2","3","4","5","6" ); |
| 339 | } |
| 340 | |
| 341 | foreach my $level ( @runlevels ) { |
| 342 | my $link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/S$start_order" . $startup_script; |
| 343 | my $new_link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/K$stop_order" . $startup_script; |
| 344 | my $target = &getGlobal('DIR', "initd") ."/" . $startup_script; |
| 345 | my $local_return; |
| 346 | |
| 347 | |
| 348 | # Replace the S__ link in this level with a K__ link. |
| 349 | if ( -e $link ) { |
| 350 | unless ($GLOBAL_LOGONLY) { |
| 351 | $local_return=unlink $link; |
| 352 | if ($local_return) { |
| 353 | $local_return=symlink $target,$new_link; |
| 354 | unless ($local_return) { |
| 355 | &B_log("ERROR","Linking $target to $new_link failed.\n"); |
| 356 | } |
| 357 | } |
| 358 | else { # unlinking failed |
| 359 | &B_log("ERROR","Unlinking $link failed\n"); |
| 360 | } |
| 361 | |
| 362 | } |
| 363 | if ($local_return) { |
| 364 | $retval++; |
| 365 | &B_log("ACTION","Removed link $link\n"); |
| 366 | |
| 367 | # |
| 368 | # If we removed the link, add a link command to the revert file |
| 369 | # Write out the revert information for recreating the S__ |
| 370 | # symlink and deleting the K__ symlink. |
| 371 | &B_revert_log(&getGlobal('BIN',"ln") . " -s $target $link\n"); |
| 372 | &B_revert_log(&getGlobal('BIN',"rm") . " -f $new_link\n"); |
| 373 | } |
| 374 | else { |
| 375 | &B_log("ERROR","B_chkconfig_off $startup_script failed\n"); |
| 376 | } |
| 377 | |
| 378 | } |
| 379 | } # foreach |
| 380 | |
| 381 | } # else-unless |
| 382 | |
| 383 | } # else-DB |
| 384 | if ($retval < @runlevels) { |
| 385 | $retval=0; |
| 386 | } |
| 387 | |
| 388 | $retval; |
| 389 | |
| 390 | } |
| 391 | |
| 392 | |
| 393 | ########################################################################### |
| 394 | # &B_service_start ($daemon_name) |
| 395 | # Starts service on RedHat/SUSE-based Linux distributions which have the |
| 396 | # service command: |
| 397 | # |
| 398 | # service $daemon_name start |
| 399 | # |
| 400 | # Other Linux distros that also support this method of starting |
| 401 | # services can be added to use this function. |
| 402 | # |
| 403 | # Here an example of where you might use this: |
| 404 | # |
| 405 | # You'd like to tell the system to start the vsftpd daemon: |
| 406 | # &B_service_start("vsftpd") |
| 407 | # |
| 408 | # Uses &B_System in HP_API.pm |
| 409 | # To match how the &B_System command works this method: |
| 410 | # returns 1 on success |
| 411 | # returns 0 on failure |
| 412 | ########################################################################### |
| 413 | |
| 414 | sub B_service_start { |
| 415 | |
| 416 | my $daemon=$_[0]; |
| 417 | |
| 418 | if ( (&GetDistro !~ /^SE/) and (&GetDistro !~ /^RH/) and |
| 419 | (&GetDistro !~ /^RHFC/) and (&GetDistro !~ /^MN/) ) { |
| 420 | &B_log("ERROR","Tried to call service_start on a system lacking a service command! Internal Bastille error."); |
| 421 | return undef; |
| 422 | } |
| 423 | |
| 424 | # only start service if init script is found |
| 425 | if ( -e (&getGlobal('DIR', 'initd') . "/$daemon") ) { |
| 426 | &B_log("ACTION","# service_start enabling $daemon\n"); |
| 427 | |
| 428 | my $service_cmd=&getGlobal('BIN', 'service'); |
| 429 | if ($service_cmd) { |
| 430 | # Start the service, |
| 431 | # Also provide &B_System revert command |
| 432 | |
| 433 | return (&B_System("$service_cmd $daemon start", |
| 434 | "$service_cmd $daemon stop")); |
| 435 | } |
| 436 | } |
| 437 | |
| 438 | # init script not found, do not try to start, return failure |
| 439 | return 0; |
| 440 | } |
| 441 | |
| 442 | ########################################################################### |
| 443 | # &B_service_stop ($daemon_name) |
| 444 | # Stops service on RedHat/SUSE-based Linux distributions which have the |
| 445 | # service command: |
| 446 | # |
| 447 | # service $daemon_name stop |
| 448 | # |
| 449 | # Other Linux distros that also support this method of starting |
| 450 | # services can be added to use this function. |
| 451 | # Stops service. |
| 452 | # |
| 453 | # |
| 454 | # Here an example of where you might use this: |
| 455 | # |
| 456 | # You'd like to tell the system to stop the vsftpd daemon: |
| 457 | # &B_service_stop("vsftpd") |
| 458 | # |
| 459 | # Uses &B_System in HP_API.pm |
| 460 | # To match how the &B_System command works this method: |
| 461 | # returns 1 on success |
| 462 | # returns 0 on failure |
| 463 | ########################################################################### |
| 464 | |
| 465 | sub B_service_stop { |
| 466 | |
| 467 | my $daemon=$_[0]; |
| 468 | |
| 469 | if ( (&GetDistro !~ /^SE/) and (&GetDistro !~ /^RH/) and |
| 470 | (&GetDistro !~ /^RHFC/) and (&GetDistro !~ /^MN/) ) { |
| 471 | &B_log("ERROR","Tried to call service_stop on a system lacking a service command! Internal Bastille error."); |
| 472 | return undef; |
| 473 | } |
| 474 | |
| 475 | # only stop service if init script is found |
| 476 | if ( -e (&getGlobal('DIR', 'initd') . "/$daemon") ) { |
| 477 | &B_log("ACTION","# service_stop disabling $daemon\n"); |
| 478 | |
| 479 | my $service_cmd=&getGlobal('BIN', 'service'); |
| 480 | if ($service_cmd) { |
| 481 | |
| 482 | # Stop the service, |
| 483 | # Also provide &B_System revert command |
| 484 | |
| 485 | return (&B_System("$service_cmd $daemon stop", |
| 486 | "$service_cmd $daemon start")); |
| 487 | } |
| 488 | } |
| 489 | |
| 490 | # init script not found, do not try to stop, return failure |
| 491 | return 0; |
| 492 | } |
| 493 | |
| 494 | |
| 495 | ########################################################################### |
| 496 | # &B_service_restart ($daemon_name) |
| 497 | # Restarts service on RedHat/SUSE-based Linux distributions which have the |
| 498 | # service command: |
| 499 | # |
| 500 | # service $daemon_name restart |
| 501 | # |
| 502 | # Other Linux distros that also support this method of starting |
| 503 | # services can be added to use this function. |
| 504 | # |
| 505 | # Here an example of where you might use this: |
| 506 | # |
| 507 | # You'd like to tell the system to restart the vsftpd daemon: |
| 508 | # &B_service_restart("vsftpd") |
| 509 | # |
| 510 | # Uses &B_System in HP_API.pm |
| 511 | # To match how the &B_System command works this method: |
| 512 | # returns 1 on success |
| 513 | # returns 0 on failure |
| 514 | ########################################################################### |
| 515 | |
| 516 | sub B_service_restart { |
| 517 | |
| 518 | my $daemon=$_[0]; |
| 519 | |
| 520 | if ( (&GetDistro !~ /^SE/) and (&GetDistro !~ /^RH/) and |
| 521 | (&GetDistro !~ /^RHFC/) and (&GetDistro !~ /^MN/) ) { |
| 522 | &B_log("ERROR","Tried to call service_restart on a system lacking a service command! Internal Bastille error."); |
| 523 | return undef; |
| 524 | } |
| 525 | |
| 526 | # only restart service if init script is found |
| 527 | if ( -e (&getGlobal('DIR', 'initd') . "/$daemon") ) { |
| 528 | &B_log("ACTION","# service_restart re-enabling $daemon\n"); |
| 529 | |
| 530 | my $service_cmd=&getGlobal('BIN', 'service'); |
| 531 | if ($service_cmd) { |
| 532 | |
| 533 | # Restart the service |
| 534 | return (&B_System("$service_cmd $daemon restart", |
| 535 | "$service_cmd $daemon restart")); |
| 536 | } |
| 537 | } |
| 538 | |
| 539 | # init script not found, do not try to restart, return failure |
| 540 | return 0; |
| 541 | } |
| 542 | |
| 543 | ########################################################################### |
| 544 | # &B_is_service_off($;$) |
| 545 | # |
| 546 | # Runs the specified test to determine whether or not the question should |
| 547 | # be answered. |
| 548 | # |
| 549 | # return values: |
| 550 | # NOTSECURE_CAN_CHANGE()/0: service is on |
| 551 | # SECURE_CANT_CHANGE()/1: service is off |
| 552 | # undef: test is not defined |
| 553 | ########################################################################### |
| 554 | |
| 555 | sub B_is_service_off ($){ |
| 556 | my $service=$_[0]; |
| 557 | |
| 558 | if(&GetDistro =~ "^HP-UX"){ |
| 559 | #die "Why do I think I'm on HPUX?!\n"; |
| 560 | return &checkServiceOnHPUX($service); |
| 561 | } |
| 562 | elsif ( (&GetDistro =~ "^RH") || (&GetDistro =~ "^SE") ) { |
| 563 | return &checkServiceOnLinux($service); |
| 564 | } |
| 565 | else { |
| 566 | &B_log("DEBUG","B_is_service off called for unsupported OS"); |
| 567 | # not yet implemented for other distributions of Linux |
| 568 | # when GLOBAL_SERVICE, GLOBAL_SERVTYPE and GLOBAL_PROCESS are filled |
| 569 | # in for Linux, then |
| 570 | # at least inetd and inittab services should be similar to the above, |
| 571 | # whereas chkconfig would be used on some Linux distros to determine |
| 572 | # if non-inetd/inittab services are running at boot time. Looking at |
| 573 | # processes should be similar. |
| 574 | return undef; |
| 575 | } |
| 576 | } |
| 577 | |
| 578 | ########################################################################### |
| 579 | # &checkServiceOnLinux($service); |
| 580 | # |
| 581 | # Checks if the given service is running on a Linux system. This is |
| 582 | # called by B_is_Service_Off(), which is the function that Bastille |
| 583 | # modules should call. |
| 584 | # |
| 585 | # Return values: |
| 586 | # NOTSECURE_CAN_CHANGE() if the service is on |
| 587 | # SECURE_CANT_CHANGE() if the service is off |
| 588 | # undef if the state of the service cannot be determined |
| 589 | # |
| 590 | ########################################################################### |
| 591 | sub checkServiceOnLinux($) { |
| 592 | my $service=$_[0]; |
| 593 | |
| 594 | # get the list of parameters which could be used to initiate the service |
| 595 | # (could be in /etc/rc.d/rc?.d, /etc/inetd.conf, or /etc/inittab, so we |
| 596 | # check all of them) |
| 597 | |
| 598 | my @params = @{ &getGlobal('SERVICE', $service) }; |
| 599 | my $chkconfig = &getGlobal('BIN', 'chkconfig'); |
| 600 | my $grep = &getGlobal('BIN', 'grep'); |
| 601 | my $inittab = &getGlobal('FILE', 'inittab'); |
| 602 | my $serviceType = &getGlobal('SERVTYPE', $service);; |
| 603 | |
| 604 | # A kludge to get things running because &getGlobal('SERVICE' doesn't |
| 605 | # return the expected values. |
| 606 | @params = (); |
| 607 | push (@params, $service); |
| 608 | |
| 609 | foreach my $param (@params) { |
| 610 | &B_log("DEBUG","Checking to see if service $service is off.\n"); |
| 611 | |
| 612 | if ($serviceType =~ /rc/) { |
| 613 | my $on = &B_Backtick("$chkconfig --list $param 2>&1"); |
| 614 | if ($on =~ /^$param:\s+unknown/) { |
| 615 | # This service isn't installed on the system |
| 616 | return NOT_INSTALLED(); |
| 617 | } |
| 618 | if ($on =~ /^error reading information on service $param: No such file or directory/) { |
| 619 | # This service isn't installed on the system |
| 620 | return NOT_INSTALLED(); |
| 621 | } |
| 622 | if ($on =~ /^error/) { |
| 623 | # This probably |
| 624 | &B_log("DEBUG","chkconfig returned: $param=$on\n"); |
| 625 | return undef; |
| 626 | } |
| 627 | $on =~ s/^$param\s+//; # remove the service name and spaces |
| 628 | $on =~ s/[0-6]:off\s*//g; # remove any runlevel:off entries |
| 629 | $on =~ s/:on\s*//g; # remove the :on from the runlevels |
| 630 | # what remains is a list of runlevels in which the service is on, |
| 631 | # or a null string if it is never turned on |
| 632 | chomp $on; # newline should be gone already (\s) |
| 633 | &B_log("DEBUG","chkconfig returned: $param=$on\n"); |
| 634 | |
| 635 | if ($on =~ /^\d+$/) { |
| 636 | # service is not off |
| 637 | ########################### BREAK out, don't skip question |
| 638 | return NOTSECURE_CAN_CHANGE(); |
| 639 | } |
| 640 | } |
| 641 | elsif ($serviceType =~ /inet/) { |
| 642 | my $on = &B_Backtick("$chkconfig --list $param 2>&1"); |
| 643 | if ($on =~ /^$param:\s+unknown/) { |
| 644 | # This service isn't installed on the system |
| 645 | return NOT_INSTALLED(); |
| 646 | } |
| 647 | if ($on =~ /^error reading information on service $param: No such file or directory/) { |
| 648 | # This service isn't installed on the system |
| 649 | return NOT_INSTALLED(); |
| 650 | } |
| 651 | if ($on =~ /^error/ ) { |
| 652 | # Something else is wrong? |
| 653 | # return undef |
| 654 | return undef; |
| 655 | } |
| 656 | if ($on =~ tr/\n// > 1) { |
| 657 | $on =~ s/^xinetd.+\n//; |
| 658 | } |
| 659 | $on =~ s/^\s*$param:?\s+//; # remove the service name and spaces |
| 660 | chomp $on; # newline should be gone already (\s) |
| 661 | &B_log("DEBUG","chkconfig returned: $param=$on\n"); |
| 662 | |
| 663 | if ($on =~ /^on$/) { |
| 664 | # service is not off |
| 665 | ########################### BREAK out, don't skip question |
| 666 | return NOTSECURE_CAN_CHANGE(); |
| 667 | } |
| 668 | } |
| 669 | else { |
| 670 | # perhaps the service is started by inittab |
| 671 | my $inittabline = &B_Backtick("$grep -E '^[^#].{0,3}:.*:.+:.*$param' $inittab"); |
| 672 | if ($inittabline =~ /.+/) { # . matches anything except newlines |
| 673 | # service is not off |
| 674 | &B_log("DEBUG","Checking inittab; found $inittabline\n"); |
| 675 | ########################### BREAK out, don't skip question |
| 676 | return NOTSECURE_CAN_CHANGE(); |
| 677 | } |
| 678 | } |
| 679 | } # foreach my $param |
| 680 | |
| 681 | |
| 682 | # boot-time parameters are not set; check processes |
| 683 | # Note the checkProcsforService returns INCONSISTENT() if a process is found |
| 684 | # assuming the checks above |
| 685 | return &checkProcsForService($service); |
| 686 | } |
| 687 | |
| 688 | 1; |
| 689 | |
| 690 | |