Hi,

We're using the "Novell LDAP Libraries for C" to make a connection from
our software to LDAP and having a problem with SSL Certificates.
Connecting over 389 works fine however, one we attempt to connect over
636 we run into problems. Some self-signed certificates, however when we
are using a Root Certificate say from an Active Directory Certificate
Authority the connect fails. Anoter scenario is with Certificate Chains
that involve DoD certificates.

ENVIRONMENT:
CLDAP: Version 8.8.4
Home Page: http://www.novell.com/developer/ndk/...ies_for_c.html
Windows 2008 R2 64-bit

TESTING:
Our code will uses the LDAPSDK.DLL, LDAPSSL.DLL and LDAPX.DLL files from
the CLDAP package, when the connection fails we receive
'ldap_simple_bind_s' and reports error code 81. Using the very same
certificates through an LDAP browser such as SoftTerra, LDP.exe, Apache
Studio etc works successfully.

CERTIFICATES:
Are there any specific requirements of an SSL Certificate that these
..dll's require? We've seen a number of various customer Certificates
fail which makes me think there is something that is required and isn't
being met when the Certs are created.

CODE:
Our code will call a .cfg file which is formated as follows.

server=<IP or FQDN>
port=636
certpath=<Path to Cert>
who=<DN of user with permissions to LDAP>
passwd=<Password for above user>

Here is the code itself ...


*// LDAPSSLTest.cpp : Defines the entry point for the console
application.
* //
#include <stdio.h>
#include <stdlib.h>

#if (defined(_WIN64) || defined(WIN32))
#include <Winsock2.h>
#endif

#include <assert.h>
#include <string>
#include <vector>
#include <map>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;

#include "ldap.h"
#include "ldap_ssl.h"

string sLDAPServer; //LDAP server
string sCertPath; // cert path
int nPort; // port

string sWho;
string sPasswd; //password

// parse comand line helpers
bool iequals(const std::string &s1, const std::string &s2)
{
#if (defined(_WIN64) || defined(WIN32))
return (_stricmp (s1.c_str(), s2.c_str())==0);
#else
return (strcasecmp (s1.c_str(), s2.c_str())==0);
#endif
}
void tokenize(const string& str, vector<string>& tokens, const string&
delimiters)
{
string::size_type lastPos = str.find_first_not_of(delimiters, 0);

string::size_type pos = str.find_first_of(delimiters, lastPos);
while (string::npos != pos || string::npos != lastPos)
{
tokens.push_back(str.substr(lastPos, pos - lastPos));
lastPos = str.find_first_not_of(delimiters, pos);
pos = str.find_first_of(delimiters, lastPos);
}
}

bool Initialize(int argc, char* argv[])
{
try
{
const string sConfigFileSplitter = string("=");//
defaultsplitter
if (argc !=2)
{
cout << "Usage: ldapssltest <configfilename>\n";
return false;
}

string sFileName=argv[1];
std::ifstream ifs(sFileName.c_str());
if(!ifs.is_open())
return false;

while (!ifs.eof() )
{
string line;
getline (ifs, line);

string::size_type pos =
line.find_first_of(sConfigFileSplitter);
if (pos != string::npos)
{
string sKey=line.substr(0, pos);
string sValue=line.substr(pos+1);

std::stringstream ss(sValue);

if (iequals(sKey, string("server")))
sLDAPServer=sValue;

if (iequals(sKey, string("port")))
{
std::stringstream ss(sValue);
ss>>nPort;
}

if (iequals(sKey, string("certpath")))
sCertPath=sValue;

if (iequals(sKey, string("who")))
sWho=sValue;

if (iequals(sKey, string("passwd")))
sPasswd=sValue;
}
}
}
catch(const std::exception& e)
{
cout << "ldapssltest parsing command line error occurred: " <<
e.what() <<std::endl;
return false;
}
return true;
}


int main(int argc, char* argv[])
{
if (!Initialize(argc, argv))
return 0;

int errorCode = 0;
// Set LDAP version to 3 and set timeout
struct timeval timeOut = {10,0}; /* 10 second connection
timeout */
if ( (errorCode=ldap_set_option( NULL, LDAP_OPT_NETWORK_TIMEOUT,
&timeOut )) != LDAP_SUCCESS )
{
cout<<"Unable to set the network timeout: "<<ldap_err2string(
errorCode )<<endl;
return 0;
}

int version = LDAP_VERSION3;
if ( (errorCode=ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION,
&version )) != LDAP_SUCCESS )
{
cout<<"Unable to set the LDAP protocol to version 3:
"<<ldap_err2string( errorCode )<<endl;
return 0;
}

if ( (errorCode=ldap_set_option( NULL, LDAP_OPT_REFERRALS,
LDAP_OPT_ON )) != LDAP_SUCCESS )
{
cout<<"Unable to enable LDAP referrals: "<<ldap_err2string(
errorCode )<<endl;
}

if (sCertPath.length()!=0)
{
if ((errorCode=ldapssl_client_init( sCertPath.c_str(), NULL ))==
LDAP_SUCCESS)
{
cout<<"Initialized LDAP SSL client:"<<sLDAPServer<<" Port:
"<<nPort<<endl;
LDAP* pLDAP = ldapssl_init( sLDAPServer.c_str(), nPort, 1
);
if ( pLDAP != NULL)
{
cout<<"LDAP SSL server initialization
successfull."<<endl;
cout<<"Bind DN or user: "<<sWho<<" Bind password:
"<<sPasswd<<endl;
errorCode=ldap_simple_bind_s( pLDAP, (sWho.length()>0)?
sWho.c_str(): NULL, (sPasswd.length()>0)? sPasswd.c_str(): NULL );

if (errorCode== LDAP_SUCCESS)
{
cout<<"Successfully bind to ldap"<<endl;
ldap_unbind_s( pLDAP );
}
else{
cout<<"LDAP simple bind failed:
"<<ldap_err2string(errorCode)<<endl;
cout<<"error code: "<<errorCode<<endl;
}
}
else{
cout<<"SSL server initialization failed:
"<<ldap_err2string( ldap_get_lderrno((pLDAP),NULL,NULL))<<endl;
cout<<"error number: "<<ldap_get_lderrno(pLDAP, NULL,
NULL)<<endl;
}
ldapssl_client_deinit();
}
else{
cout<<"LDAP SSL client initialization failed:
"<<ldap_err2string( errorCode )<<endl;
cout<<"error code: "<<errorCode<<endl;
}
}
else{

cout<<"Initialized LDAP client: "<<sLDAPServer<<" Port:
"<<nPort<<endl;
LDAP* pLDAP = ldap_init( sLDAPServer.c_str(), nPort );
if ( pLDAP != NULL)
{
cout<<"LDAP server initialization successfull."<<endl;

cout<<"Bind DN or user: "<<sWho<<" Bind password:
"<<sPasswd<<endl;

errorCode=ldap_simple_bind_s( pLDAP, (sWho.length()>0)?
sWho.c_str(): NULL, (sPasswd.length()>0)? sPasswd.c_str(): NULL );

if (errorCode== LDAP_SUCCESS)
{
cout<<"Successfully bind to ldap"<<endl;
ldap_unbind_s( pLDAP );
}
else{
cout<<"LDAP simple bind failed:
"<<ldap_err2string(errorCode)<<endl;
cout<<"error number: "<<ldap_get_lderrno(pLDAP, NULL,
NULL)<<endl;
}
}
else{
cout<<"LDAP client initialization failed:
"<<ldap_err2string( errorCode )<<endl;
cout<<"error code: "<<errorCode<<endl;
}
}
return 0;
}

Any help would really be appreciated.

Thanks,
-Mark


--
simmm
------------------------------------------------------------------------
simmm's Profile: https://forums.netiq.com/member.php?userid=2736
View this thread: https://forums.netiq.com/showthread.php?t=44978