hi all,

couple of week before, I had a wonderful discussion with micheal about 
providing SOAP APIs to the OpenCA system. Basically the idea is,

1) to programatically automate & manage some of OpenCA process from other 
applications. 
2) interoperable API to any environment.

we are running an management software (java based) in our university. We need 
to provide pki (as pluggable module) to that application. We have been using 
OpenCA for the last one year....and we are quiet comfortable with that. 
Unfortunately their is no open API available for OpenCA to run as a 
transparent server in the background. we found ejbca project from 
sourceforge.net has such a feature both as standalone PKI system or API to 
connect to other legacy systems. But We didn't try any other opensource pki 
software (because of wonderful support from OpenCA team, especially micheal 
;) ).  we started thinking about writing API's for OpenCA just when other 
folks started discussing about OpenCA Server in the devel list.

I quickly did some experiment with perl SOAP modules and tried something.... 
all i did was simply cut & paste some code from the OpenCA 'cmds' directory 
and installation of SOAP::Lite from CPAN.  It's working and also i am able to 
call those methods from java envirnment (after all soap is meant for that). I 
shared my experience with micheal, he encourged me to discuss in the devel 
list. 

I have added a prototype test program here.... Remeber i not a perl or SOAP 
expert, I started learning perl after working with OpenCA ;). Just want to 
give back something to the OpenCA community. i will keep doing some work on 
the same line.... If you guys have any idea or suggestions for OpenCA API's ( 
I am really need help in overall structure for the API's ) please write 
back... 

Thanks,
venki.
use strict;
package OpenCA::SOAP;

## Load necessary OpenCA modules
##

use OpenCA::OpenSSL;
use OpenCA::REQ;
use OpenCA::DBI;
use OpenCA::Tools;

## define global variables
##


## constructor method

sub loadConf
{
	my $invocant = shift;
	my $class = ref($invocant)||$invocant;
	my $HOME = "/epki/jc";
	my $self =	{
#			TempDir		=>	"/epki/jc/OpenCA/var/tmp",
			TempDir		=>	"/tmp",
			ModuleID	=>	0,
			ModuleShift	=>	8,
			OpenSSLPath	=>	"/usr/local/ssl/bin/openssl",
			CACert		=>	"$HOME/OpenCA/var/crypto/cacerts/cacert.pem"			
			};
	bless $self,$class;
	return $self;
}

sub generateRequest
{
	my $self = shift;
	my ($email,$cn,$ou,$passwd) = @_;

	## following method of accepting input parameters
	## should be rewritten 
	
	my $role = "User";
	my $ra = "Trustcenter itself";
	my $bits = "1024";
	my $org = "JamCracker";
	my $country = "US";
	my @elements = ("emailAddress","CN","OU","O","C");

	## form DN string

	my $dn = "";
	$dn .= $elements [0]."=".$email.",";
	$dn .= $elements [1]."=".$cn.",";
	$dn .= $elements [2]."=".$ou.",";	
	$dn .= $elements [3]."=".$org.",";
	$dn .= $elements [4]."=".$country;

	## create temp file

	my $keyFile = "$self->{TempDir}/key_$$.pem";

	## create OpenSSL object

	my $cryptoShell = new OpenCA::OpenSSL( SHELL => $self->{OpenSSLPath});

	if (not defined $cryptoShell)
	{
		die "Can't create OpenSSL object";
	}

	## create key pairs

	if (not $cryptoShell->genKey(
				BITS	=>	$bits,
				OUTFILE	=>	$keyFile,
				PASSWD	=>	$passwd) )
	{
		die "Can't create key pairs";
	}

	## change to pkcs8

	my $key = $cryptoShell->dataConvert (
				DATATYPE	=>	"KEY",
				INFORM		=>	"PEM",
				OUTFORM		=>	"PKCS8",
				INPASSWD	=>	$passwd,
				OUTPASSWD	=>	$passwd,
				INFILE		=>	$keyFile );

	if (not $key)
	{
		die "Can't Convert to pkcs8 format";
	}

	## generate PKCS10 request
	
	my $req = new OpenCA::REQ (
			SHELL	=>	$cryptoShell,
			KEYFILE	=>	$keyFile,
			SUBJECT	=>	$dn,
			PASSWD	=>	$passwd,
			FORMAT	=>	"PEM" );

	if (not $req)
	{
		die "Can't create REQ object";
	}
	
	unlink($keyFile);	
	
	## compose request

	my $tmp = "-----BEGIN HEADER-----\n";
	$tmp .= "TYPE = PKCS#10\n";

	my $db = new OpenCA::DBI(
			SHELL	=>	$cryptoShell,
			DB_Type	=>	"mysql",
			DB_Name	=>	"jcpki",
			DB_Host	=>	"localhost",
			DB_Port	=>	"3306",
			DB_User =>	"jcpki",
			DB_Passwd =>	"jcpki"); 
			
	if (not $db)
	{
		die "Can't initialize OpenCA::DBI class";
	}		
	
	my $req_elements = $db->elements(DATATYPE=>"REQUEST");
	if ((not defined $req_elements) or ($req_elements < 0))
	{
		die "Database failed while counting the requests";
	}
	else
	{
		$req_elements++;
	}
	
	my $new_serial = ($req_elements << $self->{ModuleShift})|$self->{ModuleID};
	$tmp .= "SERIAL = ".$new_serial."\n";

	my $tools = new OpenCA::Tools();
	if (not $tools)
	{
		die "Cannot initialize OpenCA::Tools class!";
	}	

	$tmp .= "NOTBEFORE = ".$tools->getDate()."\n";
	my $pin_digest = $cryptoShell->getDigest(
				DATA		=>	$passwd,
				ALGORITHM	=>	"sha1");
	if (not $pin_digest)
	{
		die "OpenSSL failed during the calculation of hash";
	}

	$tmp .= "PIN = $pin_digest\n";
	$tmp .= "RA = $ra\n";
	$tmp .= "ROLE = $role\n";
	$tmp .= "-----END HEADER-----\n";
	$tmp .= $req->getPEM();
	$tmp .= $key;

	my $new_req;
	if (not $new_req = new OpenCA::REQ(SHELL=>$cryptoShell,
					DATA	=>$tmp))
	{
		die "Internal Request Error";
	}	
	
	if (not $db->storeItem( DATATYPE=>"PENDING_REQUEST",
				OBJECT	=>$new_req,
				INFORM	=>"PEM",
				MODE	=>"INSERT"))
	{
		die "Error while storing REQ in database\n";
	}
	
	return "Success\n";
}

sub getCACertificate
{
	my $self = shift;
	my $certificate = "";
	if (not open (FD, $self->{CACert}))
	{
		die "Can't Access CA Certificate File";
	}
	while (<FD>)
	{
		$certificate .= $_;
	}
	return $certificate;
}

1;	
#!/usr/bin/perl -w

use SOAP::Lite;
my $soap = SOAP::Lite 
    ->uri('http://192.168.2.66:7777/OpenCA/SOAP')
    ->proxy('http://192.168.2.66:7777')
;
  
my $obj = $soap->call(loadConf)->result;
my $result = $soap->generateRequest($obj,"[EMAIL PROTECTED]","test1","security","myPasswd");
    
unless (defined $result->fault)
{
	print $result->result;
}else{
print $result->faultcode;
print $result->faultstring;
}

#!/usr/bin/perl -w

use SOAP::Transport::HTTP;


# don't want to die on 'Broken pipe' or Ctrl-C
$SIG{PIPE} = 'IGNORE';

$daemon = SOAP::Transport::HTTP::Daemon
    -> new (LocalPort => 7777)
    -> dispatch_to('/home/venki/perlws/soapprg/modules/','OpenCA::SOAP')
  ;
  
  print "Contact to SOAP server at ", $daemon->url, "\n";
  $daemon->handle;

Reply via email to