#!/usr/bin/perl

########## Confixx(R) 3.1 Professional ############
####### Copyright SWsoft, Inc. 2004-2005 ##########
#### http://www.swsoft.com - info@swsoft.com ####


# DBI : 0
# IO: 0


use DBI;
use Getopt::Long;

use vars qw/$db_address $dbUser $dbPw $dbClientEncoding $bin_openssl $tmpdir $ServerID/;
use strict;

$db_address = 'DBI:mysql:confixx:localhost;mysql_socket=/var/run/mysqld/mysqld.sock';
$dbUser = 'root';
$dbPw = 'gT85JkoXc4d';
$dbClientEncoding = "latin1";
$bin_openssl = '/usr/bin/openssl';
$tmpdir = '/var/www/confixx/tmp';
$ServerID = '221909ac3a1f9dade7e7e630c1a02e9f';

my ($user,$selfsigned,$sth,$dbh,$csr,$sql,$server_id);

my @config_opts = ( 'user|u=s',
										'self|s:i',
										'sid=s',
										'match|m'
									);

my %args = ();
&GetOptions( \%args, @config_opts );

unless( $args{'user'} ){
	$args{'user'} = shift @ARGV;
}

while( my $arg = shift @ARGV ){

	if( $arg =~ /^match$/i ){
		unless( exists $args{'match'} ){
			$args{'match'} = $arg;
		}

	}elsif( $arg =~ /^([01yn]|yes|no)$/i ){
		unless( exists $args{'self'} ){
			$args{'self'} = $arg;
		}

	}elsif( $arg =~ /[a-z0-9]{10}/i ){
		unless( exists $args{'sid'} ){
			$args{'sid'} = $arg;
		}
	}
}

unless( $user = $args{'user'} ){
  &fehler( "mlf||ssl_argv||#1001" );
}

$selfsigned = $args{'self'} =~ /n|no/? 0: $args{'self'};
$server_id = $args{'sid'}? $args{'sid'}: $ServerID; 


my $keyfile = "$tmpdir/$user.key";
my $csrfile = "$tmpdir/$user.csr";
my $crtfile = "$tmpdir/$user.crt";
my $cafile = "$tmpdir/ca-$user.crt";

$dbh = DBI->connect($db_address, $dbUser, $dbPw)
  or &fehler("mlf||scripts_db_connect||#2001||$DBI::errstr");
$dbh->do("SET NAMES '$::dbClientEncoding'");
$sth = $dbh->prepare("SELECT privatekey, neu, countrycode, state, city, firm,".
										 " unit, common, email, crt, ca".
										 " FROM cssl WHERE kunde='$user' AND server_id='$server_id'");

$sth->execute or 
	&fehler("mlf||#2002||ssl_db_fetch||$DBI::errstr");

my ($key, $new, $cc, $state, $city, $firm, $unit, $common, $email, $crt,$ca) = $sth->fetchrow_array or 
	&fehler("mlf||ssl_db_getuser||#2003||$user||$DBI::errstr");

$sth->finish;

if( exists( $args{'match'} ) ){

	$dbh->disconnect;

 if( &matchKeyCrt( $key, $crt, $ca ) ){
	 exit 0; ## success
 }else{
	 exit 1; ## fail
 }
}

unless( $cc =~ /^\w\w$/ ) { &fehler("mlf||ssl_val_cc"); }
unless( $state ) { &fehler("mlf||ssl_val_state"); }
unless( $city ) { &fehler("mlf||ssl_val_city"); }
unless( $firm ) { &fehler("mlf||ssl_val_firm"); }
unless( $unit ) { &fehler("mlf||ssl_val_unit"); }
unless( $common ) { &fehler("mlf||ssl_val_common"); }
unless( $email =~ /\S+\@(?:\S+\.)+\S+/) { &fehler("mlf||ssl_val_email"); }

if(($key eq "") || $new){
  $key = &create_key();

} else {
  if( open( KEY, '>', $keyfile ) ){
		print KEY $key;
		close(KEY);
	} else {
		&fehler("mlf||scripts_file_read||#1002||$keyfile");
	}

}

$csr = &create_csr( $selfsigned );

if ( $key && $csr ) {
	if ( $selfsigned ) {
		$sql = "UPDATE cssl SET crt='$csr', privatekey='$key', csr='', ca='', neu=0 WHERE kunde='$user' AND server_id='$server_id'";
	} else {
		$sql = "UPDATE cssl SET csr='$csr', privatekey='$key', crt='', ca='' ,neu=0 WHERE kunde='$user' AND server_id='$server_id'";
	}

	$dbh->do( $sql ) or 
		&fehler("mlf||ssl_db_update||#2004||$DBI::errstr");
}

$dbh->disconnect;

unlink $keyfile;
unlink $csrfile;


## Unterprogramme

sub create_key {

  my ($key);

  my $return = system( "$bin_openssl genrsa -rand -des3 -out $keyfile 2048 2>/dev/null" );

	unless ( $return == 0 ) {
		&fehler("mlf||ssl_key_create||#1003");
	}

  if( open(KEY, '<', $keyfile ) ){
		while(<KEY>){
			$key .= $_;
		}
		close(KEY);
	} else {
		&fehler("mlf||scripts_file_open_read||#1004");
	}

	return $key;
}


sub create_csr{

	my ($selfsigned) = @_;

	my ($csr,$cmd);



	if ( $selfsigned ) {
		$cmd = "$bin_openssl  req -new -x509 -days 365 -key $keyfile -out $csrfile";
	} else {
		$cmd = "$bin_openssl  req -new -key $keyfile -out $csrfile";
	}

	if ( open(INPUT,"| $cmd 1>/dev/null") ) {
		print INPUT <<"SETTINGS";
$cc
$state
$city
$firm
$unit
$common
$email
SETTINGS

		print INPUT "\n\n";

		close INPUT;
	}

  if( open(CSR, '<', $csrfile ) ){
		while(<CSR>){
			$csr .= $_;
		}
		close(CSR);	
	} else {
		&fehler( "mlf||scripts_file_open_read||#1006||$csrfile" );
	}

	return $csr;
}


sub print_file{
  my ($file) = @_;
  open( FILE, $file );
  while (<FILE>){
    print $_;
  }
	close( FILE );
}


sub fehler {
  my ($msg) = @_;
  if($msg ne ""){
    print "$msg\n";
  }
  exit 1;
}


sub matchKeyCrt {
	my( $key, $crt,$ca ) = @_;

  my ($md5_key, $md5_crt);
	chomp $ca;
	if ($ca){	
		open ( CA , '>', $cafile);
		$ca =~ s/\r//g;
		print CA $ca;
		close($cafile);
		#check if input is a certificate 
		if (system "$bin_openssl x509 -noout -modulus < $cafile >/dev/null 2>&1"){
		 	unlink($cafile);
			return 0;
		 }
		 unlink($cafile);
	}
	
  if ( $crt && $key ) {

		open( KEY, '>', $keyfile );
		$key =~ s/\r//g;
		print KEY $key;
		close(KEY);

		$md5_key = `$bin_openssl rsa -noout -modulus -in $keyfile 2>/dev/null | $bin_openssl md5`;

		unlink( $keyfile );

		if( ( ! $md5_key ) ||
				( $md5_key eq "d41d8cd98f00b204e9800998ecf8427e\n" ) ||
				( $md5_key eq "68b329da9893e34099c7d8ad5cb9c940\n" ) ){
			return 0; ## fail
		}

		open( CRT, '>', $crtfile );
		$crt =~ s/\r//g;
		print CRT $crt;
		close(CRT);
		
		$md5_crt = `$bin_openssl x509 -noout -modulus -in $crtfile | $bin_openssl md5`;

		unlink( $crtfile );

		if( $md5_key eq $md5_crt  ){
			return 1; ## success
		}
  }

	return 0; ## fail
}
## //Unterprogramme
