Archive for March, 2006

Back to the future with VMware Server

Sunday, March 26th, 2006

A few weeks ago VMware released their free VMware Server Beta virtualization software which I downloaded and installed on my little Debian slave, an AMD Duron 1300 with 512MB RAM. This machine normally holds backups of my main computer and serves as a general purpose Linux box and webserver for me at home. Well, I had to learn that there is still much more that you can do with it.

Every now and then I wished to have more than one Linux box so that I could easily try something out and get rid of it afterwards without touching my default installation. And, yes, very seldom I’d like to have a Windows 98 environment to compile and test an older piece of software. But yet I was neither willing to provide a third computer for that nor to struggle with drive images or multi-boot setups.

And now these wishes become true at no cost with VMware Server. You see, I am excited. So I took the following screenshots to demonstrate how simple a new virtual machine can be brought to life. The shots are taken from VMware Server Console running on my Windows XP main machine to control the Debian slave with VMware Server.

You may complain about the one or another shot being redundant, but my intention is to also produce an authentic impression of this beautiful installation process that we all got to like that much over the years. Of course, the good old Windows 98 startup disk had been prepared and inserted into Debian slave’s disk drive ;-)


Perl – Apache::Htpasswd

Monday, March 13th, 2006

Imagine you set up dozens of virtual hosts and want each of them to have an individual default password for a protected area, i.e. a logfile directory being accessible via http://vhost/logs/. Putting .htaccess files into the target directories is step one and fairly simple. Whereas step two, adding the .htpasswd files, may end up unhandily, either juggling with cleartext and encrypted passwords or falling back on system() calls of htpasswd(2).

The example below shows how this can be handled with the modules Apache::Htpasswd and String::Random. Just provide a filename and a username, the subroutine will create the .htaccess file, add the user with a new random password and return the cleartext password to be handed out to your customer.


use String::Random;
use Apache::Htpasswd;

sub DefaultHtpasswd($$) {
  my($Filename,$Username) = @_;

  my $RandomString = new String::Random;
  my $PasswdString = $RandomString->randpattern('nnCcCnCc');

  my $Htpasswd = new Apache::Htpasswd($Filename);

  $Htpasswd->htpasswd($Username, $PasswdString, 1)
  or die($Htpasswd->error);

  return($PasswdString);
}


Perl – CatOS config via SNMP / TFTP

Sunday, March 12th, 2006

Below is a piece of code that I wrote a while ago when setting up a backup mechanism to automatically retrieve (and put) configuration files from (or to) Cisco Catalyst switches (running CatOS).

Usually, as a perl programmer with a new challenge, you will first do a search on CPAN and almost probably find the answer or at least a hint. But at that time I decided not to go for the Cisco::Conf module that uses telnet instead of SNMP commands and operates in writeNet mode. Today, the more recent Cisco::CopyConfig should be the module of choice, but it uses ccCopy mode and works for IOS devices only.

My example uses tftpGrp mode, a third variant, that has not yet been packed in a module.

Short explanation: Subroutine, give it your Catalyst’s hostname or IP address ($Host) and SNMP write community string ($Cty), the TFTP server’s hostname or IP address ($Server) and the filename on TFTP server ($Filename). The action ($Action) to be performed by Catalyst is given in clear text, see %Actions for allowed values. Module number ($Module) and timeout in seconds ($Timeout) are optional arguments and default to standard values if omitted. Returns result in clear text, see %Results for possible values.

Don’t forget to touch and chmod 666 file on TFTP server before transfer and remove it afterwards. Have fun!


use Convert::BER;
use Net::SNMP;

sub tftpGrp {
  my($Host,$Cty,$Server,$Filename,
     $Action,$Module,$Timeout) = @_; 
  ################################
  my %OIDs = (
   'tftpHost'   => '1.3.6.1.4.1.9.5.1.5.1.0',
   'tftpFile'   => '1.3.6.1.4.1.9.5.1.5.2.0',
   'tftpModule' => '1.3.6.1.4.1.9.5.1.5.3.0',
   'tftpAction' => '1.3.6.1.4.1.9.5.1.5.4.0',
   'tftpResult' => '1.3.6.1.4.1.9.5.1.5.5.0',
  );

  my %Actions = (
   'other'          => 1,
   'downloadConfig' => 2,
   'uploadConfig'   => 3,
   'downloadSw'     => 4,
   'uploadSw'       => 5,
   'downloadFw'     => 6,
   'uploadFw'       => 7,
  );

  my %Results = (
   1  => 'inProgress',
   2  => 'success',
   3  => 'noResponse',
   4  => 'tooManyRetries',
   5  => 'noBuffers',
   6  => 'noProcesses',
   7  => 'badChecksum',
   8  => 'badLength',
   9  => 'badFlash',
   10 => 'serverError',
   11 => 'userCanceled',
   12 => 'wrongCode',
   13 => 'fileNotFound',
   14 => 'invalidTftpHost',
   15 => 'invalidTftpModule',
   16 => 'accessViolation',
   17 => 'unknownStatus',
   18 => 'invalidStorageDevice',
   19 => 'insufficientSpaceOnStorageDevice',
   20 => 'insufficientDramSize',
   21 => 'incompatibleImage',
  );
  ################################
  $Action  = $Actions{$Action} or return(undef); 
  $Module  =  1 unless(int($Module));
  $Timeout = 10 unless(int($Timeout));

  my($Session,$Error) = Net::SNMP->session(
    -version   => 'snmpv2c',
    -hostname  => $Host,
    -community => $Cty
  );
  return($Error) unless(defined($Session));

  $Session->timeout($Timeout);

  $Session->set_request($OIDs{'tftpHost'},OCTET_STRING,$Server);
  $Session->set_request($OIDs{'tftpFile'},OCTET_STRING,$Filename);
  $Session->set_request($OIDs{'tftpModule'},INTEGER,$Module);
  $Session->set_request($OIDs{'tftpAction'},INTEGER,$Action);

  $Error = $Session->error();
  if($Error) { $Session->close(); return($Error); }

  for(my $Time = time(); time() <= $Time + $Timeout;) {
    sleep(1);
    my $Result = $Session->get_request($OIDs{'tftpResult'});
    my $Value  = $Result->{$OIDs{'tftpResult'}};
       $Error  = $Results{$Value};
    $Timeout++ if($Error eq 'inProgress');
    last       if($Error eq 'success');
  }
  $Session->close();
  return($Error);
}