#!/usr/bin/perl #Copyright (c) 2009 Eucalyptus Systems, Inc. # #This program is free software: you can redistribute it and/or modify #it under the terms of the GNU General Public License as published by #the Free Software Foundation, only version 3 of the License. # #This file is distributed in the hope that it will be useful, but WITHOUT #ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License #for more details. # #You should have received a copy of the GNU General Public License along #with this program. If not, see . # #Please contact Eucalyptus Systems, Inc., 130 Castilian #Dr., Goleta, CA 93101 USA or visit #if you need additional information or have any questions. # #This file may incorporate work covered under the following copyright and #permission notice: # # Software License Agreement (BSD License) # # Copyright (c) 2008, Regents of the University of California # # # Redistribution and use of this software in source and binary forms, with # or without modification, are permitted provided that the following # conditions are met: # # Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER # OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF # THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE # LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS # SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING # IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA # BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN # THE REGENTS’ DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT # OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR # WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH # ANY SUCH LICENSES OR RIGHTS. # delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; $ENV{'PATH'}='/bin:/usr/bin:/sbin:/usr/sbin/'; $eucaconf=$ENV{'EUCALYPTUS'} . "/etc/eucalyptus/eucalyptus.conf"; if (open(FH, "$eucaconf")) { while() { chomp; my $line = $_; if ($line =~ /^\s*VNET_MODE="(.*)"/) { my $mode = $1; if (($mode =~ /MANAGED/) ) { # only do key injection if we're not in managed mode print "done\n"; exit(0); } } } close(FH); } #$MOUNT=untaint(`which mount`); #$UMOUNT=untaint(`which umount`); #$MOUNT=untaint("/tmp/euca_mountwrap"); #$UMOUNT=untaint("/tmp/euca_mountwrap"); $MKDIR=untaint(`which mkdir`); $RMDIR=untaint(`which rmdir`); $CHOWN=untaint(`which chown`); $CHMOD=untaint(`which chmod`); $MKTEMP=untaint(`which mktemp`); $TUNE2FS=untaint(`which tune2fs`); $LOSETUP=untaint(`which losetup`); # check binaries if (!-x $MKDIR || !-x $RMDIR || !-x $CHOWN || !-x $CHMOD || !-x $MKTEMP || !-x $LOSETUP) { print STDERR "add_key cannot find all required binaries\n"; do_exit(1); } # check input params $mounter = untaint(shift @ARGV); $offset = untaint(shift @ARGV); $img = untaint(shift @ARGV); $key = shift @ARGV; # untaint later $tmpfile = ""; $loopdev = ""; $mounted = 0; $attached = 0; if (!-f "$img" || !-x "$mounter") { print STDERR "add_key cannot verify inputs: mounter=$mounter img=$img\n"; do_exit(1); } if ($offset eq "") { $offset = 0; } chomp($tmpfile = untaint(`$MKTEMP -d`)); if (! -d "$tmpfile") { print STDERR "no dir: $tmpfile"; do_exit(1); } # find loop dev and attach image to it for ($i=0; $i<10 && !$attached; $i++) { $loopdev=untaint(`$LOSETUP -f`); if ($loopdev ne "") { if ($offset == 0) { $rc = system("$LOSETUP $loopdev $img"); } else { $rc = system("$LOSETUP -o $offset $loopdev $img"); } if (!$rc) { $attached = 1; } else { system("$LOSETUP -d $loopdev"); } } } if (!$attached) { print STDERR "cannot attach a loop device\n"; do_exit(1); } if (system("$TUNE2FS -c 0 -i 0 $loopdev >/dev/null 2>&1")) { print STDERR "cmd: $TUNE2FS -c 0 -i 0 $loopdev\n"; # do_exit(1); } # without a key, add_key.pl just runs tune2fs if (not defined($key)) { do_exit(0); } $key = untaint($key); if (!-f "$key") { print STDERR "add_key cannot verify inputs: key=$key\n"; do_exit(1); } if (system("$mounter mount $loopdev $tmpfile")) { print STDERR "cannot mount: $mounter mount $loopdev $tmpfile\n"; do_exit(1); } $mounted = 1; if ( !-d "$tmpfile/root/.ssh" ) { if (system("$MKDIR $tmpfile/root/.ssh")) { print STDERR "cmd: $MKDIR $tmpfile/root/.ssh\n"; do_exit(1); } system("$CHOWN root $tmpfile/root/.ssh"); system("$CHMOD 0700 $tmpfile/root/.ssh"); } if (!open(OFH, ">>$tmpfile/root/.ssh/authorized_keys")) { print STDERR "cannot write to: $tmpfile/root/.ssh/authorized_keys\n"; do_exit(1); } print OFH "\n"; if (!open(FH, "$key")) { print STDERR "cannot read from: $key\n"; do_exit(1); } while() { chomp; print OFH "$_\n"; } close(FH); close(OFH); system("$CHOWN root $tmpfile/root/.ssh/authorized_keys"); system("$CHMOD 0600 $tmpfile/root/.ssh/authorized_keys"); do_exit(0); sub do_exit() { $e = shift; if ($mounted && ($tmpfile ne "")) { system("$mounter umount $tmpfile"); } if ($attached && ($loopdev ne "")) { system("$LOSETUP -d $loopdev"); } if ($tmpfile ne "") { system("$RMDIR $tmpfile"); } if (-f "$img") { # be conservative about deleting loopback devices open(RFH, "losetup -a|"); while() { chomp; my $line = $_; if ($line =~ /$img/) { if ($line =~ /(\/dev\/loop\d+).*/) { system("$LOSETUP -d $1"); } } } close(RFH); } exit($e); } sub untaint() { $str = shift; if ($str =~ /^([ &:#-\@\w.]+)$/) { $str = $1; #data is now untainted } else { $str = ""; } return($str); }