27 3.44 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#
# Extract the current image hostkeys from the frisbee MFS.
# Also extract the current root password from the MFS and
# insert into the sitevar.
#
use strict;
use libinstall;
use installvars;
use libEmulab;

my $MFSROOT = "$TFTP_DIR/frisbee/boot/mfsroot";

sub InstallUpdate($$)
{
    my ($version, $phase) = @_;

17 18 19
    return 0
	if (IMPOTENT_MODE());

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
    if ($phase eq "pre") {
	Phase "hostkeys", "Grabbing existing keys and root password", sub {
	    my $failed = 0;
	    my $done   = 1;
	    my @output = ();
	    my $passhash;

	    #
	    # If the root password sitevar is not set, we need to proceed.
	    #
	    if (!GetSiteVar("images/root_password", \$passhash)) {
		PhaseFail("Could not get sitevar images/root_password");
	    }
	    $done = 0
		if ($passhash eq "");
		
	    Phase "keydir", "Creating $IMAGEKEYS_DIR", sub {
		DoneIfExists($IMAGEKEYS_DIR);
		mkdir "$IMAGEKEYS_DIR",0755 or
		    PhaseFail("Unable to create $IMAGEKEYS_DIR: $!");
	    };
	    my %keytypes = (
		"rsa1"	=> "ssh_host_key",
		"rsa"	=> "ssh_host_rsa_key",
		"dsa"	=> "ssh_host_dsa_key");

	    foreach my $type (keys(%keytypes)) {
		my $name = $keytypes{$type};
		$done = 0
		    if (! -e "$IMAGEKEYS_DIR/$name");
	    }
	    PhaseSkip("keys/password exist")
		if ($done);

	    Phase "point", "Creating mountpoint for MFS", sub {
		DoneIfExists("/mfsmnt");
		mkdir "/mfsmnt", 0755 or
		    PhaseFail("Unable to create /mfsmnt: $!");
	    };


	    if (-e $MFSROOT) {
		if ($FBSD_MAJOR >= 5) {
		    ExecQuietFatal("mdconfig -a -t vnode -f $MFSROOT -u 2");
		    if (ExecQuiet("mount /dev/md2 /mfsmnt")) {
			ExecQuiet("mdconfig -d -u 2");
			PhaseFail("mount error");
		    }
		}
		else {
		    ExecQuietFatal("vnconfig -c vn1 $MFSROOT");
		    if (ExecQuiet("mount /dev/vn1 /mfsmnt")) {
			ExecQuiet("vnconfig -u vn1");
			PhaseFail("mount error");
		    }
		}
	    }
	    # Lets hope they are there. If not, we just make up new ones.
	    Phase "imagekeys", "Copying/Creating image host keys", sub {
		foreach my $type (keys(%keytypes)) {
		    my $name = $keytypes{$type};

		    Phase $type, "$type host key", sub {
			DoneIfExists("$IMAGEKEYS_DIR/$name");

			if (-e "/mfsmnt/etc/ssh/$name") {
			    $failed = ExecQuiet("$CP -p /mfsmnt/etc/ssh/$name ".
						"       /mfsmnt/etc/ssh/$name.pub ".
						"       $IMAGEKEYS_DIR");
			}
			else {
			    $failed = ExecQuiet("$SSH_KEYGEN -t $type -N '' ".
						"   -f $IMAGEKEYS_DIR/$name");
			}
		    };
		    # Stop if we have any problems.
		    if ($failed) {
			@output = LastOutput();
			last;
		    }
		}
	    };
	    if ($passhash eq "") {
		my $master = "/etc/master.passwd";
		$master    = "/mfsmnt/$master" if (-e $MFSROOT);
		
		my ($status,@lines) = ExecQuiet("grep root $master");
		if ($status) {
		    $failed = 1;
		    @output = LastOutput();
		}
		else {
		    $passhash = $lines[0];
		    if ($passhash =~ /root:([^:]*)/) {
			$passhash = $1;
		    }
		    else {
			$failed = 1;
			@output = ("Could not parse root line");
		    }
		    if (!SetSiteVar("images/root_password", $passhash)) {
			$failed = 1;
			@output = ("SetSiteVar failed");
		    }
		}
	    }

	    if (-e $MFSROOT) {
		ExecQuietFatal("umount /mfsmnt");
		if ($FBSD_MAJOR >= 5) {
		    ExecQuietFatal("mdconfig -d -u 2");
		}
		else {
		    ExecQuietFatal("vnconfig -u vn1");
		}
	    }
	    if ($failed) {
		my $msg = join(' ', @output);
		PhaseFail("Unable to execute: '$msg'");
	    }
	    PhaseSucceed("got all keys");
	};
    }
    return 0;
}
1;

# Local Variables:
# mode:perl
# End: