Month: January 2015

Installing Debian Jessie on an APU1D4

To install Debian Jessie on an APU1D4, it is easiest to go for a network installation. You need
– a TFTP server
– a DHCP server
– the Debian file structure in the TFTP server’s root directory

For DHCP you will need something like the following configuration:

ddns-update-style none;
max-lease-time 186400;
authoritative;

subnet 192.168.66.0 netmask 255.255.255.0 {
  range 192.168.66.100 192.168.66.150;
  option domain-name-servers 192.168.66.1;
  option domain-name "example.com";
  option domain-search "example.com";
  option routers 192.168.66.1;
  option broadcast-address 192.168.66.255;
  default-lease-time 86400;
  max-lease-time 186400;
}

host apuc{
	hardware ethernet 00:0d:b9:12:34:bc;
	fixed-address 192.168.66.66;
        filename "pxelinux.0";
        next-server 192.168.66.1;
}
host apud{
	hardware ethernet 00:0d:b9:12:34:bd;
	fixed-address 192.168.66.66;
        filename "pxelinux.0";
        next-server 192.168.66.1;
}
host apue{
	hardware ethernet 00:0d:b9:12:34:be;
	fixed-address 192.168.66.66;
        filename "pxelinux.0";
        next-server 192.168.66.1;
}

For the TFTP server you need something like the following configuration:

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure"

Then simply extract the debian installer files into /src/tftp . I have included my working configuration into netboot_serial_20150107.tar. Should you want to change its configuration, simply edit the file pxelinux.cfg/default file. Mine looks as follows and is preconfigured for serial console output:

default install
label install
	menu label ^Install
	menu default
	kernel debian-installer/amd64/linux
	append initrd=debian-installer/amd64/initrd.gz --- vga=normal console=tty0 console=ttyS0,115200n8

Attach a serial console cable and fire it up!

Frontend for openssl to check key chains

Since checking SSL key chains with openssl is sometimes a bit tricky, I have written a little perl script as wrapper around it.

Just download check_chain.zip, unzip it and run it as follows:

./check_chain.pl -p server port

-p (optional) prints out the certificates as well
server is the server to check
port (optional) is the port to connect to.

Here is the code:

#!/usr/bin/perl -w

use strict;

my $has_date_parse = 1;
eval {
	require Date::Parse;
	Date::Parse->import( qw/str2time/ )
};

if ( $@ ne "" ) {
	print "Module Date::Parse not found! Skipping expiration date calculation!n";
	$has_date_parse = 0;
}

my $print_cert = 0;
my $host = shift || &usage();
if ( $host eq '-p' ) {
	$print_cert = 1;
	$host = shift;
}
my $port = (shift || 443);


my $output = `echo "t" | openssl s_client -host $host -port $port -showcerts 2> /dev/null`;

my $cert_num = 0;

my $line;
my @certs;
my %certs;

foreach $line ( split /n/, $output ) {
	if ( $line =~ /BEGIN CERTIFICATE/ .. $line =~ /END CERTIFICATE/ ) {
		$certs[$cert_num] .=  "$linen";
	}
	$cert_num += 1 if $line =~ /END CERTIFICATE/;
}

my $i;
my $serial;
my $attribute;
foreach $i ( 0 .. scalar @certs -1 ) {
	$serial = qx{echo "$certs[$i]" | openssl x509 -serial -noout};
	$serial =~ s/serial=//;
	chomp $serial;
	$certs{$serial}{'certificate'} = $certs[$i];

	foreach $attribute ( qw/issuer subject issuer_hash subject_hash enddate/ ) {
		$certs{$serial}{"$attribute"} = qx{echo "$certs[$i]" | openssl x509 -$attribute -noout};
		chomp $certs{$serial}{"$attribute"};
		$certs{$serial}{"$attribute"} =~ s/notAfter=//;
	}

	# Certificate stored, reuse @certs to keep order with serial number
	$certs[$i] = $serial;
	$certs{$serial}{"order"} = $i;
}

print "nChecked server: $host on port $portn";

my $found;
foreach $i ( 0 .. scalar @certs -1 ) {
	print "nCertificate $i:n";
	$serial = $certs[$i];
	print "t", $certs{$serial}{"subject"}, " (hashed: ", $certs{$serial}{"subject_hash"}, ")n";
	print "tserial number (check in browser): $serialn";
	print "texpires: ", $certs{$serial}{"enddate"};
	if ( $has_date_parse == 1 ) {
		print " (in ", int ((str2time($certs{$serial}{"enddate"}) - time) /60/60/24  ), " days)" ;

	}
	print "n";
	print "t", $certs{$serial}{"issuer"}, " (hashed: ", $certs{$serial}{"issuer_hash"}, ")n";
	print "tissuer found in chain: ";
	$found = "NO - should be root certificate";
	if ( $certs{$serial}{"issuer_hash"} eq $certs{$serial}{"subject_hash"} ) {
		$found = "SELF SIGNED CERTIFICATE";
	} else {
		foreach ( keys %certs ) {
			if ( $certs{$serial}{"issuer_hash"} eq $certs{$_}{"subject_hash"} ) {
				$found = "YES";
			}
		}
	}
	print "$foundn";
}

if ( $print_cert == 1 ) {
	foreach $i ( 0 .. scalar @certs -1 ) {
		print "nCertificate $i:n";
		$serial = $certs[$i];
		print $certs{$serial}{"certificate"}
	}
}

sub usage {
	print "Usage: $0 [-p] server_name [port]n";
	print "t-p : also print certificatesn";
	print "tserver_name : server to check, mandatoryn";
	print "tport : port to check, default: 443n";
	exit;
}

Its output is as follows:

$ ./check_chain.pl www.lavalite.de

Checked server: www.lavalite.de on port 443

Certificate 0:
	subject= /C=DE/OU=Domain Control Validated/CN=www.lavalite.de (hashed: dad54aee)
	serial number (check in browser): 11213FB18C3CEF8B39A731AB874D155363F2
	expires: Dec  8 11:13:28 2015 GMT (in 318 days)
	issuer= /C=BE/O=GlobalSign nv-sa/CN=GlobalSign Domain Validation CA - SHA256 - G2 (hashed: 79701ca5)
	issuer found in chain: YES

Certificate 1:
	subject= /C=BE/O=GlobalSign nv-sa/CN=GlobalSign Domain Validation CA - SHA256 - G2 (hashed: 79701ca5)
	serial number (check in browser): 040000000001444EF03E20
	expires: Feb 20 10:00:00 2024 GMT (in 3314 days)
	issuer= /C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA (hashed: b0f3e76e)
	issuer found in chain: NO - should be root certificate