To start with: a few words of warning for Windows developers. If you are deemed to work with MS Visual Studio 6 (as I am, due to some compatibility reasons), you may notice "mysterious" behaviour of your code: it will simply crash with no reason, while executing a call to LDAP functions. This is caused by the fact that the version of wldap32.lib that is shipped with VS6 does not "match" the DLL that you find in your windows xp, etc (all in all: VS6 is an "ancient" stuff). Just look at these article from Microsoft's support: 283199, and this discussion . Apparently, you need an updated version of wldap32.lib file... The problem is that VS6 is not supported anymore, and there's no Microsoft SDK available for it anymore!
What you could do, however, is to get the wldap32.h from a newer version of Visual Studio, and copy it to your VS6's \Lib subdirectory (overwriting the old one!). You could also get this file from one of the newer SDK's, but remember: the SDK will NOT work with your VS6...
To be able to find out whether you have an "old" version of wldap32.lib, or the new one, have a look at the date of this file (usually in C:\Program Files\Microsoft Visual Studio\VC98\Lib ): if it is 13 May 1998, then it is the "buggy" one and needs to be replaced. I have one with date 14 April 2005 (got it from one of SDK's) and it works OK.
A few more words... Don't try to "upgrade" the include file the same way (i.e. the winldap.h)... there are some conflicts and the compiler cannot cope with mismatched versions. Just leave your old one as it is! All in all - you may always re-declare the newer, missing parts in your implementation file.
OK. Let's get into something real now. My problem is: I want to implement an authentication mechanism, that will be based on the Active Directory, i.e. I want that the user may authenticate to my program with the same credentials as he uses to log in to the Windows machine at our site (and all these Windows machines are managed using Active Directory).
For those of us who do not speak windows :-) : Active Directory is basically an LDAP server, holding various administrative information for Windows. We want to treat it simply as an LDAP server that can do authentication for us.
The following code demonstrates authentication on Windows. Note that you need to link it against wldap32.lib !
#include "stdafx.h"
#include
#include
#include
bool HandleError(int rc, const char* what)
{
if (rc==0) return false; // no error
if (rc==-1) rc=LdapGetLastError();
printf("ERROR in %s: %i %s\n",what,rc,ldap_err2string(rc));
return true;
}
int main(int argc, char* argv[])
{
char *ldapHost="myLdapServer.mydomain.org";
char *userName="myUserName";
char *password="myPassword";
// initialize
LDAP *ldap=ldap_init(ldapHost,LDAP_PORT);
if (ldap==NULL) {printf("\nERROR in ldap_init\n\n"); return -1;}
// set LDAP version
unsigned ldapver=LDAP_VERSION3;
int rc=ldap_set_option(ldap,LDAP_OPT_PROTOCOL_VERSION, (void*)&ldapver);
if (HandleError(rc,"set protocol version")) return -1;
// set connection timeout, and connect
LDAP_TIMEVAL connectionTimeout;
LDAP_TIMEVAL *pConTimeout=&connectionTimeout;
connectionTimeout.tv_sec=10;
rc = ldap_connect(ldap, pConTimeout);
if (HandleError(rc,"Connect")) return -1;
// credentials for SASL/DIGEST-MD5 are passed through this
// data structure; you need #include
SEC_WINNT_AUTH_IDENTITY auth;
auth.Domain=NULL; // may be left empty!
auth.DomainLength=0;
auth.User=(unsigned char*)strdup(userName);
auth.UserLength=strlen(userName);
auth.Password=(unsigned char*)strdup(password);
auth.PasswordLength=strlen(password);
auth.Flags=SEC_WINNT_AUTH_IDENTITY_ANSI;
char* bindDN=NULL; // credentials already defined above! Leave empty!!!
rc=ldap_bind_s(ldap,bindDN,(char*)&auth,LDAP_AUTH_NEGOTIATE);
if (HandleError(rc,"Bind")) return -1;
rc=ldap_unbind_s(ldap);
if (HandleError(rc,"Unbind")) return -1;
return 0;
}
As you can see, we use the standard ldap_bind_s function to perform the bind (authentication), and we pass the authentication credentials in the SEC_WINNT_AUTH_IDENTITY structure. Note that you need to change the ldapHost, userName and password to represent yours, to make the thing actually work.
In the next post I describe how to make SASL/DIGEST-MD5 authentication work with ActiveDirectory using OpenLDAP, i.e. on Linux.
(c) Piotr Golonka 2007
No comments:
Post a Comment