Bonjour à tous !
Je suis confronté à une difficulté depuis maintenant presque 2 semaines et, étant cours d'idée sur le sujet, je viens partager celui-ci avec vous.
Le sujet : développement d'un requêteur LDAP en c++. Jusque là rien de bien compliqué mais de multiples contraintes ont rendu ce projet sans-fin. Le serveur a requêter est un LDAP Lotus Domino en SSL. Le développement est fait avec Visual Studio 2013 Pro (chaque possibilité décrites ci-dessous ont aussi été testé avec VS 2008 Pro).
J'ai donc commencé par utiliser la librairie winldap. Le fonctionnement est Ok sur l'ensemble de mes serveurs de tests, mais sur le serveur cible cela ne fonctionnait que sur WinXP, pas Win7. Afin de valider le fonctionnement de l'outil, j'ai effectué les même tests avec deux soft du commerce : Softerra Ldap Browser 2.6 et Softerra Ldap Browser 4.5 (www.ldapbrowser.com)
Résultat des tests :
- Softerra LDAP Browser 2.6 sur WinXP : OK
- Softerra LDAP Browser 2.6 sur Win7 : OK
- Softerra LDAP Browser 4.5 sur WinXP : OK
- Softerra LDAP Browser 4.5 sur Win7 : KO
- Mon outil sur WinXP : OK
- Mon outil sur Win7 : KO
Lors d'un KO, le code erreur LDAP est 0x51 ==> LDAP_SERVER_DOWN.
Le message dans le journal d'activité windows est plus explicite :
Pour info, le certificat utilisé :Fatal alert 40, Internal error 107.
An SSL 3.0 connection request was received from a remote client application , but none of the cipher suites supported by the client application is supported by the server. The SSL connection request has failed.
Bon, déjà je me dit que mon outil n'est pas complètement naze, il fonctionne sur l'ensemble des serveurs quel que soit la plateforme sur lequel il est déployé, il fonctionne sur le serveur cible depuis WinXP mais surtout il a exactement le même comportement que le soft de Softerra.Key Info - RSA 2048-bit Signature Algorithm - SHA-1 with RSA Encryption Product Name - Digital ID Class 3 - VeriSign Global Server OnSite Two Year
Possibilité N°1 - Bascule sur Mozilla LDAP C-SDK
La question qui se pose après ces tests c'est pourquoi la 2.6 fonctionne quelle que soit la plateforme mais pas la 4.5 (et donc mon outils) ? Après quelques recherches, la 2.6 est basée sur Mozilla LDAP C-SDK contrairement à la version 4.5 basé sur winldap.
Ok, je vais donc migrer sur Mozilla LDAP C-SDK (https://wiki.mozilla.org/LDAP_C_SDK).
Les sources étant disponibles, il "suffit" de les compiler et j'aurais ma bibliothèque mais la compilation ne se passe pas aussi bien que je ne l'aurais voulu. Pour compiler j'ai utiliser cygwin et l'autoconf, mais un paquet d'erreur ne m'ont pas permit de continuer :
Et pourtant :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 sh ../../../config/cygwin-wrapper gcc -o decode.o -c -pipe -pthread -O -UDEBUG -DNDEBUG=1 -DXP_PC=1 -DWIN32=1 -D_WINDOWS=1 -DWINNT=1 -D_X86_=1 -DFORCE_PR_LOG -DUSE_WAITPID -DNEEDPROTOS -DNET_SSL -DNO_LIBLCACHE -DLDAP_REFERRALS -DNS_DOMESTIC -I../../../ldap/include -I../../../../../dist/./include decode.c gcc: erreur: /ID:/mozldap-6.0.7/mozldap-6.0.7/c-sdk/ldap/include: No such file or directory
Étonnant, et je n’arrive pas à me l'expliquer.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 $ ls D:/mozldap-6.0.7/mozldap-6.0.7/c-sdk/ldap/included isptmpl.h lber.h ldap.h ldap-deprecated.h ldaplog.h ldappr.h ldap-standard-tmpl.h ldif.h Makefile.client MANIFEST proto-ntutil.h srchpref.h iutil.h lcache.h ldap_ssl.h ldap-extension.h ldap-platform.h ldaprot.h ldap-to-be-deprecated.h Makefile Makefile.in portable.h regex.h
J'ai essayé de me tourner vers une version binaire de cette bibliothèque : ftp://ftp.mozilla.org/pub/mozilla.or...leases/v6.0.4/
Pas mieux, lors de l'exécution :
D'après le msdn il s'agit d'un problème de manifest, mais ma dll est bien déclaré (de plus j'ai essayé de compiler avec mingw mon code et le message d'erreur est le même).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 Runtime Error! R6034 An application has made an attempt to load the C runtime library incorrectly.
Mon code de test :
J'aimerais arriver à compiler la bibliothèque, mais je sèche complètement sur le sujet.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 #include <iostream> #include <ldap.h> #include <sasl.h> using namespace std; static int sasl_flags = LDAP_SASL_QUIET; static char *sasl_mech = "GSSAPI"; #define VALIDVAL(n) ((n >= SASL_CB_USER) && (n <= SASL_CB_GETREALM)) #define VAL(n) default_values[n-0x4001] static int example_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *prompts) { if (prompts == NULL) { return (LDAP_PARAM_ERROR); } return (LDAP_SUCCESS); } int main() { int rc; LDAP *ld; LDAPControl **ctrls = NULL; int ldversion = LDAP_VERSION3; int debuglevel = 0; ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debuglevel); if ((ld = ldap_init("10.5.97.2", 636)) == NULL) { return 1; } ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion); rc = ldap_sasl_interactive_bind_ext_s(ld, "", sasl_mech, NULL, NULL, sasl_flags, example_sasl_interact, NULL, &ctrls); if (rc != LDAP_SUCCESS) { ldap_perror(ld, "Bind Error"); } else { sasl_ssf_t ssf; unsigned long val = 0; if (!ldap_get_option(ld, LDAP_OPT_X_SASL_SSF, &ssf)) { val = (unsigned long)ssf; } cout << "Bind successful, security level is " << val << endl; } return 0; }
Possibilité N°2 - Bascule sur SUN LDAP C-SDK
Après quelques recherches, SUN a la même chose que mozilla mais livre les binaires (c'est la même bibliothèque avec quelques modifications notamment sur la partie SSL, on y retrouve des référence à Mozilla) ==> https://oss.oracle.com/projects/sun-ldapcsdk/.
Malheureusemennt, ils fournissent les .dll, les .h mais pas de .lib ou de .o. J'ai donc voulu générer mes .lib via l'utilisation de expdef.exe (http://purefractalsolutions.com/show.php?a=utils/expdef) et de LIB.exe de VS2008.
J'ai commencé par m'attaquer à nsldap32v50.dll, un dumpbin.exe de cette DLL me donne (ceci n'est pas le résultat complet, juste une extraction) :
Un dumpbin.exe du .lib généré :LIBRARY NSLDAP32V50.dll
EXPORTS
ldap_abandon @10
ldap_add @11
ldap_unbind @13
....
ldap_set_option @418
...
Impec Un rapide code de test :Dump of file nsldap32v50.lib
File Type: LIBRARY
Exports ordinal name
...
418 _ldap_set_option
...
Et je me prend un erreur lors du link :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <ldap.h> int main(int argc, _TCHAR* argv[]) { LDAP *ld; LDAPMessage *result, *e; BerElement *ber; char *a, *dn; char **vals; int i; int ldversion = LDAP_VERSION3; int debuglevel = 7; LDAPControl **ctrls = NULL; ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debuglevel); std::cout << "Hellow World !" << std::endl; return 0; }
La librairie est pourtant bien linké. Par contre le link recherche l'adresse de la fonction _ldap_set_option@12 alors que mes lib et dll sont au format _ldap_set_option.TestLdapSun.obj : error LNK2001: unresolved external symbol _ldap_set_option@12
TestLdapSun.exe : fatal error LNK1120: 1 unresolved externals
Donc un problème de convention de nommage. En farfouillant dans les .h de SUN, je tombe là dessus :
avec :
Code : Sélectionner tout - Visualiser dans une fenêtre à part LDAP_API(int) LDAP_CALL ldap_set_option( LDAP *ld, int option, const void *optdata );
Ok, je change le DEFINE pour utiliser la "bonne" convention de nommage :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 #define LDAP_PASCAL __stdcall #define LDAP_CALL LDAP_PASCAL
Et là, miracle, ça link
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 #define LDAP_PASCAL __cdecl #define LDAP_CALL LDAP_PASCAL
Mais lors de l'exécution :
Et oui, c'était trop beau et le changement de convention de nommage à la sauvage je le sentais moyen.Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function pointer declared with a different calling convention.
Pareil que pour la première possibilité, je sèche complètement là dessus.
Si vous avez des idées ou des pistes de réflexions sur l'une ou l'autre possibilité, je suis preneur.
Désolé pour la longueur du post, mais il me semblait important de vous présenter la démarche m'ayant conduit à ces résultats.
Merci d'avance à vous et bonne journée
Partager