moved here from the newlib branch
[platform/upstream/curl.git] / lib / ldap.c
1 /*****************************************************************************
2  *                                  _   _ ____  _     
3  *  Project                     ___| | | |  _ \| |    
4  *                             / __| | | | |_) | |    
5  *                            | (__| |_| |  _ <| |___ 
6  *                             \___|\___/|_| \_\_____|
7  *
8  *  The contents of this file are subject to the Mozilla Public License
9  *  Version 1.0 (the "License"); you may not use this file except in
10  *  compliance with the License. You may obtain a copy of the License at
11  *  http://www.mozilla.org/MPL/
12  *
13  *  Software distributed under the License is distributed on an "AS IS"
14  *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
15  *  License for the specific language governing rights and limitations
16  *  under the License.
17  *
18  *  The Original Code is Curl.
19  *
20  *  The Initial Developer of the Original Code is Daniel Stenberg.
21  *
22  *  Portions created by the Initial Developer are Copyright (C) 1998.
23  *  All Rights Reserved.
24  *
25  * ------------------------------------------------------------
26  * Contributor(s):
27  *  Bjørn Reese <breese@mail1.stofanet.dk>
28  *
29  *      http://curl.haxx.nu
30  *
31  * $Source$
32  * $Revision$
33  * $Date$
34  * $Author$
35  * $State$
36  * $Locker$
37  *
38  * ------------------------------------------------------------
39  ****************************************************************************/
40
41 /* -- WIN32 approved -- */
42 #include <stdio.h>
43 #include <string.h>
44 #include <stdarg.h>
45 #include <stdlib.h>
46 #include <ctype.h>
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include <errno.h>
50
51 #include "setup.h"
52
53 #if defined(WIN32) && !defined(__GNUC__)
54 #else
55 # ifdef HAVE_UNISTD_H
56 #  include <unistd.h>
57 # endif
58 # ifdef HAVE_DLFCN_H
59 #  include <dlfcn.h>
60 # endif
61 #endif
62
63 #include "urldata.h"
64 #include <curl/curl.h>
65 #include "sendf.h"
66 #include "escape.h"
67
68 #define _MPRINTF_REPLACE /* use our functions only */
69 #include <curl/mprintf.h>
70
71
72 #define DYNA_GET_FUNCTION(type, fnc) \
73   (fnc) = (type)DynaGetFunction(#fnc); \
74   if ((fnc) == NULL) { \
75     return CURLE_FUNCTION_NOT_FOUND; \
76   } \
77
78 /***********************************************************************
79  */
80 static void *libldap = NULL;
81 static void *liblber = NULL;
82
83 static void DynaOpen(void)
84 {
85 #if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL)
86   if (libldap == NULL) {
87     /*
88      * libldap.so should be able to resolve its dependency on
89      * liblber.so automatically, but since it does not we will
90      * handle it here by opening liblber.so as global.
91      */
92     dlopen("liblber.so",
93 #ifdef RTLD_LAZY_GLOBAL /* It turns out some systems use this: */
94            RTLD_LAZY_GLOBAL
95 #else
96            RTLD_LAZY | RTLD_GLOBAL
97 #endif
98            );
99     libldap = dlopen("libldap.so", RTLD_LAZY);
100   }
101 #endif
102 }
103
104 static void DynaClose(void)
105 {
106 #if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL)
107   if (libldap) {
108     dlclose(libldap);
109   }
110   if (liblber) {
111     dlclose(liblber);
112   }
113 #endif
114 }
115
116 static void * DynaGetFunction(char *name)
117 {
118   void *func = NULL;
119
120 #if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL)
121   if (libldap) {
122     func = dlsym(libldap, name);
123   }
124 #endif
125   
126   return func;
127 }
128
129 static int WriteProc(void *param, char *text, int len)
130 {
131   struct UrlData *data = (struct UrlData *)param;
132
133   data->fwrite(text, 1, strlen(text), data->out);
134   return 0;
135 }
136
137 CURLcode ldap_done(struct connectdata *conn)
138 {
139   return CURLE_OK;
140 }
141
142 /***********************************************************************
143  */
144 CURLcode ldap(struct connectdata *conn)
145 {
146   CURLcode status = CURLE_OK;
147   int rc;
148   void *(*ldap_open)(char *, int);
149   int (*ldap_simple_bind_s)(void *, char *, char *);
150   int (*ldap_unbind_s)(void *);
151   int (*ldap_url_search_s)(void *, char *, int, void **);
152   void *(*ldap_first_entry)(void *, void *);
153   void *(*ldap_next_entry)(void *, void *);
154   char *(*ldap_err2string)(int);
155   int (*ldap_entry2text)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long);
156   int (*ldap_entry2html)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long, char *, char *);
157   void *server;
158   void *result;
159   void *entryIterator;
160
161   int ldaptext;
162   struct UrlData *data=conn->data;
163   
164   infof(data, "LDAP: %s %s\n", data->url);
165
166   DynaOpen();
167   if (libldap == NULL) {
168     failf(data, "The needed LDAP library/libraries couldn't be opened");
169     return CURLE_LIBRARY_NOT_FOUND;
170   }
171
172   ldaptext = data->bits.ftp_ascii; /* This is a dirty hack */
173   
174   /* The types are needed because ANSI C distinguishes between
175    * pointer-to-object (data) and pointer-to-function.
176    */
177   DYNA_GET_FUNCTION(void *(*)(char *, int), ldap_open);
178   DYNA_GET_FUNCTION(int (*)(void *, char *, char *), ldap_simple_bind_s);
179   DYNA_GET_FUNCTION(int (*)(void *), ldap_unbind_s);
180   DYNA_GET_FUNCTION(int (*)(void *, char *, int, void **), ldap_url_search_s);
181   DYNA_GET_FUNCTION(void *(*)(void *, void *), ldap_first_entry);
182   DYNA_GET_FUNCTION(void *(*)(void *, void *), ldap_next_entry);
183   DYNA_GET_FUNCTION(char *(*)(int), ldap_err2string);
184   DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long), ldap_entry2text);
185   DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long, char *, char *), ldap_entry2html);
186   
187   server = ldap_open(data->hostname, data->port);
188   if (server == NULL) {
189     failf(data, "LDAP: Cannot connect to %s:%d",
190           data->hostname, data->port);
191     status = CURLE_COULDNT_CONNECT;
192   } else {
193     rc = ldap_simple_bind_s(server, data->user, data->passwd);
194     if (rc != 0) {
195       failf(data, "LDAP: %s", ldap_err2string(rc));
196       status = CURLE_LDAP_CANNOT_BIND;
197     } else {
198       rc = ldap_url_search_s(server, data->url, 0, &result);
199       if (rc != 0) {
200         failf(data, "LDAP: %s", ldap_err2string(rc));
201         status = CURLE_LDAP_SEARCH_FAILED;
202       } else {
203         for (entryIterator = ldap_first_entry(server, result);
204              entryIterator;
205              entryIterator = ldap_next_entry(server, entryIterator))
206           {
207             if (ldaptext) {
208               rc = ldap_entry2text(server, NULL, entryIterator, NULL,
209                                    NULL, NULL, WriteProc, data,
210                                    "", 0, 0);
211               if (rc != 0) {
212                 failf(data, "LDAP: %s", ldap_err2string(rc));
213                 status = CURLE_LDAP_SEARCH_FAILED;
214               }
215             } else {
216               rc = ldap_entry2html(server, NULL, entryIterator, NULL,
217                                    NULL, NULL, WriteProc, data,
218                                    "", 0, 0, NULL, NULL);
219               if (rc != 0) {
220                 failf(data, "LDAP: %s", ldap_err2string(rc));
221                 status = CURLE_LDAP_SEARCH_FAILED;
222               }
223             }
224           }
225       }
226       ldap_unbind_s(server);
227     }
228   }
229   DynaClose();
230   
231   return status;
232 }