#!/usr/bin/perl # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html #(C)IBM Corp # #----------------------------------------------------------------------------- =head1 aixremoteshell This sets up the remote shell for root on the AIX node,such that root can login with no password. The default is /bin/rsh and /bin/rcp but can be overriden by setting the useSSHonAIX attribute in the site table to yes, in which case we will use ssh/scp. =cut #----------------------------------------------------------------------------- # # If USESSHONAIX does not exist or is no or 0 then # setup .rhosts on the node # else (ssh) # setup the ssh keys on the node # end # MAIN use strict; use IO::Socket; my $useSocketSSL=eval { require IO::Socket::SSL; }; if ($useSocketSSL) { require IO::Socket::SSL; } my $rc = 0; # Override from site table my $usesshonaix = $ENV{'USESSHONAIX'}; my $master = $ENV{'MASTER'}; my $node = $ENV{'NODE'}; my $msg; my $home; my $cmd; my $username = "root"; my @root = split ':', (`/bin/grep ^$username /etc/passwd 2>&1`); $home = $root[5]; # root home directory must be root system $rc = &runcmd("chown root $home"); if ($rc != 0) { my $msg = "It fails to chown root $home"; if (defined($logenable)) { `logger -t xcat $msg`; } exit 1; } $rc = &runcmd("chgrp system $home"); if ($rc != 0) { my $msg = "It fails to chgrp system $home"; `logger -t xcat $msg`; exit 1; } $usesshonaix =~ tr/a-z/A-Z/; # convert to upper if ((!defined($usesshonaix)) || ($usesshonaix eq "0") || ($usesshonaix eq "NO")) { # setting up rsh # setup .rhosts if not already setup $cmd = "/bin/grep \"^$master root\" /.rhosts"; `$cmd 2>&1`; my $rc = $? >> 8; if ($rc) { # if not found, then add entry in .rhosts &runcmd("/bin/echo $master root >> /.rhosts"); chmod 0600, "/.rhosts"; } } else { # setting up ssh if (&setupSSH != 0) { my $msg = "Failed to setup ssh on $node.\n"; `logger -t xcat $msg`; # print $msg; exit 0; } } exit 0; # # Subroutines # sub setupSSH { my $sshdconfig = "/etc/ssh/sshd_config"; my $sshconfig = "/etc/ssh/ssh_config"; if (-e $sshdconfig) { # ssh installed my $tmp="$sshdconfig.ORIG"; if (!(-e "$sshdconfig.ORIG")) { &runcmd("cp $sshdconfig $sshdconfig.ORIG"); } &runcmd("echo \"KeyRegenerationInterval 0\" >>$sshdconfig"); &runcmd("echo \"X11Forwarding yes\" >>$sshdconfig"); &runcmd("echo \"MaxStartups 1024\" >>$sshdconfig"); #&runcmd("echo \"PasswordAuthentication no\" >>$sshdconfig"); if (!(-e "$sshconfig.ORIG")) { &runcmd("cp $sshconfig $sshconfig.ORIG"); } &runcmd("echo \"StrictHostKeyChecking no\" >>$sshconfig"); } else { # ssh not installed my $msg = "Failed to setup ssh on $node, ssh not installed. \n"; `logger -t xcat $msg`; exit 0; } if (-e "/xcatpost/_ssh") { # ssh public key available $rc = &runcmd("mkdir -p /.ssh"); if ($rc == 0) { $rc = &runcmd("cp -fp /xcatpost/_ssh/* /.ssh"); if ($rc == 0) { $rc = &runcmd("chmod 0700 /.ssh"); $rc = &runcmd("chmod 0600 /.ssh/*"); } } } else { # ssh keys not available my $msg = "Failed to setup ssh on $node, ssh keys not available. \n"; `logger -t xcat $msg`; exit 0; } # get the name of my service node/NIM master from /etc/xcatinfo # ! use value of MASTER env variable instead $::servnode = $master; my $response=&getresponse("ssh_dsa_hostkey"); if (defined ($response) ) { my $fd; my $filename = "/etc/ssh/ssh_host_dsa_key"; &runcmd("mkdir -p /etc/ssh"); open($fd, '>',$filename); print $fd $response; close($fd); # set the permissions my $cmd = "chmod 600 $filename > /dev/null 2>&1"; &runcmd($cmd); } else { $msg = "aixremoteshell: Could not get ssh_host_dsa_key file.\n"; `logger -t xcat $msg`; } my $response=&getresponse("ssh_rsa_hostkey"); if (defined ($response) ) { my $fd; my $filename = "/etc/ssh/ssh_host_rsa_key"; &runcmd("mkdir -p /etc/ssh"); open($fd, '>',$filename); print $fd $response; close($fd); # set the permissions my $cmd = "chmod 600 $filename > /dev/null 2>&1"; &runcmd($cmd); } else { $msg = "aixremoteshell: Could not get ssh_host_rsa_key file.\n"; `logger -t xcat $msg`; } if ( -f "/etc/xCATSN") { &runcmd("mkdir -p /etc/xcat/hostkeys; cp /etc/ssh/ssh* /etc/xcat/hostkeys/. > /dev/null 2>&1"); } my $response=&getresponse("ssh_root_key"); if (defined ($response) ) { my $fd; my $filename = "/.ssh/id_rsa"; &runcmd("mkdir -p /.ssh"); open($fd, '>',$filename); print $fd $response; close($fd); # set the permissions #TODO - what perms are needed??? my $cmd = "chmod 600 $filename > /dev/null 2>&1"; &runcmd($cmd); if ( -f "/.ssh/id_rsa" ) { &runcmd("ssh-keygen -y -f /.ssh/id_rsa > /.ssh/id_rsa.pub"); } } else { $msg = "aixremoteshell: Could not get id_rsa file.\n"; `logger -t xcat $msg`; } return 0; } ##################################################### # # getresponse # Request info from xcatd on the management node # # - uses SSL socket on port 3001 to connect to MN xcatd # to make the request for info # ##################################################### sub getresponse { my ($req) = @_; my $port = "3001"; # open listener connection to wait for check from management node my $lpid = &openlistener(); # open a socket to request credentials my $sock = IO::Socket::SSL->new( PeerAddr => $::servnode, PeerPort => $port, Proto => 'tcp', ); unless ($sock) { my $msg = "aixremoteshell: Cannot connect to host \'$::servnode\'\n"; `logger -t xcat $msg`; #print $msg; kill 2, $lpid; return undef; } # request must be in XML format print $sock "\n"; print $sock " getcredentials\n"; print $sock " $req\n"; print $sock " 300\n"; print $sock "\n"; #TODO - do we have to try again after waiting for a bit???? my $response=''; my $line; while (defined ($line = <$sock>)) { # skip xml tags next if ($line =~ /^\s*/) { last: } $response .= $line; } close ($sock); kill 2, $lpid; if ($response) { return $response; } return undef; } ##################################################### # # openlistener # - fork a child process to respond to a check from the MN # ##################################################### sub openlistener { my $node = $ENV{'NODE'}; # fork a child process to open a socket to listen for communication # from the server my $pid = fork; unless (defined $pid) { # fork failed $msg = "aixremoteshell: Could not fork process.\n"; `logger -t xcat $msg`; print $msg; return undef; } if ($pid != 0) { # This is the parent process, just return return $pid; } my $listener = IO::Socket::INET->new( LocalPort => '300', Proto => 'tcp', Listen => '64', Reuse => 1 ); unless ($listener) { my $msg = "aixremoteshell: Cannot open socket on \'$node\'\n"; `logger -t xcat $msg`; print $msg; exit 1; } # xcatd sends a quick req to see if we are really asking # for info - this listener checks for the req and says ok my $client; while ($client = $listener->accept()) { # $client is the new connection my $text=<$client>; # see if we got "CREDOKBYYOU?" if ($text =~ /CREDOKBYYOU?/) { print $client "CREDOKBYME"; close($client); close($listener); exit 0; } close($client); } close($client); close($listener); exit 0; } # # run the command # sub runcmd { my ($cmd) = @_; my $rc = 0; $cmd .= ' 2>&1'; $::outref = `$cmd`; if ($?) { $rc = $? >> 8; if ($rc > 0) { my $msg = "$cmd returned rc=$rc @$::outref\n"; `logger -t xcat $msg`; # print $msg; } } return 0; }