#!/usr/local/bin/perl

# by mcr@sandelman.ottawa.on.ca
#
#
# Format is simple.
#   1 byte throw away
#   8 bytes of hex length.
#   4  bytes for encoded type, preferably printable.
#   length - 13 bytes of data
#
# e.g:
# CLLLLLLLLTTTTxxxxxxxxxxxx
#
#   The length includes the headers, and also the single
# character that preceeds the length. The single character
# is always ignored, and will typically be syntactic sugar.
#
#   Within a type, this same system may be repeated, or the type
# may employ fixed width fields. It is recommended that any
# type with optional fields using the taging system.
#   All integers are encoded in hex, the length of them
#
#   HEX digits are always in lower case.
#   Types are ideally in upper case.
#   
#
#

sub indent {
    local($depth) = @_;

    return " " x ($depth * 2);
}


sub hexdump {
    local($data)=@_;
    local($i,$byte);

    $i=0;
    while($line=substr($data,$i,16)) {
	@bytes = unpack("C16",$line . ("\0" x 16));
	print "\t";
	foreach $byte (@bytes) {
	    printf "%02x ",$byte;
	}
	print "    ";
	foreach $byte (@bytes) {
	    if($byte > 32 && $byte <126) {
		printf "%c",$byte;
	    } else {
		print ".";
	    }
	}
	print "\n";
	$i+=16;
    }
}

sub dumpstruct {
    local($depth, $cert, %dumpers)=@_;
    
    ($lf, $length, $type) = unpack("CA8A4",$cert);
    $length = hex($length);
    while($length > 0) {
	$data = substr($cert,13,$length - 13);
	$cert = substr($cert,$length);

	print &indent($depth)."$type packet of length $length\n";
	if(defined($dumpers{$type})) {
	    #print "Running routine: $dumpers{$type}\n";
	    eval "&". $dumpers{$type}. "(". ($depth+1) .",\$data);";
	} else {
	    &hexdump($data);
	}

	($lf, $length, $type) = unpack("CA8A4",$cert);
	$length = hex($length);
    }
}

$topstruct{'AUTH'} = "dumpauth";
sub dumpauth {
    local($depth,$authdata) = @_;

    print &indent($depth)."Auth field:\n";

    &dumpstruct($depth+1,$authdata, %authstruct);
}

$authstruct{'MAYD'}="dumpauth_mayd";
sub dumpauth_mayd {
    local($depth, $mayddata) = @_;
    local($delegatedepth);
    
    $delegatedepth = hex($mayddata);
    print &indent($depth)."May delegate $delegatedepth times\n";
}

$authstruct{'USER'}="dumpauth_user";
sub dumpauth_user {
    local($depth, $userdata) = @_;
    
    print &indent($depth)."Authorization to login:\n";
    &dumpstruct($depth+1, $userdata, %userstruct);
}

$userstruct{'USER'}="dumpuser_user";
sub dumpuser_user {
    local($depth,$userdata) = @_;

    print &indent($depth)."Username: $userdata\n";
}
$userstruct{'HOST'}="dumpuser_host";
sub dumpuser_host {
    local($depth,$userdata) = @_;

    print &indent($depth)."Hostname: $userdata\n";
}


foreach $file (@ARGV) {
    open(F,$file);
    undef $/;
    $data=<F>;
    close(F);
    &dumpstruct(0,$data, %topstruct);
}

    

