All Certificate Basic Requests work OK but now I'm trying to work with PKCS#10 requests. Well, the PKI works fine and I can publish by LDAP server all certificates with "o=Tecnopolis-CA,c=it" (the basedn of ldap.conf) in subject field!! When I write another organization in Subject field (i.e., o=Tecnopolis CSATA, c=IT) the "Updating Certificates on LDAP server" gives me the following message:
Exporting valid certificates to LDAP ... Certificate 1 OKCertificate 2 OKCertificate 3 OKCertificate 4 OKCertificate 5 OKCertificate 6 FAILED (error -4: Distinguished name conflicts with basedn.)Obviously, I've defined on my LDAP Server the new organization and the error missing if I change the basedn in ldap.conf file in OpencaHOME/etc/servers directory
Can I use the PKI to issue certificates with PKCS#10 requests with some other Organizations? Or I can serve only one organization (for my PKI o=Tecnopolis-CA,c=it)?
New directory servers like OpenLDAP v2 support different suffixes but OpenCA 0.9.1 only supports one suffix (basedn). This has nothing to do with organization only with the suffix.
OpenCA 0.9.2 will support different suffixes too. I attached the changed ldap-utils.lib. You must simply add all suffixes to the basedn. E.g.
basedn "o=Tecnopolis CA, c=IT" "o=Tecnopolis CSATA, c=IT"
The interface of the functions in ldap-utils.lib didn't change. We will not add the new ldap-utils.lib to 0.9.1 because it is a new feature and not a bugfix.
Best regards
Michael -- ------------------------------------------------------------------- Michael Bell Email: [EMAIL PROTECTED] ZE Computer- und Medienservice Tel.: +49 (0)30-2093 2482 (Computing Centre) Fax: +49 (0)30-2093 2704 Humboldt-University of Berlin Unter den Linden 6 10099 Berlin Email (private): [EMAIL PROTECTED] Germany http://www.openca.org
## RA Server Management Utility ## (c) 1999 by Massimiliano Pala ## All Rights Reserved ## ## Project Information: ## ## Current Version ..................... $VER ## Project Started on .................. 17/12/1998 ## Last Modified on .................... 30/03/2001 ## Project Closed on ................... n/a ## ## Program currently tested with OpenLDAP v.1.2 on Linux, Solaris ## and Sleepycat DB. ## ## DISC CLAIMER: THIS SOFTWARE IS GIVEN AS IS WITHOUT ANY WARRANTIES ## ABOUT ANY DAMAGE DERIVED BY THE USE ( CORRECT OR NOT ) OF THIS ## SOFTWARE. THE AUTHOR IS THEREFORE NOT RESPONSABLE IN ANY WAY OF ## DAMAGES RELATED IN ANY WAY TO THIS OR SUPPORTED SOFTWARE AS WELL. ## ## If you want to contact me (the author) please use the e-mail ## addresses listed below. Do not esitate in reporting bugs, enhancement ## or anything seems useful in developing this software: ## ## [EMAIL PROTECTED] ## [EMAIL PROTECTED] ## [EMAIL PROTECTED] ##
## Thank you for using this software, and remember that Open Projects
## are the future of mankind. Do not sleep, partecipate to world wide
## efforts to make life easier for all!
use X500::DN;
sub addCertsUsers {
my $keys = { @_ };
## Reserved Variables
my ( @certsList );
my ( $filename, $tmp, $ID, $cert, $ldap, $ret );
## Get Required parameter
my $certDir = getRequired( 'CertDir' );
## Debugging info
my $DEBUG = 0;
if ($keys->{DEBUG}) {
$DEBUG = 1;
}
##// This file has the latest imported certificate's serials
$filename = "$certDir/lastImport.txt";
##// Let's open the lastImport.txt
if( not -e "$filename" ) {
configError( i18nGettext ("File __FILE__ not found!", "__FILE__", $filename));
}
$tmp = $tools->getFile( "$filename");
if( $tmp eq "" ) {
success( gettext ("Last Import file was empty."));
}
@certsList = split( "\n", $tmp );
my $table = $query->buildRefs ( ELEMENTS =>, MAXITEMS =>);
$table .= $query->startTable (COLS=>[ gettext ("Cert.-No."),
gettext ("DN"),
gettext ("adding dn"),
gettext ("adding certificate") ],
WIDTH=>"100%",
TITLE_BGCOLOR=>"#DDCCFF");
foreach $ID (@certsList) {
my @line = ();
my ( $filter, $serID, $parsed, $ret, $entry );
( $serID ) = ( $ID =~ /([a-f0-9]+)/i );
##// Let's be sure it is in the right format
$serID = uc( $serID );
$serID = "0$serID" if( length($serID) % 2 );
my $cert = $db->getItem ( DATATYPE => "VALID_CERTIFICATE",
KEY => $serID );
if( not $cert ) {
$table .= $query->addTableLine( DATA => [
"<FONT COLOR=\"Red\">".
i18nGettext ("ERROR [__CERT_SERIAL__] : can't get certificate from
dB!",
"__CERT_SERIAL__", $serID).
"\n</FONT>" ] );
next;
}
$parsed = $cert->getParsed();
push ( @line, $serID, $parsed->{DN});
$ret = addLDAPobject ( CERTIFICATE=>$cert );
my $text;
$text .= "<FONT COLOR=\"Red\">" if ( not $ret->{STATUS} );
$text .= $ret->{DESC};
$text .= "</FONT>" if ( not $ret->{STATUS} );
push ( @line, $text);
if( $ret->{STATUS} ) {
$ret = addLDAPattribute ( CERTIFICATE => $cert , NOPRINT => "true");
if ($ret->{STATUS}) {
push (@line, gettext ("success"));
} else {
push (@line, i18nGettext ("Error : __ERRNO__", "__ERRNO__", $ret->{CODE}));
}
} else {
push (@line, gettext ("operation not performed"));
}
$table .= $query->addTableLine ( DATA => [ @line ]);
}
$table .= $query->endTable;
print $table;
return gettext ("Ok.");
}
sub addLDAPobject {
######################################################
## only certs makes sense because a CRL can only be ##
## produced if a valid CA-cert exists ##
######################################################
my $keys = { @_ };
my ( $obj, $parsed, $serID, $ldap, $ldapadd_result, $ret, $dn, $cn, $sn, $email );
my $DEBUG = 0;
if ($keys->{DEBUG}) {
$DEBUG = 1;
}
## check the type of the attribute
$obj = $keys->{CERTIFICATE};
return { STATUS => 0, CODE => -2, DESC => gettext ("No object specified.") } if (
not $obj );
## get the needed data
my $cert_dn = $obj->getParsed ()->{DN};
my $cert_cn = $obj->getParsed ()->{DN_HASH}->{CN}[0];
my $cert_serID = $obj->getParsed ()->{SERIAL};
my $cert_email = $obj->getParsed ()->{EMAILADDRESS};
my $cert_ou = $obj->getParsed ()->{DN_HASH}->{OU};
my $cert_o = $obj->getParsed ()->{DN_HASH}->{O}[0];
my $cert_l = $obj->getParsed ()->{DN_HASH}->{L}[0];
my $cert_st = $obj->getParsed ()->{DN_HASH}->{ST}[0];
my $cert_c = $obj->getParsed ()->{DN_HASH}->{C}[0];
## debugging
print "Information of the Object:<br>\n" if ($DEBUG);
print "dn ".$cert_dn."<br>\n" if ($DEBUG);
print "cn ".$cert_cn."<br>\n" if ($DEBUG);
print "serID ".$cert_serID."<br>\n" if ($DEBUG);
print "email ".$cert_email."<br>\n" if ($DEBUG);
print "ou ".$cert_ou."<br>\n" if ($DEBUG);
print "o ".$cert_o."<br>\n" if ($DEBUG);
print "l ".$cert_l."<br>\n" if ($DEBUG);
print "st ".$cert_st."<br>\n" if ($DEBUG);
print "c ".$cert_c."<br>\n" if ($DEBUG);
print "End of the information of the Object.<br>\n" if ($DEBUG);
## here we could perform some operations with the data
## sn is not the real sn sometimes but you can find
## the person via a search with a wildcard
my $cert_sn = $cert_cn;
$cert_sn =~ s/\s*$//;
$cert_sn =~ s/^[^ ]* //;
my $ou_counter = 0;
my @ou_array = ();
## Get the Connection to the Server
if ( not ( $ldap = LDAP_connect() )) {
## print "<FONT COLOR=\"Red\">";
## print i18nGettext ("LDAP [__CERT_SERIAL__]: Connection Refused by server!",
"__CERT_SERIAL__", $cert_serID)."\n";
## print "</FONT><BR>\n";
return { STATUS => 0, CODE => -3, DESC => gettext ("Connection refused by
server.") };
};
##// Let's bind for a predetermined User
$ret = LDAP_bind( LDAP => $ldap );
if( $ret->is_error ) {
my $msg = i18nGettext ("LDAP-bind failed: __ERRVAL__",
"__ERRVAL__", $ret->error) ;
LDAP_disconnect( LDAP => $ldap );
return { STATUS => 0, CODE => $ret->code, DESC => $msg };
};
my $dn_object = LDAP_getDN ($obj->getParsed ()->{DN}, $DEBUG);
my $suffix_object = LDAP_getSuffix ($dn_object, $DEBUG);
if (not $suffix_object)
{
print "dn conflicts with basedn(s)<br>\n" if ($DEBUG);
LDAP_disconnect ( $ldap );
return { STATUS => 0 ,
DESC => gettext ("Distinguished name conflicts with basedn(s)."),
CODE => -4 };
}
## add an empty string to create the basedn if necessary
my @dn_array = reverse LDAP_getPath ($dn_object, $suffix_object, $DEBUG);
push @dn_array, ["",""];
## setup the tree for the DN
## attention only the last ldapadd must be successful !!!
print "Building the missing nodes of the LDAP-tree ...<br>\n" if ($DEBUG);
my $add_dn = $suffix_object->getRFC2253String;
my $actual_element;
my $use_ldap_add = 0;
while (scalar (@dn_array)) {
$actual_element = pop @dn_array;
## setup ou-array
## FIXME: this looks for me like a hack; michael bell
if ($actual_element->[0] =~ /^\s*ou\s*$/i) {
$ou_array [$ou_counter] = $actual_element->[1];
$ou_counter++;
}
## prepare the needed strings
if ($actual_element->[0]) {
## protection against basedn
$add_dn = $actual_element->[0]."=".
$actual_element->[1].",".$add_dn;
}
print "Try to add $add_dn ...<br>\n" if ($DEBUG);
## check that the entry does not exist in the LDAP-tree
print "LDAP Schema DN: ".$add_dn."<br>\n" if ($DEBUG);
my $ldap_schema = $ldap->schema (dn => $add_dn);
## I stop the insertion because of a searcherror too
if ( not $ldap_schema ) {
print "node doesn't exist<br>\n" if ($DEBUG);
} elsif (not $ldap_schema->error() ) {
## node/leaf exists
print "node exists<br>\n" if ($DEBUG);
next;
} else {
print "something is going wrong --> node doesn't exist?<br>\n" if ($DEBUG);
print "LDAP Schema-Code ".$ldap_schema->error()."<br>\n" if ($DEBUG);
}
$use_ldap_add = 1;
## insert the different types
##// attention: I don't insert here a CA!!!
## this most be done otherwise because I cannot declare
## any o and ou to be a (sub)CA
my @attr;
if ($add_dn =~ /^\s*(cn|dc|sn|email|emailAddress|serialNumber)\s*=.*$/i) {
if ($obj->getParsed()->{IS_CA}) {
push @attr, 'objectclass' => [ 'top',
'organization',
'pkiCA'
];
push @attr, 'o' => $cert_o if ($cert_o);
push @attr, 'st' => $cert_st if ($cert_st and $add_dn =~ /\s*st\s*=/i);
push @attr, 'l' => $cert_l if ($cert_l and $add_dn =~ /\s*l\s*=/i);
## push @attr, 'authorityRevocationList;binary' => '';
## push @attr, 'certificateRevocationList;binary' => '';
## push @attr, 'cACertificate;binary' => '';
} else {
if (not $cert_sn or not $cert_cn)
{
LDAP_disconnect ( $ldap );
return { STATUS => 0 ,
DESC => gettext ("The common name is not specified but required
for this objectclass."),
CODE => -101 };
}
push @attr, 'objectclass' => [ 'top',
'person',
'organizationalPerson',
'inetOrgPerson'
];
push @attr, 'cn' => $cert_cn;
if ($add_dn =~ /^\s*sn\s*=.*$/i) {
my $sn = $add_dn;
$sn =~ s/,.*$//g;
$sn =~ s/^.*=//;
push @attr, 'sn' => $sn;
} else {
push @attr, 'sn' => $cert_sn;
}
push @attr, 'ou' => [ @ou_array ] if (scalar @ou_array);
push @attr, 'o' => $cert_o if ($cert_o);
push @attr, 'mail' => $cert_email if ($cert_email);
push @attr, 'st' => $cert_st if ($cert_st and $add_dn =~ /\s*st\s*=/i);
push @attr, 'l' => $cert_l if ($cert_l and $add_dn =~ /\s*l\s*=/i);
}
} elsif ($add_dn =~ /^\s*ou\s*=.*$/i) {
if (not scalar @ou_array) {
LDAP_disconnect ( $ldap );
return { STATUS => 0 ,
DESC => gettext ("There is no organizational unit specified but at
minimum one is required for this objectclass."),
CODE => -102 };
}
push @attr, 'ou' => [ @ou_array ];
## push @attr, 'authorityRevocationList;binary' => '';
## push @attr, 'certificateRevocationList;binary' => '';
## push @attr, 'cACertificate;binary' => '';
push @attr, 'objectclass' => [ 'top',
'organizationalUnit',
'pkiCA'
];
push @attr, 'st' => $cert_st if ($cert_st and $add_dn =~ /\s*st\s*=/i);
push @attr, 'l' => $cert_l if ($cert_l and $add_dn =~ /\s*l\s*=/i);
} elsif ($add_dn =~ /^\s*o\s*=.*$/i) {
if (not $cert_o)
{
LDAP_disconnect ( $ldap );
return { STATUS => 0 ,
DESC => gettext ("The organization is not specified but required
for this objectclass."),
CODE => -103 };
}
push @attr, 'o' => $cert_o;
## push @attr, 'authorityRevocationList;binary' => '';
## push @attr, 'certificateRevocationList;binary' => '';
## push @attr, 'cACertificate;binary' => '';
push @attr, 'objectclass' => [ 'top',
'organization',
'pkiCA'
];
push @attr, 'st' => $cert_st if ($cert_st and $add_dn =~ /\s*st\s*=/i);
push @attr, 'l' => $cert_l if ($cert_l and $add_dn =~ /\s*l\s*=/i);
} elsif ($add_dn =~ /^\s*c\s*=.*$/i) {
if (not $cert_c)
{
LDAP_disconnect ( $ldap );
return { STATUS => 0 ,
DESC => gettext ("The country is not specified but required for
this objectclass."),
CODE => -104 };
}
push @attr, 'c' => $cert_c;
push @attr, 'objectclass' => [ 'top',
'country'
];
} elsif ($add_dn =~ /^\s*st\s*=.*$/i) {
if (not $cert_st)
{
LDAP_disconnect ( $ldap );
return { STATUS => 0 ,
DESC => gettext ("The state is not specified but required for this
objectclass."),
CODE => -105 };
}
push @attr, 'st' => $cert_st;
push @attr, 'objectclass' => [ 'top',
'locality'
];
} elsif ($add_dn =~ /^\s*l\s*=.*$/i) {
if (not $cert_l)
{
LDAP_disconnect ( $ldap );
return { STATUS => 0 ,
DESC => gettext ("The locality is not specified but required for
this objectclass."),
CODE => -106 };
}
push @attr, 'st' => $cert_l;
push @attr, 'objectclass' => [ 'top',
'locality'
];
} else {
LDAP_disconnect ( $ldap );
return { STATUS => 0 ,
DESC => gettext ("The attribute is unknown to OpenCA's ldap-code.
Please report to [EMAIL PROTECTED]"),
CODE => -199 };
}
print "Attributes for the insertion:<br>\n" if ($DEBUG);
for (my $h=0; $h < scalar @attr; $h+=2) {
print "$attr[$h] = $attr[$h+1]<br>\n" if ($DEBUG);
}
print "Must setup a CA-cert<br>\n" if ($DEBUG and $obj->getParsed()->{IS_CA});
print "Must setup a normal cert<br>\n" if ($DEBUG and not
$obj->getParsed()->{IS_CA});
$ldapadd_result = $ldap->add ( $add_dn , attr => [ @attr ] );
print "The resultcode of the nodeinsertion was ".
$ldapadd_result->code.".<br>\n" if ($DEBUG);
last if ($ldapadd_result->code);
}
if ($use_ldap_add) {
if( $ldapadd_result->is_error ) {
## print "<FONT COLOR=\"Red\">";
## print "Error Adding DN [$serID]: " . $ldapadd_result->code ."<BR>\n";
## print "</FONT>";
LDAP_disconnect ( $ldap );
return { STATUS => 0 ,
DESC => i18nGettext ("LDAP-add failed: __ERRVAL__",
"__ERRVAL__", $ldapadd_result->error),
CODE => $ldapadd_result->code };
}
}
LDAP_disconnect ( $ldap );
return { STATUS => 1, CODE => 0, DESC => gettext("Success") };
}
## this function add certificates and CRLs to the directory
sub addLDAPattribute {
my $keys = { @_ };
my $obj;
my $ret;
my $ldap;
my $noprint;
my $dn;
my $attr;
my $txt;
my @values;
my @mails;
my $DEBUG = 0;
if ($keys->{DEBUG}) {
$DEBUG = 1;
}
## check the type of the attribute
if ( $keys->{CERTIFICATE} ) {
$obj = $keys->{CERTIFICATE};
$attr = "userCertificate";
} elsif ( $keys->{AUTHORITY_CERTIFICATE} ) {
$obj = $keys->{AUTHORITY_CERTIFICATE};
$attr = "cACertificate";
} elsif ( $keys->{CRL} ) {
$obj = $keys->{CRL};
$attr = "certificateRevocationList";
} elsif ( $keys->{AUTHORITY_CRL} ) {
$obj = $keys->{AUTHORITY_CRL};
$attr = "authorityRevocationList";
}
$attr .= ";binary";
return { STATUS => 0, CODE => -1, DESC => "No object specified." } if ( not $obj );
## set output mode
$noprint = $keys->{NOPRINT};
$noprint = 0 if ($DEBUG);
## Initializing Connection to LDAP Server
if ( not ( $ldap = LDAP_connect() )) {
return { STATUS => 0, CODE => -3, DESC => gettext ("Connection refused by
server.") };
}
##// Let's bind for a predetermined User
$ret = LDAP_bind( LDAP => $ldap );
if ( $ret->is_error ) {
my $msg = i18nGettext ("LDAP-bind failed: __ERRVAL__",
"__ERRVAL__", $ret->error) ;
LDAP_disconnect( LDAP => $ldap );
return { STATUS => 0, CODE => $ret->code, DESC => $msg };
}
## get dn
if ( $attr =~ /RevocationList/i ) {
$dn = $obj->getParsed()->{ISSUER};
} else { # certificates
$dn = $obj->getParsed()->{DN};
}
$dn =~ s/\//,/g;
$dn =~ s/^ *,* *//g;
## fix problems with big letters
$dn =~ s/email=/email=/i;
$dn =~ s/cn=/cn=/i;
$dn =~ s/c=/c=/i;
$dn =~ s/ou=/ou=/i;
$dn =~ s/o=/o=/i;
$dn =~ s/st=/st=/i;
$dn =~ s/l=/l=/i;
## $serID = $cert->getSerial();
print "addLDAPattribute: DN= ".$dn."<br>\n" if ($DEBUG);
print "attr: ".$attr."<br>\n" if ($DEBUG);
###########################
## build the crypto-data ##
###########################
## search the attribute
my $search_filter = "($attr=*)";
print "LDAP Searchfilter: ".$search_filter."<br>\n" if ($DEBUG);
my $mesg = $ldap->search (
base => $dn,
scope => "base",
filter => $search_filter);
print "LDAP Search Mesg-Code ".$mesg->code."<br>\n" if ($DEBUG);
print "LDAP Search Mesg-Count ".$mesg->count."<br>\n" if ($DEBUG);
## I stop the insertion because of a searcherror too
if ( not $mesg or $mesg->code ) {
## search failed
if (!$noprint) {
print gettext("Search for the attribute failed.")."\n";
}
my $code, $msg;
if ($mesg) {
$code = $mesg->code;
$msg = $mesg->error;
} else {
$code = -4;
$msg = gettext ("LDAP-search failed but the function returned no
message-object.");
}
LDAP_disconnect( LDAP => $ldap );
return { STATUS => 0 , CODE => $code, DESC => $msg };
}
if ( not $mesg->count or ($attr =~ /RevocationList/i)) {
## attribute not present now
@values = ($obj->getDER());
} else {
## we can get only one entry because scope is set to "base"
## load values
@values = $mesg->entry (0)->get_value ( $attr);
push @values, $obj->getDER();
## remove doubles
@values = sort @values;
for (my $i=1; $i < scalar @values; $i++) {
if ($values[$i] eq $values[$i-1]) {
splice @values, $i, 1;
$i--;
}
}
}
##############################
## build the emailaddresses ##
##############################
## search the attribute
$search_filter = "(mail=*)";
print "LDAP Searchfilter: ".$search_filter."<br>\n" if ($DEBUG);
$mesg = $ldap->search (
base => $dn,
scope => "base",
filter => $search_filter);
print "LDAP Search Mesg-Code ".$mesg->code."<br>\n" if ($DEBUG);
print "LDAP Search Mesg-Count ".$mesg->count."<br>\n" if ($DEBUG);
## I stop the insertion because of a searcherror too
if ( not $mesg or $mesg->code ) {
## search failed
if (!$noprint) {
print gettext("Search for the attribute mail failed.")."\n";
}
my $code, $msg;
if ($mesg) {
$code = $mesg->code;
$msg = $mesg->error;
} else {
$code = -4;
$msg = gettext ("LDAP-search failed but the function returned no
message-object.");
}
LDAP_disconnect( LDAP => $ldap );
return { STATUS => 0 , CODE => $code, DESC => $msg };
}
@mails = ();
if ($attr =~ /userCertificate/i) {
if ( not $mesg->count ) {
push @mails, $obj->getParsed()->{EMAILADDRESS} if
($obj->getParsed()->{EMAILADDRESS});
} else {
@mails = $mesg->entry (0)->get_value ("mail");
@mails = () if ((scalar @mails == 1) and not $mails[0]);
my $email = $obj->getParsed()->{EMAILADDRESS};
foreach my $h (@mails) {
if ($h =~ /$email/i) {
$email = "";
last;
}
}
if ($email) {
push @mails, $obj->getParsed()->{EMAILADDRESS};
}
}
}
## insert into ldap
print "Starting LDAP-modify: dn is ".$dn."<br>\n" if ($DEBUG);
if (scalar @mails) {
print "fixing mail too<br>\n" if ($DEBUG);
$mesg = $ldap->modify ($dn, changes => [
replace => [$attr => [ @values ]],
replace => ['mail' => [ @mails ]]
]);
} else {
$mesg = $ldap->modify ($dn, changes => [
replace => [$attr => [ @values ]]
]);
}
if( $mesg->code ) {
$txt = i18nGettext ("Error __ERRNO__: __ERRVAL__",
"__ERRNO__", $mesg->code,
"__ERRVAL__", $mesg->error);
if (!$noprint) {
print "$txt\n";
}
LDAP_disconnect( LDAP => $ldap );
return { STATUS => 0 , CODE => $mesg->code, DESC => $mesg->error };
}
$txt = gettext("Attribute successfully inserted.");
LDAP_disconnect( LDAP => $ldap );
if (!$noprint) {
print i18nGettext ("Success (__MESSAGE__)", "__MESSAGE__", $txt)."\n";
}
return { STATUS => 1,
DESC => i18nGettext ("Success (__MESSAGE__)", "__MESSAGE__", $txt),
CODE => 0 };
}
## this function add certificates and CRLs to the directory
sub deleteLDAPattribute {
my $keys = { @_ };
my $obj;
my $ret;
my $ldap;
my $noprint;
my $dn;
my $attr;
my $txt;
my @values;
my $DEBUG = 0;
if ($keys->{DEBUG}) {
$DEBUG = 1;
}
## check the type of the attribute
if ( $keys->{CERTIFICATE} ) {
$obj = $keys->{CERTIFICATE};
$attr = "userCertificate";
} elsif ( $keys->{AUTHORITY_CERTIFICATE} ) {
$obj = $keys->{AUTHORITY_CERTIFICATE};
$attr = "cACertificate";
} elsif ( $keys->{CRL} ) {
$obj = $keys->{CRL};
$attr = "certificateRevocationList";
} elsif ( $keys->{AUTHORITY_CRL} ) {
$obj = $keys->{AUTHORITY_CRL};
$attr = "authorityRevocationList";
}
$attr .= ";binary";
return { STATUS => 0, CODE => -1, DESC => "No object specified." } if ( not $obj );
## set output mode
$noprint = $keys->{NOPRINT};
$noprint = 0 if ($DEBUG);
## Initializing Connection to LDAP Server
if ( not ( $ldap = LDAP_connect() )) {
return { STATUS => 0, CODE => -3, DESC => gettext ("Connection refused by
server.") };
}
##// Let's bind for a predetermined User
$ret = LDAP_bind( LDAP => $ldap );
if ( $ret->is_error ) {
my $msg = i18nGettext ("LDAP-bind failed: __ERRVAL__",
"__ERRVAL__", $ret->error) ;
LDAP_disconnect( LDAP => $ldap );
return { STATUS => 0, CODE => $ret->code, DESC => $msg };
}
## get dn
if ( $attr =~ /RevocationList/i ) {
$dn = $obj->getParsed()->{ISSUER};
} else { # certificates
$dn = $obj->getParsed()->{DN};
}
$dn =~ s/\//,/g;
$dn =~ s/^ *,* *//g;
## fix problems with big letters
$dn =~ s/email=/email=/i;
$dn =~ s/cn=/cn=/i;
$dn =~ s/c=/c=/i;
$dn =~ s/ou=/ou=/i;
$dn =~ s/o=/o=/i;
$dn =~ s/st=/st=/i;
$dn =~ s/l=/l=/i;
## $serID = $cert->getSerial();
print "deleteLDAPattribute: DN= ".$dn."<br>\n" if ($DEBUG);
print "attr: ".$attr."<br>\n" if ($DEBUG);
## search the attribute
my $search_filter = "($attr=*)";
print "LDAP Searchfilter: ".$search_filter."<br>\n" if ($DEBUG);
my $mesg = $ldap->search (
base => $dn,
scope => "base",
filter => $search_filter);
print "LDAP Search Mesg-Code ".$mesg->code."<br>\n" if ($DEBUG);
print "LDAP Search Mesg-Count ".$mesg->count."<br>\n" if ($DEBUG);
## I stop the insertion because of a searcherror too
if ( not $mesg or $mesg->code ) {
## search failed
if (!$noprint) {
print gettext("Search for the attribute failed.")."\n";
}
my $code, $msg;
if ($mesg) {
$code = $mesg->code;
$msg = $mesg->error;
} else {
$code = -4;
$msg = gettext ("LDAP-search failed but the function returned no
message-object.");
}
LDAP_disconnect( LDAP => $ldap );
return { STATUS => 0 , CODE => $code, DESC => $msg };
}
my $entry = $mesg->entry (0);
if ( $attr =~ /RevocationList/i ) {
## attribute not present now
@values = ();
$entry->replace ( $attr => [ @values ] );
} else {
## we can get only one entry because scope is set to "base"a
## load values
@values = $entry->get_value ( $attr);
## remove doubles
@values = sort @values;
for (my $i=1; $i < scalar @values; $i++) {
if ($values[$i] eq $values[$i-1]) {
splice @values, $i, 1;
$i--;
}
}
## remove the specified object
@values = sort @values;
for (my $i=0; $i < scalar @values; $i++) {
if ($values[$i] eq $obj->getDER()) {
splice @values, $i, 1;
$i--;
}
}
$entry->replace ( $attr => [ @values ] );
}
## update ldap
print "Starting LDAP-modify: dn is ".$dn."<br>\n" if ($DEBUG);
$mesg = $entry->update ($ldap);
if( $mesg->code ) {
$txt = i18nGettext ("Unknown Error ( __ERRNO__ )", "__ERRNO__", $mesg->code);
if (!$noprint) {
print "$txt\n";
}
LDAP_disconnect( LDAP => $ldap );
return { STATUS => 0 , CODE => $mesg->code, DESC => $mesg->error };
}
$txt = gettext ("Attribute successfully deleted.");
LDAP_disconnect( LDAP => $ldap );
if (!$noprint) {
print i18nGettext ("Success (__MESSAGE__)", "__MESSAGE__", $txt)."\n";
}
return { STATUS => 1,
DESC => i18nGettext ("Success (__MESSAGE__)", "__MESSAGE__", $txt),
CODE => 0 };
}
sub LDAPsearch {
my $keys = { @_ };
my ( $mseg, $ldap, $limit, $ldapBase, $serID, $filter, $ret );
$filter = $keys->{FILTER};
$serID = $keys->{SERIAL};
return if ( not $filter );
## Get required configuration keys
$ldapBase = getRequired( 'basedn' );
## Initializing Connection to LDAP Server
if ( not ( $ldap = LDAP_connect() )) {
print "<FONT COLOR=\"Red\">";
print i18nGettext ("LDAP [__CERT_SERIAL__]: Connection Refused by
server!", "__CERT_SERIAL__", $serID)."\n";
print "</FONT><BR>\n";
return;
};
##// Let's bind for a predetermined User
$ret = LDAP_bind( LDAP => $ldap );
if( $ret->is_error ) {
print i18nGettext ("Failed in Bind: __ERRNO__", "__ERRNO__",
$ret->{CODE}) . "\n";
LDAP_disconnect( LDAP => $ldap );
return $ret->{CODE};
};
my $mesg = $ldap->search ( base => "$ldapBase",
filter => "$filter" );
if ( $mesg->code ) {
LDAP_disconnect( LDAP => $ldap );
return;
}
return { COUNT => $mesg->count, ENTRIES => $mesg->entries };
};
sub LDAP_connect {
my $keys = { @_ };
my ( $ldap, $ldapSrv, $port, $ldapVersion);
## Initializing Connection to LDAP Server
$ldapSrv = getRequired('ldapserver');
$port = getRequired('ldapport');
$ldapVersion = getRequired('ldapversion');
## if no initialization found, get defaults
$port = 389 if (not $port);
## Get the Connection to the Server
$ldap = Net::LDAP->new ($ldapSrv,
port => $port,
async => 0,
version => $ldapVersion );
return undef if( not $ldap );
return $ldap;
}
sub LDAP_disconnect {
my $keys => [EMAIL PROTECTED];
my $ldap = $keys->{LDAP};
return {STATUS => 0 } if ( not $ldap );
$ldap->unbind;
return {STATUS => 1};
}
sub LDAP_bind {
my $keys = [EMAIL PROTECTED];
## Get Required Parameters
my $ldapUsr = getRequired('ldaproot');
my $ldapPwd = getRequired('ldappwd');
## Get ldap passed ref
my $ldap = $keys->{LDAP};
## Return if no object passed
return if( not $ldap );
## Try to bind to selected user
my $mesg = $ldap->bind( "$ldapUsr", 'password' => "$ldapPwd" );
## if got an error, return it
if ( $mesg->code ) {
LDAP_disconnect( LDAP => $ldap );
}
return $mesg;
}
sub LDAP_get_crl {
## determine the newest CRL
my $keys = { @_ };
my $DEBUG = 0;
if ($keys->{DEBUG}) {
$DEBUG = 1;
}
print "ldap-utils.lib: LDAP_get_crl: try to determine the newest CRL<br>\n"
if ($DEBUG);
my @list = $db->searchItems ( DATATYPE => "CRL" );
my $newest_crl = undef;
my $newest_timestamp = 0;
foreach my $h (@list) {
my $timestamp = $cryptoShell->getNumericDate
($h->getParsed()->{LAST_UPDATE});
print "ldap-utils.lib: LDAP_get_crl: check date $timestamp<br>\n"
if ($DEBUG);
if ($newest_timestamp < $timestamp) {
if ($DEBUG) {
print "ldap-utils.lib: LDAP_get_crl: newer crl
found<br>\n";
print "ldap-utils.lib: LDAP_get_crl: timestamp:
$timestamp<br>\n";
print "ldap-utils.lib: LDAP_get_crl:
crl:<br>\n".$h."<br>\n";
}
$newest_timestamp = $timestamp;
$newest_crl = $h;
}
}
print "ldap-utils.lib: LDAP_get_crl: return newest crl<br>\n" if ($DEBUG);
return $newest_crl;
}
sub LDAP_get_ca {
## determine the newest CA-cert
my $keys = { @_ };
my $DEBUG = 0;
if ($keys->{DEBUG}) {
$DEBUG = 1;
}
print "ldap-utils.lib: LDAP_get_ca: try to determine the newest CA-cert<br>\n"
if ($DEBUG);
my @list = $db->searchItems ( DATATYPE => "CA_CERTIFICATE" );
my $newest_ca = undef;
my $newest_notbefore = 0;
foreach my $h (@list) {
my $notbefore = $cryptoShell->getNumericDate
($h->getParsed()->{NOTBEFORE});
print "ldap-utils.lib: LDAP_get_ca: check NOTBEFORE $notbefore<br>\n"
if ($DEBUG);
if ($newest_notbefore < $notbefore) {
if ($DEBUG) {
print "ldap-utils.lib: LDAP_get_ca: newer ca-cert
found<br>\n";
print "ldap-utils.lib: LDAP_get_ca: notbefore:
$notbefore<br>\n";
print "ldap-utils.lib: LDAP_get_ca:
ca:<br>\n".$h."<br>\n";
}
$newest_notbefore = $notbefore;
$newest_ca = $h;
}
}
print "ldap-utils.lib: LDAP_get_ca: return newest ca<br>\n" if ($DEBUG);
return $newest_ca;
}
sub LDAP_getDN {
## first argument must be the DN
return undef if (not $_[0]);
my $DEBUG = $_[1];
print "LDAP_getDN called<br>\n" if ($DEBUG);
print "LDAP_getDN: dn: ".$_[0]."<br>\n" if ($DEBUG);
## parse dn
my $dn = X500::DN->ParseRFC2253 ($_[0]);
return undef if (not $dn);
## has problems but we don't support multivalued attributes
return undef if ($dn->hasMultivaluedRDNs());
print "LDAP_getDN successfully finished<br>\n" if ($DEBUG);
return $dn;
}
sub LDAP_getSuffix {
my $dn = $_[0];
my $DEBUG = $_[1];
print "LDAP_getSuffix called<br>\n" if ($DEBUG);
my @suffix_list = getRequiredList ('basedn');
my $suffix_dn;
foreach my $suffix (@suffix_list)
{
$suffix_dn = LDAP_getDN ($suffix, $DEBUG);
return undef if (not $suffix_dn);
my $res = LDAP_cmpDN ($dn, $suffix_dn, $DEBUG);
last if (defined $res and $res >= 0);
undef $suffix_dn;
}
print "LDAP_getSuffix successfully finished<br>\n" if ($DEBUG);
return $suffix_dn;
}
sub LDAP_cmpDN {
my $dn_1 = $_[0];
my $dn_2 = $_[1];
my $DEBUG = $_[2];
print "LDAP_cmpDN called<br>\n" if ($DEBUG);
my @rdn_list_1 = $dn_1->getRDNs;
my @rdn_list_2 = $dn_2->getRDNs;
my $length = scalar @rdn_list_1;
$length = scalar @rdn_list_2 if (scalar @rdn_list_1 > scalar @rdn_list_2);
print "LDAP_cmpDN: looping<br>\n" if ($DEBUG);
for (my $i=0; $i < $length; $i++)
{
## we don't support multivalued attributes
my @type_1 = $rdn_list_1[$i]->getAttributeTypes;
my @type_2 = $rdn_list_2[$i]->getAttributeTypes;
my $value_1 = $rdn_list_1[$i]->getAttributeValue ($type_1[0]);
my $value_2 = $rdn_list_2[$i]->getAttributeValue ($type_2[0]);
## normalization
$type_1[0] = lc $type_1[0];
$type_2[0] = lc $type_2[0];
$value_1 = lc $value_1;
$value_2 = lc $value_2;
## compare types
return undef if ($type_1[0] ne $type_2[0]);
return undef if ($value_1 ne $value_2);
}
print "LDAP_cmpDN successfully finished<br>\n" if ($DEBUG);
return 0 if (scalar @rdn_list_1 == scalar @rdn_list_2);
return -1 if (scalar @rdn_list_1 < scalar @rdn_list_2);
return 1;
}
sub LDAP_getPath {
my @node = $_[0]->getRDNs;
my @suffix = $_[1]->getRDNs;
my $DEBUG = $_[2];
print "LDAP_getPath called<br>\n" if ($DEBUG);
my @path = ();
for (my $i=scalar @suffix; $i < scalar @node; $i++)
{
## we don't support multivalued attributes
push @path, [($node[$i]->getAttributeTypes)[0],
$node[$i]->getAttributeValue (
($node[$i]->getAttributeTypes)[0]
)
];
}
print "LDAP_getPath successfully finished<br>\n" if ($DEBUG);
return @path;
}
1;
