xref: /aosp_15_r20/external/curl/lib/openldap.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker  *                      _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker  *  Project         ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker  *                 / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker  *                | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker  *                 \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker  *
8*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Howard Chu, <[email protected]>
10*6236dae4SAndroid Build Coastguard Worker  *
11*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
12*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
13*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.se/docs/copyright.html.
14*6236dae4SAndroid Build Coastguard Worker  *
15*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
16*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
17*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
18*6236dae4SAndroid Build Coastguard Worker  *
19*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
21*6236dae4SAndroid Build Coastguard Worker  *
22*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
23*6236dae4SAndroid Build Coastguard Worker  *
24*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
25*6236dae4SAndroid Build Coastguard Worker 
26*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
27*6236dae4SAndroid Build Coastguard Worker 
28*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP)
29*6236dae4SAndroid Build Coastguard Worker 
30*6236dae4SAndroid Build Coastguard Worker /*
31*6236dae4SAndroid Build Coastguard Worker  * Notice that USE_OPENLDAP is only a source code selection switch. When
32*6236dae4SAndroid Build Coastguard Worker  * libcurl is built with USE_OPENLDAP defined the libcurl source code that
33*6236dae4SAndroid Build Coastguard Worker  * gets compiled is the code from openldap.c, otherwise the code that gets
34*6236dae4SAndroid Build Coastguard Worker  * compiled is the code from ldap.c.
35*6236dae4SAndroid Build Coastguard Worker  *
36*6236dae4SAndroid Build Coastguard Worker  * When USE_OPENLDAP is defined a recent version of the OpenLDAP library
37*6236dae4SAndroid Build Coastguard Worker  * might be required for compilation and runtime. In order to use ancient
38*6236dae4SAndroid Build Coastguard Worker  * OpenLDAP library versions, USE_OPENLDAP shall not be defined.
39*6236dae4SAndroid Build Coastguard Worker  */
40*6236dae4SAndroid Build Coastguard Worker 
41*6236dae4SAndroid Build Coastguard Worker #include <ldap.h>
42*6236dae4SAndroid Build Coastguard Worker 
43*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
44*6236dae4SAndroid Build Coastguard Worker #include <curl/curl.h>
45*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
46*6236dae4SAndroid Build Coastguard Worker #include "vtls/vtls.h"
47*6236dae4SAndroid Build Coastguard Worker #include "transfer.h"
48*6236dae4SAndroid Build Coastguard Worker #include "curl_ldap.h"
49*6236dae4SAndroid Build Coastguard Worker #include "curl_base64.h"
50*6236dae4SAndroid Build Coastguard Worker #include "cfilters.h"
51*6236dae4SAndroid Build Coastguard Worker #include "connect.h"
52*6236dae4SAndroid Build Coastguard Worker #include "curl_sasl.h"
53*6236dae4SAndroid Build Coastguard Worker #include "strcase.h"
54*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
55*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
56*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
57*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
58*6236dae4SAndroid Build Coastguard Worker 
59*6236dae4SAndroid Build Coastguard Worker /*
60*6236dae4SAndroid Build Coastguard Worker  * Uncommenting this will enable the built-in debug logging of the openldap
61*6236dae4SAndroid Build Coastguard Worker  * library. The debug log level can be set using the CURL_OPENLDAP_TRACE
62*6236dae4SAndroid Build Coastguard Worker  * environment variable. The debug output is written to stderr.
63*6236dae4SAndroid Build Coastguard Worker  *
64*6236dae4SAndroid Build Coastguard Worker  * The library supports the following debug flags:
65*6236dae4SAndroid Build Coastguard Worker  * LDAP_DEBUG_NONE         0x0000
66*6236dae4SAndroid Build Coastguard Worker  * LDAP_DEBUG_TRACE        0x0001
67*6236dae4SAndroid Build Coastguard Worker  * LDAP_DEBUG_CONSTRUCT    0x0002
68*6236dae4SAndroid Build Coastguard Worker  * LDAP_DEBUG_DESTROY      0x0004
69*6236dae4SAndroid Build Coastguard Worker  * LDAP_DEBUG_PARAMETER    0x0008
70*6236dae4SAndroid Build Coastguard Worker  * LDAP_DEBUG_ANY          0xffff
71*6236dae4SAndroid Build Coastguard Worker  *
72*6236dae4SAndroid Build Coastguard Worker  * For example, use CURL_OPENLDAP_TRACE=0 for no debug,
73*6236dae4SAndroid Build Coastguard Worker  * CURL_OPENLDAP_TRACE=2 for LDAP_DEBUG_CONSTRUCT messages only,
74*6236dae4SAndroid Build Coastguard Worker  * CURL_OPENLDAP_TRACE=65535 for all debug message levels.
75*6236dae4SAndroid Build Coastguard Worker  */
76*6236dae4SAndroid Build Coastguard Worker /* #define CURL_OPENLDAP_DEBUG */
77*6236dae4SAndroid Build Coastguard Worker 
78*6236dae4SAndroid Build Coastguard Worker /* Machine states. */
79*6236dae4SAndroid Build Coastguard Worker typedef enum {
80*6236dae4SAndroid Build Coastguard Worker   OLDAP_STOP,           /* Do nothing state, stops the state machine */
81*6236dae4SAndroid Build Coastguard Worker   OLDAP_SSL,            /* Performing SSL handshake. */
82*6236dae4SAndroid Build Coastguard Worker   OLDAP_STARTTLS,       /* STARTTLS request sent. */
83*6236dae4SAndroid Build Coastguard Worker   OLDAP_TLS,            /* Performing TLS handshake. */
84*6236dae4SAndroid Build Coastguard Worker   OLDAP_MECHS,          /* Get SASL authentication mechanisms. */
85*6236dae4SAndroid Build Coastguard Worker   OLDAP_SASL,           /* SASL binding reply. */
86*6236dae4SAndroid Build Coastguard Worker   OLDAP_BIND,           /* Simple bind reply. */
87*6236dae4SAndroid Build Coastguard Worker   OLDAP_BINDV2,         /* Simple bind reply in protocol version 2. */
88*6236dae4SAndroid Build Coastguard Worker   OLDAP_LAST            /* Never used */
89*6236dae4SAndroid Build Coastguard Worker } ldapstate;
90*6236dae4SAndroid Build Coastguard Worker 
91*6236dae4SAndroid Build Coastguard Worker #ifndef _LDAP_PVT_H
92*6236dae4SAndroid Build Coastguard Worker extern int ldap_pvt_url_scheme2proto(const char *);
93*6236dae4SAndroid Build Coastguard Worker extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url,
94*6236dae4SAndroid Build Coastguard Worker                         LDAP **ld);
95*6236dae4SAndroid Build Coastguard Worker #endif
96*6236dae4SAndroid Build Coastguard Worker 
97*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_setup_connection(struct Curl_easy *data,
98*6236dae4SAndroid Build Coastguard Worker                                        struct connectdata *conn);
99*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_do(struct Curl_easy *data, bool *done);
100*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_done(struct Curl_easy *data, CURLcode, bool);
101*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_connect(struct Curl_easy *data, bool *done);
102*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_connecting(struct Curl_easy *data, bool *done);
103*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_disconnect(struct Curl_easy *data,
104*6236dae4SAndroid Build Coastguard Worker                                  struct connectdata *conn, bool dead);
105*6236dae4SAndroid Build Coastguard Worker 
106*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_perform_auth(struct Curl_easy *data, const char *mech,
107*6236dae4SAndroid Build Coastguard Worker                                    const struct bufref *initresp);
108*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_continue_auth(struct Curl_easy *data, const char *mech,
109*6236dae4SAndroid Build Coastguard Worker                                     const struct bufref *resp);
110*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_cancel_auth(struct Curl_easy *data, const char *mech);
111*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_get_message(struct Curl_easy *data, struct bufref *out);
112*6236dae4SAndroid Build Coastguard Worker 
113*6236dae4SAndroid Build Coastguard Worker static Curl_recv oldap_recv;
114*6236dae4SAndroid Build Coastguard Worker 
115*6236dae4SAndroid Build Coastguard Worker /*
116*6236dae4SAndroid Build Coastguard Worker  * LDAP protocol handler.
117*6236dae4SAndroid Build Coastguard Worker  */
118*6236dae4SAndroid Build Coastguard Worker 
119*6236dae4SAndroid Build Coastguard Worker const struct Curl_handler Curl_handler_ldap = {
120*6236dae4SAndroid Build Coastguard Worker   "ldap",                               /* scheme */
121*6236dae4SAndroid Build Coastguard Worker   oldap_setup_connection,               /* setup_connection */
122*6236dae4SAndroid Build Coastguard Worker   oldap_do,                             /* do_it */
123*6236dae4SAndroid Build Coastguard Worker   oldap_done,                           /* done */
124*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* do_more */
125*6236dae4SAndroid Build Coastguard Worker   oldap_connect,                        /* connect_it */
126*6236dae4SAndroid Build Coastguard Worker   oldap_connecting,                     /* connecting */
127*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* doing */
128*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* proto_getsock */
129*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* doing_getsock */
130*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* domore_getsock */
131*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* perform_getsock */
132*6236dae4SAndroid Build Coastguard Worker   oldap_disconnect,                     /* disconnect */
133*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* write_resp */
134*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* write_resp_hd */
135*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* connection_check */
136*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* attach connection */
137*6236dae4SAndroid Build Coastguard Worker   PORT_LDAP,                            /* defport */
138*6236dae4SAndroid Build Coastguard Worker   CURLPROTO_LDAP,                       /* protocol */
139*6236dae4SAndroid Build Coastguard Worker   CURLPROTO_LDAP,                       /* family */
140*6236dae4SAndroid Build Coastguard Worker   PROTOPT_NONE                          /* flags */
141*6236dae4SAndroid Build Coastguard Worker };
142*6236dae4SAndroid Build Coastguard Worker 
143*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SSL
144*6236dae4SAndroid Build Coastguard Worker /*
145*6236dae4SAndroid Build Coastguard Worker  * LDAPS protocol handler.
146*6236dae4SAndroid Build Coastguard Worker  */
147*6236dae4SAndroid Build Coastguard Worker 
148*6236dae4SAndroid Build Coastguard Worker const struct Curl_handler Curl_handler_ldaps = {
149*6236dae4SAndroid Build Coastguard Worker   "ldaps",                              /* scheme */
150*6236dae4SAndroid Build Coastguard Worker   oldap_setup_connection,               /* setup_connection */
151*6236dae4SAndroid Build Coastguard Worker   oldap_do,                             /* do_it */
152*6236dae4SAndroid Build Coastguard Worker   oldap_done,                           /* done */
153*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* do_more */
154*6236dae4SAndroid Build Coastguard Worker   oldap_connect,                        /* connect_it */
155*6236dae4SAndroid Build Coastguard Worker   oldap_connecting,                     /* connecting */
156*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* doing */
157*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* proto_getsock */
158*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* doing_getsock */
159*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* domore_getsock */
160*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* perform_getsock */
161*6236dae4SAndroid Build Coastguard Worker   oldap_disconnect,                     /* disconnect */
162*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* write_resp */
163*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* write_resp_hd */
164*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* connection_check */
165*6236dae4SAndroid Build Coastguard Worker   ZERO_NULL,                            /* attach connection */
166*6236dae4SAndroid Build Coastguard Worker   PORT_LDAPS,                           /* defport */
167*6236dae4SAndroid Build Coastguard Worker   CURLPROTO_LDAPS,                      /* protocol */
168*6236dae4SAndroid Build Coastguard Worker   CURLPROTO_LDAP,                       /* family */
169*6236dae4SAndroid Build Coastguard Worker   PROTOPT_SSL                           /* flags */
170*6236dae4SAndroid Build Coastguard Worker };
171*6236dae4SAndroid Build Coastguard Worker #endif
172*6236dae4SAndroid Build Coastguard Worker 
173*6236dae4SAndroid Build Coastguard Worker /* SASL parameters for the ldap protocol */
174*6236dae4SAndroid Build Coastguard Worker static const struct SASLproto saslldap = {
175*6236dae4SAndroid Build Coastguard Worker   "ldap",                     /* The service name */
176*6236dae4SAndroid Build Coastguard Worker   oldap_perform_auth,         /* Send authentication command */
177*6236dae4SAndroid Build Coastguard Worker   oldap_continue_auth,        /* Send authentication continuation */
178*6236dae4SAndroid Build Coastguard Worker   oldap_cancel_auth,          /* Send authentication cancellation */
179*6236dae4SAndroid Build Coastguard Worker   oldap_get_message,          /* Get SASL response message */
180*6236dae4SAndroid Build Coastguard Worker   0,                          /* Maximum initial response length (no max) */
181*6236dae4SAndroid Build Coastguard Worker   LDAP_SASL_BIND_IN_PROGRESS, /* Code received when continuation is expected */
182*6236dae4SAndroid Build Coastguard Worker   LDAP_SUCCESS,               /* Code to receive upon authentication success */
183*6236dae4SAndroid Build Coastguard Worker   SASL_AUTH_NONE,             /* Default mechanisms */
184*6236dae4SAndroid Build Coastguard Worker   0                           /* Configuration flags */
185*6236dae4SAndroid Build Coastguard Worker };
186*6236dae4SAndroid Build Coastguard Worker 
187*6236dae4SAndroid Build Coastguard Worker struct ldapconninfo {
188*6236dae4SAndroid Build Coastguard Worker   struct SASL sasl;          /* SASL-related parameters */
189*6236dae4SAndroid Build Coastguard Worker   LDAP *ld;                  /* Openldap connection handle. */
190*6236dae4SAndroid Build Coastguard Worker   Curl_recv *recv;           /* For stacking SSL handler */
191*6236dae4SAndroid Build Coastguard Worker   Curl_send *send;
192*6236dae4SAndroid Build Coastguard Worker   struct berval *servercred; /* SASL data from server. */
193*6236dae4SAndroid Build Coastguard Worker   ldapstate state;           /* Current machine state. */
194*6236dae4SAndroid Build Coastguard Worker   int proto;                 /* LDAP_PROTO_TCP/LDAP_PROTO_UDP/LDAP_PROTO_IPC */
195*6236dae4SAndroid Build Coastguard Worker   int msgid;                 /* Current message id. */
196*6236dae4SAndroid Build Coastguard Worker };
197*6236dae4SAndroid Build Coastguard Worker 
198*6236dae4SAndroid Build Coastguard Worker struct ldapreqinfo {
199*6236dae4SAndroid Build Coastguard Worker   int msgid;
200*6236dae4SAndroid Build Coastguard Worker   int nument;
201*6236dae4SAndroid Build Coastguard Worker };
202*6236dae4SAndroid Build Coastguard Worker 
203*6236dae4SAndroid Build Coastguard Worker /*
204*6236dae4SAndroid Build Coastguard Worker  * oldap_state()
205*6236dae4SAndroid Build Coastguard Worker  *
206*6236dae4SAndroid Build Coastguard Worker  * This is the ONLY way to change LDAP state!
207*6236dae4SAndroid Build Coastguard Worker  */
oldap_state(struct Curl_easy * data,ldapstate newstate)208*6236dae4SAndroid Build Coastguard Worker static void oldap_state(struct Curl_easy *data, ldapstate newstate)
209*6236dae4SAndroid Build Coastguard Worker {
210*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *ldapc = data->conn->proto.ldapc;
211*6236dae4SAndroid Build Coastguard Worker 
212*6236dae4SAndroid Build Coastguard Worker #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
213*6236dae4SAndroid Build Coastguard Worker   /* for debug purposes */
214*6236dae4SAndroid Build Coastguard Worker   static const char * const names[] = {
215*6236dae4SAndroid Build Coastguard Worker     "STOP",
216*6236dae4SAndroid Build Coastguard Worker     "SSL",
217*6236dae4SAndroid Build Coastguard Worker     "STARTTLS",
218*6236dae4SAndroid Build Coastguard Worker     "TLS",
219*6236dae4SAndroid Build Coastguard Worker     "MECHS",
220*6236dae4SAndroid Build Coastguard Worker     "SASL",
221*6236dae4SAndroid Build Coastguard Worker     "BIND",
222*6236dae4SAndroid Build Coastguard Worker     "BINDV2",
223*6236dae4SAndroid Build Coastguard Worker     /* LAST */
224*6236dae4SAndroid Build Coastguard Worker   };
225*6236dae4SAndroid Build Coastguard Worker 
226*6236dae4SAndroid Build Coastguard Worker   if(ldapc->state != newstate)
227*6236dae4SAndroid Build Coastguard Worker     infof(data, "LDAP %p state change from %s to %s",
228*6236dae4SAndroid Build Coastguard Worker           (void *)ldapc, names[ldapc->state], names[newstate]);
229*6236dae4SAndroid Build Coastguard Worker #endif
230*6236dae4SAndroid Build Coastguard Worker 
231*6236dae4SAndroid Build Coastguard Worker   ldapc->state = newstate;
232*6236dae4SAndroid Build Coastguard Worker }
233*6236dae4SAndroid Build Coastguard Worker 
234*6236dae4SAndroid Build Coastguard Worker /* Map some particular LDAP error codes to CURLcode values. */
oldap_map_error(int rc,CURLcode result)235*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_map_error(int rc, CURLcode result)
236*6236dae4SAndroid Build Coastguard Worker {
237*6236dae4SAndroid Build Coastguard Worker   switch(rc) {
238*6236dae4SAndroid Build Coastguard Worker   case LDAP_NO_MEMORY:
239*6236dae4SAndroid Build Coastguard Worker     return CURLE_OUT_OF_MEMORY;
240*6236dae4SAndroid Build Coastguard Worker   case LDAP_INVALID_CREDENTIALS:
241*6236dae4SAndroid Build Coastguard Worker     return CURLE_LOGIN_DENIED;
242*6236dae4SAndroid Build Coastguard Worker   case LDAP_PROTOCOL_ERROR:
243*6236dae4SAndroid Build Coastguard Worker     return CURLE_UNSUPPORTED_PROTOCOL;
244*6236dae4SAndroid Build Coastguard Worker   case LDAP_INSUFFICIENT_ACCESS:
245*6236dae4SAndroid Build Coastguard Worker     return CURLE_REMOTE_ACCESS_DENIED;
246*6236dae4SAndroid Build Coastguard Worker   }
247*6236dae4SAndroid Build Coastguard Worker   return result;
248*6236dae4SAndroid Build Coastguard Worker }
249*6236dae4SAndroid Build Coastguard Worker 
oldap_url_parse(struct Curl_easy * data,LDAPURLDesc ** ludp)250*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_url_parse(struct Curl_easy *data, LDAPURLDesc **ludp)
251*6236dae4SAndroid Build Coastguard Worker {
252*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
253*6236dae4SAndroid Build Coastguard Worker   int rc = LDAP_URL_ERR_BADURL;
254*6236dae4SAndroid Build Coastguard Worker   static const char * const url_errs[] = {
255*6236dae4SAndroid Build Coastguard Worker     "success",
256*6236dae4SAndroid Build Coastguard Worker     "out of memory",
257*6236dae4SAndroid Build Coastguard Worker     "bad parameter",
258*6236dae4SAndroid Build Coastguard Worker     "unrecognized scheme",
259*6236dae4SAndroid Build Coastguard Worker     "unbalanced delimiter",
260*6236dae4SAndroid Build Coastguard Worker     "bad URL",
261*6236dae4SAndroid Build Coastguard Worker     "bad host or port",
262*6236dae4SAndroid Build Coastguard Worker     "bad or missing attributes",
263*6236dae4SAndroid Build Coastguard Worker     "bad or missing scope",
264*6236dae4SAndroid Build Coastguard Worker     "bad or missing filter",
265*6236dae4SAndroid Build Coastguard Worker     "bad or missing extensions"
266*6236dae4SAndroid Build Coastguard Worker   };
267*6236dae4SAndroid Build Coastguard Worker 
268*6236dae4SAndroid Build Coastguard Worker   *ludp = NULL;
269*6236dae4SAndroid Build Coastguard Worker   if(!data->state.up.user && !data->state.up.password &&
270*6236dae4SAndroid Build Coastguard Worker      !data->state.up.options)
271*6236dae4SAndroid Build Coastguard Worker     rc = ldap_url_parse(data->state.url, ludp);
272*6236dae4SAndroid Build Coastguard Worker   if(rc != LDAP_URL_SUCCESS) {
273*6236dae4SAndroid Build Coastguard Worker     const char *msg = "url parsing problem";
274*6236dae4SAndroid Build Coastguard Worker 
275*6236dae4SAndroid Build Coastguard Worker     result = rc == LDAP_URL_ERR_MEM ? CURLE_OUT_OF_MEMORY :
276*6236dae4SAndroid Build Coastguard Worker       CURLE_URL_MALFORMAT;
277*6236dae4SAndroid Build Coastguard Worker     rc -= LDAP_URL_SUCCESS;
278*6236dae4SAndroid Build Coastguard Worker     if((size_t) rc < sizeof(url_errs) / sizeof(url_errs[0]))
279*6236dae4SAndroid Build Coastguard Worker       msg = url_errs[rc];
280*6236dae4SAndroid Build Coastguard Worker     failf(data, "LDAP local: %s", msg);
281*6236dae4SAndroid Build Coastguard Worker   }
282*6236dae4SAndroid Build Coastguard Worker   return result;
283*6236dae4SAndroid Build Coastguard Worker }
284*6236dae4SAndroid Build Coastguard Worker 
285*6236dae4SAndroid Build Coastguard Worker /* Parse the login options. */
oldap_parse_login_options(struct connectdata * conn)286*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_parse_login_options(struct connectdata *conn)
287*6236dae4SAndroid Build Coastguard Worker {
288*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
289*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = conn->proto.ldapc;
290*6236dae4SAndroid Build Coastguard Worker   const char *ptr = conn->options;
291*6236dae4SAndroid Build Coastguard Worker 
292*6236dae4SAndroid Build Coastguard Worker   while(!result && ptr && *ptr) {
293*6236dae4SAndroid Build Coastguard Worker     const char *key = ptr;
294*6236dae4SAndroid Build Coastguard Worker     const char *value;
295*6236dae4SAndroid Build Coastguard Worker 
296*6236dae4SAndroid Build Coastguard Worker     while(*ptr && *ptr != '=')
297*6236dae4SAndroid Build Coastguard Worker       ptr++;
298*6236dae4SAndroid Build Coastguard Worker 
299*6236dae4SAndroid Build Coastguard Worker     value = ptr + 1;
300*6236dae4SAndroid Build Coastguard Worker 
301*6236dae4SAndroid Build Coastguard Worker     while(*ptr && *ptr != ';')
302*6236dae4SAndroid Build Coastguard Worker       ptr++;
303*6236dae4SAndroid Build Coastguard Worker 
304*6236dae4SAndroid Build Coastguard Worker     if(checkprefix("AUTH=", key))
305*6236dae4SAndroid Build Coastguard Worker       result = Curl_sasl_parse_url_auth_option(&li->sasl, value, ptr - value);
306*6236dae4SAndroid Build Coastguard Worker     else
307*6236dae4SAndroid Build Coastguard Worker       result = CURLE_SETOPT_OPTION_SYNTAX;
308*6236dae4SAndroid Build Coastguard Worker 
309*6236dae4SAndroid Build Coastguard Worker     if(*ptr == ';')
310*6236dae4SAndroid Build Coastguard Worker       ptr++;
311*6236dae4SAndroid Build Coastguard Worker   }
312*6236dae4SAndroid Build Coastguard Worker 
313*6236dae4SAndroid Build Coastguard Worker   return result == CURLE_URL_MALFORMAT ? CURLE_SETOPT_OPTION_SYNTAX : result;
314*6236dae4SAndroid Build Coastguard Worker }
315*6236dae4SAndroid Build Coastguard Worker 
oldap_setup_connection(struct Curl_easy * data,struct connectdata * conn)316*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_setup_connection(struct Curl_easy *data,
317*6236dae4SAndroid Build Coastguard Worker                                        struct connectdata *conn)
318*6236dae4SAndroid Build Coastguard Worker {
319*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
320*6236dae4SAndroid Build Coastguard Worker   LDAPURLDesc *lud;
321*6236dae4SAndroid Build Coastguard Worker   (void)conn;
322*6236dae4SAndroid Build Coastguard Worker 
323*6236dae4SAndroid Build Coastguard Worker   /* Early URL syntax check. */
324*6236dae4SAndroid Build Coastguard Worker   result = oldap_url_parse(data, &lud);
325*6236dae4SAndroid Build Coastguard Worker   ldap_free_urldesc(lud);
326*6236dae4SAndroid Build Coastguard Worker 
327*6236dae4SAndroid Build Coastguard Worker   return result;
328*6236dae4SAndroid Build Coastguard Worker }
329*6236dae4SAndroid Build Coastguard Worker 
330*6236dae4SAndroid Build Coastguard Worker /*
331*6236dae4SAndroid Build Coastguard Worker  * Get the SASL authentication challenge from the server credential buffer.
332*6236dae4SAndroid Build Coastguard Worker  */
oldap_get_message(struct Curl_easy * data,struct bufref * out)333*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_get_message(struct Curl_easy *data, struct bufref *out)
334*6236dae4SAndroid Build Coastguard Worker {
335*6236dae4SAndroid Build Coastguard Worker   struct berval *servercred = data->conn->proto.ldapc->servercred;
336*6236dae4SAndroid Build Coastguard Worker 
337*6236dae4SAndroid Build Coastguard Worker   if(!servercred || !servercred->bv_val)
338*6236dae4SAndroid Build Coastguard Worker     return CURLE_WEIRD_SERVER_REPLY;
339*6236dae4SAndroid Build Coastguard Worker   Curl_bufref_set(out, servercred->bv_val, servercred->bv_len, NULL);
340*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
341*6236dae4SAndroid Build Coastguard Worker }
342*6236dae4SAndroid Build Coastguard Worker 
343*6236dae4SAndroid Build Coastguard Worker /*
344*6236dae4SAndroid Build Coastguard Worker  * Sends an initial SASL bind request to the server.
345*6236dae4SAndroid Build Coastguard Worker  */
oldap_perform_auth(struct Curl_easy * data,const char * mech,const struct bufref * initresp)346*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_perform_auth(struct Curl_easy *data, const char *mech,
347*6236dae4SAndroid Build Coastguard Worker                                    const struct bufref *initresp)
348*6236dae4SAndroid Build Coastguard Worker {
349*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
350*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = conn->proto.ldapc;
351*6236dae4SAndroid Build Coastguard Worker   struct berval cred;
352*6236dae4SAndroid Build Coastguard Worker   struct berval *pcred = &cred;
353*6236dae4SAndroid Build Coastguard Worker   int rc;
354*6236dae4SAndroid Build Coastguard Worker 
355*6236dae4SAndroid Build Coastguard Worker   cred.bv_val = (char *) Curl_bufref_ptr(initresp);
356*6236dae4SAndroid Build Coastguard Worker   cred.bv_len = Curl_bufref_len(initresp);
357*6236dae4SAndroid Build Coastguard Worker   if(!cred.bv_val)
358*6236dae4SAndroid Build Coastguard Worker     pcred = NULL;
359*6236dae4SAndroid Build Coastguard Worker   rc = ldap_sasl_bind(li->ld, NULL, mech, pcred, NULL, NULL, &li->msgid);
360*6236dae4SAndroid Build Coastguard Worker   if(rc != LDAP_SUCCESS)
361*6236dae4SAndroid Build Coastguard Worker     return oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND);
362*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
363*6236dae4SAndroid Build Coastguard Worker }
364*6236dae4SAndroid Build Coastguard Worker 
365*6236dae4SAndroid Build Coastguard Worker /*
366*6236dae4SAndroid Build Coastguard Worker  * Sends SASL continuation.
367*6236dae4SAndroid Build Coastguard Worker  */
oldap_continue_auth(struct Curl_easy * data,const char * mech,const struct bufref * resp)368*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_continue_auth(struct Curl_easy *data, const char *mech,
369*6236dae4SAndroid Build Coastguard Worker                                     const struct bufref *resp)
370*6236dae4SAndroid Build Coastguard Worker {
371*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
372*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = conn->proto.ldapc;
373*6236dae4SAndroid Build Coastguard Worker   struct berval cred;
374*6236dae4SAndroid Build Coastguard Worker   struct berval *pcred = &cred;
375*6236dae4SAndroid Build Coastguard Worker   int rc;
376*6236dae4SAndroid Build Coastguard Worker 
377*6236dae4SAndroid Build Coastguard Worker   cred.bv_val = (char *) Curl_bufref_ptr(resp);
378*6236dae4SAndroid Build Coastguard Worker   cred.bv_len = Curl_bufref_len(resp);
379*6236dae4SAndroid Build Coastguard Worker   if(!cred.bv_val)
380*6236dae4SAndroid Build Coastguard Worker     pcred = NULL;
381*6236dae4SAndroid Build Coastguard Worker   rc = ldap_sasl_bind(li->ld, NULL, mech, pcred, NULL, NULL, &li->msgid);
382*6236dae4SAndroid Build Coastguard Worker   if(rc != LDAP_SUCCESS)
383*6236dae4SAndroid Build Coastguard Worker     return oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND);
384*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
385*6236dae4SAndroid Build Coastguard Worker }
386*6236dae4SAndroid Build Coastguard Worker 
387*6236dae4SAndroid Build Coastguard Worker /*
388*6236dae4SAndroid Build Coastguard Worker  * Sends SASL bind cancellation.
389*6236dae4SAndroid Build Coastguard Worker  */
oldap_cancel_auth(struct Curl_easy * data,const char * mech)390*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_cancel_auth(struct Curl_easy *data, const char *mech)
391*6236dae4SAndroid Build Coastguard Worker {
392*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = data->conn->proto.ldapc;
393*6236dae4SAndroid Build Coastguard Worker   int rc = ldap_sasl_bind(li->ld, NULL, LDAP_SASL_NULL, NULL, NULL, NULL,
394*6236dae4SAndroid Build Coastguard Worker                           &li->msgid);
395*6236dae4SAndroid Build Coastguard Worker 
396*6236dae4SAndroid Build Coastguard Worker   (void)mech;
397*6236dae4SAndroid Build Coastguard Worker   if(rc != LDAP_SUCCESS)
398*6236dae4SAndroid Build Coastguard Worker     return oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND);
399*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
400*6236dae4SAndroid Build Coastguard Worker }
401*6236dae4SAndroid Build Coastguard Worker 
402*6236dae4SAndroid Build Coastguard Worker /* Starts LDAP simple bind. */
oldap_perform_bind(struct Curl_easy * data,ldapstate newstate)403*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_perform_bind(struct Curl_easy *data, ldapstate newstate)
404*6236dae4SAndroid Build Coastguard Worker {
405*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
406*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = conn->proto.ldapc;
407*6236dae4SAndroid Build Coastguard Worker   char *binddn = NULL;
408*6236dae4SAndroid Build Coastguard Worker   struct berval passwd;
409*6236dae4SAndroid Build Coastguard Worker   int rc;
410*6236dae4SAndroid Build Coastguard Worker 
411*6236dae4SAndroid Build Coastguard Worker   passwd.bv_val = NULL;
412*6236dae4SAndroid Build Coastguard Worker   passwd.bv_len = 0;
413*6236dae4SAndroid Build Coastguard Worker 
414*6236dae4SAndroid Build Coastguard Worker   if(data->state.aptr.user) {
415*6236dae4SAndroid Build Coastguard Worker     binddn = conn->user;
416*6236dae4SAndroid Build Coastguard Worker     passwd.bv_val = conn->passwd;
417*6236dae4SAndroid Build Coastguard Worker     passwd.bv_len = strlen(passwd.bv_val);
418*6236dae4SAndroid Build Coastguard Worker   }
419*6236dae4SAndroid Build Coastguard Worker 
420*6236dae4SAndroid Build Coastguard Worker   rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd,
421*6236dae4SAndroid Build Coastguard Worker                       NULL, NULL, &li->msgid);
422*6236dae4SAndroid Build Coastguard Worker   if(rc != LDAP_SUCCESS)
423*6236dae4SAndroid Build Coastguard Worker     return oldap_map_error(rc,
424*6236dae4SAndroid Build Coastguard Worker                            data->state.aptr.user ?
425*6236dae4SAndroid Build Coastguard Worker                            CURLE_LOGIN_DENIED : CURLE_LDAP_CANNOT_BIND);
426*6236dae4SAndroid Build Coastguard Worker   oldap_state(data, newstate);
427*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
428*6236dae4SAndroid Build Coastguard Worker }
429*6236dae4SAndroid Build Coastguard Worker 
430*6236dae4SAndroid Build Coastguard Worker /* Query the supported SASL authentication mechanisms. */
oldap_perform_mechs(struct Curl_easy * data)431*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_perform_mechs(struct Curl_easy *data)
432*6236dae4SAndroid Build Coastguard Worker {
433*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = data->conn->proto.ldapc;
434*6236dae4SAndroid Build Coastguard Worker   int rc;
435*6236dae4SAndroid Build Coastguard Worker   static const char * const supportedSASLMechanisms[] = {
436*6236dae4SAndroid Build Coastguard Worker     "supportedSASLMechanisms",
437*6236dae4SAndroid Build Coastguard Worker     NULL
438*6236dae4SAndroid Build Coastguard Worker   };
439*6236dae4SAndroid Build Coastguard Worker 
440*6236dae4SAndroid Build Coastguard Worker   rc = ldap_search_ext(li->ld, "", LDAP_SCOPE_BASE, "(objectclass=*)",
441*6236dae4SAndroid Build Coastguard Worker                        (char **) supportedSASLMechanisms, 0,
442*6236dae4SAndroid Build Coastguard Worker                        NULL, NULL, NULL, 0, &li->msgid);
443*6236dae4SAndroid Build Coastguard Worker   if(rc != LDAP_SUCCESS)
444*6236dae4SAndroid Build Coastguard Worker     return oldap_map_error(rc, CURLE_LOGIN_DENIED);
445*6236dae4SAndroid Build Coastguard Worker   oldap_state(data, OLDAP_MECHS);
446*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
447*6236dae4SAndroid Build Coastguard Worker }
448*6236dae4SAndroid Build Coastguard Worker 
449*6236dae4SAndroid Build Coastguard Worker /* Starts SASL bind. */
oldap_perform_sasl(struct Curl_easy * data)450*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_perform_sasl(struct Curl_easy *data)
451*6236dae4SAndroid Build Coastguard Worker {
452*6236dae4SAndroid Build Coastguard Worker   saslprogress progress = SASL_IDLE;
453*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = data->conn->proto.ldapc;
454*6236dae4SAndroid Build Coastguard Worker   CURLcode result = Curl_sasl_start(&li->sasl, data, TRUE, &progress);
455*6236dae4SAndroid Build Coastguard Worker 
456*6236dae4SAndroid Build Coastguard Worker   oldap_state(data, OLDAP_SASL);
457*6236dae4SAndroid Build Coastguard Worker   if(!result && progress != SASL_INPROGRESS)
458*6236dae4SAndroid Build Coastguard Worker     result = CURLE_LOGIN_DENIED;
459*6236dae4SAndroid Build Coastguard Worker   return result;
460*6236dae4SAndroid Build Coastguard Worker }
461*6236dae4SAndroid Build Coastguard Worker 
462*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SSL
463*6236dae4SAndroid Build Coastguard Worker static Sockbuf_IO ldapsb_tls;
464*6236dae4SAndroid Build Coastguard Worker 
ssl_installed(struct connectdata * conn)465*6236dae4SAndroid Build Coastguard Worker static bool ssl_installed(struct connectdata *conn)
466*6236dae4SAndroid Build Coastguard Worker {
467*6236dae4SAndroid Build Coastguard Worker   return conn->proto.ldapc->recv != NULL;
468*6236dae4SAndroid Build Coastguard Worker }
469*6236dae4SAndroid Build Coastguard Worker 
oldap_ssl_connect(struct Curl_easy * data,ldapstate newstate)470*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_ssl_connect(struct Curl_easy *data, ldapstate newstate)
471*6236dae4SAndroid Build Coastguard Worker {
472*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
473*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = conn->proto.ldapc;
474*6236dae4SAndroid Build Coastguard Worker   bool ssldone = FALSE;
475*6236dae4SAndroid Build Coastguard Worker   CURLcode result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
476*6236dae4SAndroid Build Coastguard Worker   if(!result) {
477*6236dae4SAndroid Build Coastguard Worker     oldap_state(data, newstate);
478*6236dae4SAndroid Build Coastguard Worker 
479*6236dae4SAndroid Build Coastguard Worker     if(ssldone) {
480*6236dae4SAndroid Build Coastguard Worker       Sockbuf *sb;
481*6236dae4SAndroid Build Coastguard Worker 
482*6236dae4SAndroid Build Coastguard Worker       /* Install the libcurl SSL handlers into the sockbuf. */
483*6236dae4SAndroid Build Coastguard Worker       ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
484*6236dae4SAndroid Build Coastguard Worker       ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data);
485*6236dae4SAndroid Build Coastguard Worker       li->recv = conn->recv[FIRSTSOCKET];
486*6236dae4SAndroid Build Coastguard Worker       li->send = conn->send[FIRSTSOCKET];
487*6236dae4SAndroid Build Coastguard Worker     }
488*6236dae4SAndroid Build Coastguard Worker   }
489*6236dae4SAndroid Build Coastguard Worker 
490*6236dae4SAndroid Build Coastguard Worker   return result;
491*6236dae4SAndroid Build Coastguard Worker }
492*6236dae4SAndroid Build Coastguard Worker 
493*6236dae4SAndroid Build Coastguard Worker /* Send the STARTTLS request */
oldap_perform_starttls(struct Curl_easy * data)494*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_perform_starttls(struct Curl_easy *data)
495*6236dae4SAndroid Build Coastguard Worker {
496*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = data->conn->proto.ldapc;
497*6236dae4SAndroid Build Coastguard Worker   int rc = ldap_start_tls(li->ld, NULL, NULL, &li->msgid);
498*6236dae4SAndroid Build Coastguard Worker 
499*6236dae4SAndroid Build Coastguard Worker   if(rc != LDAP_SUCCESS)
500*6236dae4SAndroid Build Coastguard Worker     return oldap_map_error(rc, CURLE_USE_SSL_FAILED);
501*6236dae4SAndroid Build Coastguard Worker   oldap_state(data, OLDAP_STARTTLS);
502*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
503*6236dae4SAndroid Build Coastguard Worker }
504*6236dae4SAndroid Build Coastguard Worker #endif
505*6236dae4SAndroid Build Coastguard Worker 
oldap_connect(struct Curl_easy * data,bool * done)506*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
507*6236dae4SAndroid Build Coastguard Worker {
508*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
509*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li;
510*6236dae4SAndroid Build Coastguard Worker   static const int version = LDAP_VERSION3;
511*6236dae4SAndroid Build Coastguard Worker   int rc;
512*6236dae4SAndroid Build Coastguard Worker   char *hosturl;
513*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_OPENLDAP_DEBUG
514*6236dae4SAndroid Build Coastguard Worker   static int do_trace = -1;
515*6236dae4SAndroid Build Coastguard Worker #endif
516*6236dae4SAndroid Build Coastguard Worker 
517*6236dae4SAndroid Build Coastguard Worker   (void)done;
518*6236dae4SAndroid Build Coastguard Worker 
519*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(!conn->proto.ldapc);
520*6236dae4SAndroid Build Coastguard Worker   li = calloc(1, sizeof(struct ldapconninfo));
521*6236dae4SAndroid Build Coastguard Worker   if(!li)
522*6236dae4SAndroid Build Coastguard Worker     return CURLE_OUT_OF_MEMORY;
523*6236dae4SAndroid Build Coastguard Worker   else {
524*6236dae4SAndroid Build Coastguard Worker     CURLcode result;
525*6236dae4SAndroid Build Coastguard Worker     li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme);
526*6236dae4SAndroid Build Coastguard Worker     conn->proto.ldapc = li;
527*6236dae4SAndroid Build Coastguard Worker 
528*6236dae4SAndroid Build Coastguard Worker     /* Initialize the SASL storage */
529*6236dae4SAndroid Build Coastguard Worker     Curl_sasl_init(&li->sasl, data, &saslldap);
530*6236dae4SAndroid Build Coastguard Worker 
531*6236dae4SAndroid Build Coastguard Worker     /* Clear the TLS upgraded flag */
532*6236dae4SAndroid Build Coastguard Worker     conn->bits.tls_upgraded = FALSE;
533*6236dae4SAndroid Build Coastguard Worker 
534*6236dae4SAndroid Build Coastguard Worker     result = oldap_parse_login_options(conn);
535*6236dae4SAndroid Build Coastguard Worker     if(result)
536*6236dae4SAndroid Build Coastguard Worker       return result;
537*6236dae4SAndroid Build Coastguard Worker   }
538*6236dae4SAndroid Build Coastguard Worker 
539*6236dae4SAndroid Build Coastguard Worker   hosturl = aprintf("%s://%s%s%s:%d",
540*6236dae4SAndroid Build Coastguard Worker                     conn->handler->scheme,
541*6236dae4SAndroid Build Coastguard Worker                     conn->bits.ipv6_ip ? "[" : "",
542*6236dae4SAndroid Build Coastguard Worker                     conn->host.name,
543*6236dae4SAndroid Build Coastguard Worker                     conn->bits.ipv6_ip ? "]" : "",
544*6236dae4SAndroid Build Coastguard Worker                     conn->remote_port);
545*6236dae4SAndroid Build Coastguard Worker   if(!hosturl)
546*6236dae4SAndroid Build Coastguard Worker     return CURLE_OUT_OF_MEMORY;
547*6236dae4SAndroid Build Coastguard Worker 
548*6236dae4SAndroid Build Coastguard Worker   rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld);
549*6236dae4SAndroid Build Coastguard Worker   if(rc) {
550*6236dae4SAndroid Build Coastguard Worker     failf(data, "LDAP local: Cannot connect to %s, %s",
551*6236dae4SAndroid Build Coastguard Worker           hosturl, ldap_err2string(rc));
552*6236dae4SAndroid Build Coastguard Worker     free(hosturl);
553*6236dae4SAndroid Build Coastguard Worker     return CURLE_COULDNT_CONNECT;
554*6236dae4SAndroid Build Coastguard Worker   }
555*6236dae4SAndroid Build Coastguard Worker 
556*6236dae4SAndroid Build Coastguard Worker   free(hosturl);
557*6236dae4SAndroid Build Coastguard Worker 
558*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_OPENLDAP_DEBUG
559*6236dae4SAndroid Build Coastguard Worker   if(do_trace < 0) {
560*6236dae4SAndroid Build Coastguard Worker     const char *env = getenv("CURL_OPENLDAP_TRACE");
561*6236dae4SAndroid Build Coastguard Worker     do_trace = (env && strtol(env, NULL, 10) > 0);
562*6236dae4SAndroid Build Coastguard Worker   }
563*6236dae4SAndroid Build Coastguard Worker   if(do_trace)
564*6236dae4SAndroid Build Coastguard Worker     ldap_set_option(li->ld, LDAP_OPT_DEBUG_LEVEL, &do_trace);
565*6236dae4SAndroid Build Coastguard Worker #endif
566*6236dae4SAndroid Build Coastguard Worker 
567*6236dae4SAndroid Build Coastguard Worker   /* Try version 3 first. */
568*6236dae4SAndroid Build Coastguard Worker   ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
569*6236dae4SAndroid Build Coastguard Worker 
570*6236dae4SAndroid Build Coastguard Worker   /* Do not chase referrals. */
571*6236dae4SAndroid Build Coastguard Worker   ldap_set_option(li->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
572*6236dae4SAndroid Build Coastguard Worker 
573*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SSL
574*6236dae4SAndroid Build Coastguard Worker   if(conn->handler->flags & PROTOPT_SSL)
575*6236dae4SAndroid Build Coastguard Worker     return oldap_ssl_connect(data, OLDAP_SSL);
576*6236dae4SAndroid Build Coastguard Worker 
577*6236dae4SAndroid Build Coastguard Worker   if(data->set.use_ssl) {
578*6236dae4SAndroid Build Coastguard Worker     CURLcode result = oldap_perform_starttls(data);
579*6236dae4SAndroid Build Coastguard Worker 
580*6236dae4SAndroid Build Coastguard Worker     if(!result || data->set.use_ssl != CURLUSESSL_TRY)
581*6236dae4SAndroid Build Coastguard Worker       return result;
582*6236dae4SAndroid Build Coastguard Worker   }
583*6236dae4SAndroid Build Coastguard Worker #endif
584*6236dae4SAndroid Build Coastguard Worker 
585*6236dae4SAndroid Build Coastguard Worker   if(li->sasl.prefmech != SASL_AUTH_NONE)
586*6236dae4SAndroid Build Coastguard Worker     return oldap_perform_mechs(data);
587*6236dae4SAndroid Build Coastguard Worker 
588*6236dae4SAndroid Build Coastguard Worker   /* Force bind even if anonymous bind is not needed in protocol version 3
589*6236dae4SAndroid Build Coastguard Worker      to detect missing version 3 support. */
590*6236dae4SAndroid Build Coastguard Worker   return oldap_perform_bind(data, OLDAP_BIND);
591*6236dae4SAndroid Build Coastguard Worker }
592*6236dae4SAndroid Build Coastguard Worker 
593*6236dae4SAndroid Build Coastguard Worker /* Handle the supported SASL mechanisms query response */
oldap_state_mechs_resp(struct Curl_easy * data,LDAPMessage * msg,int code)594*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_state_mechs_resp(struct Curl_easy *data,
595*6236dae4SAndroid Build Coastguard Worker                                        LDAPMessage *msg, int code)
596*6236dae4SAndroid Build Coastguard Worker {
597*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
598*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = conn->proto.ldapc;
599*6236dae4SAndroid Build Coastguard Worker   int rc;
600*6236dae4SAndroid Build Coastguard Worker   BerElement *ber = NULL;
601*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
602*6236dae4SAndroid Build Coastguard Worker   struct berval bv, *bvals;
603*6236dae4SAndroid Build Coastguard Worker 
604*6236dae4SAndroid Build Coastguard Worker   switch(ldap_msgtype(msg)) {
605*6236dae4SAndroid Build Coastguard Worker   case LDAP_RES_SEARCH_ENTRY:
606*6236dae4SAndroid Build Coastguard Worker     /* Got a list of supported SASL mechanisms. */
607*6236dae4SAndroid Build Coastguard Worker     if(code != LDAP_SUCCESS && code != LDAP_NO_RESULTS_RETURNED)
608*6236dae4SAndroid Build Coastguard Worker       return CURLE_LOGIN_DENIED;
609*6236dae4SAndroid Build Coastguard Worker 
610*6236dae4SAndroid Build Coastguard Worker     rc = ldap_get_dn_ber(li->ld, msg, &ber, &bv);
611*6236dae4SAndroid Build Coastguard Worker     if(rc < 0)
612*6236dae4SAndroid Build Coastguard Worker       return oldap_map_error(rc, CURLE_BAD_CONTENT_ENCODING);
613*6236dae4SAndroid Build Coastguard Worker     for(rc = ldap_get_attribute_ber(li->ld, msg, ber, &bv, &bvals);
614*6236dae4SAndroid Build Coastguard Worker         rc == LDAP_SUCCESS;
615*6236dae4SAndroid Build Coastguard Worker         rc = ldap_get_attribute_ber(li->ld, msg, ber, &bv, &bvals)) {
616*6236dae4SAndroid Build Coastguard Worker       int i;
617*6236dae4SAndroid Build Coastguard Worker 
618*6236dae4SAndroid Build Coastguard Worker       if(!bv.bv_val)
619*6236dae4SAndroid Build Coastguard Worker         break;
620*6236dae4SAndroid Build Coastguard Worker 
621*6236dae4SAndroid Build Coastguard Worker       if(bvals) {
622*6236dae4SAndroid Build Coastguard Worker         for(i = 0; bvals[i].bv_val; i++) {
623*6236dae4SAndroid Build Coastguard Worker           size_t llen;
624*6236dae4SAndroid Build Coastguard Worker           unsigned short mech = Curl_sasl_decode_mech((char *) bvals[i].bv_val,
625*6236dae4SAndroid Build Coastguard Worker                                                       bvals[i].bv_len, &llen);
626*6236dae4SAndroid Build Coastguard Worker           if(bvals[i].bv_len == llen)
627*6236dae4SAndroid Build Coastguard Worker             li->sasl.authmechs |= mech;
628*6236dae4SAndroid Build Coastguard Worker         }
629*6236dae4SAndroid Build Coastguard Worker         ber_memfree(bvals);
630*6236dae4SAndroid Build Coastguard Worker       }
631*6236dae4SAndroid Build Coastguard Worker     }
632*6236dae4SAndroid Build Coastguard Worker     ber_free(ber, 0);
633*6236dae4SAndroid Build Coastguard Worker     break;
634*6236dae4SAndroid Build Coastguard Worker 
635*6236dae4SAndroid Build Coastguard Worker   case LDAP_RES_SEARCH_RESULT:
636*6236dae4SAndroid Build Coastguard Worker     switch(code) {
637*6236dae4SAndroid Build Coastguard Worker     case LDAP_SIZELIMIT_EXCEEDED:
638*6236dae4SAndroid Build Coastguard Worker       infof(data, "Too many authentication mechanisms\n");
639*6236dae4SAndroid Build Coastguard Worker       FALLTHROUGH();
640*6236dae4SAndroid Build Coastguard Worker     case LDAP_SUCCESS:
641*6236dae4SAndroid Build Coastguard Worker     case LDAP_NO_RESULTS_RETURNED:
642*6236dae4SAndroid Build Coastguard Worker       if(Curl_sasl_can_authenticate(&li->sasl, data))
643*6236dae4SAndroid Build Coastguard Worker         result = oldap_perform_sasl(data);
644*6236dae4SAndroid Build Coastguard Worker       else
645*6236dae4SAndroid Build Coastguard Worker         result = CURLE_LOGIN_DENIED;
646*6236dae4SAndroid Build Coastguard Worker       break;
647*6236dae4SAndroid Build Coastguard Worker     default:
648*6236dae4SAndroid Build Coastguard Worker       result = oldap_map_error(code, CURLE_LOGIN_DENIED);
649*6236dae4SAndroid Build Coastguard Worker       break;
650*6236dae4SAndroid Build Coastguard Worker     }
651*6236dae4SAndroid Build Coastguard Worker     break;
652*6236dae4SAndroid Build Coastguard Worker   default:
653*6236dae4SAndroid Build Coastguard Worker     break;
654*6236dae4SAndroid Build Coastguard Worker   }
655*6236dae4SAndroid Build Coastguard Worker   return result;
656*6236dae4SAndroid Build Coastguard Worker }
657*6236dae4SAndroid Build Coastguard Worker 
658*6236dae4SAndroid Build Coastguard Worker /* Handle a SASL bind response. */
oldap_state_sasl_resp(struct Curl_easy * data,LDAPMessage * msg,int code)659*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_state_sasl_resp(struct Curl_easy *data,
660*6236dae4SAndroid Build Coastguard Worker                                       LDAPMessage *msg, int code)
661*6236dae4SAndroid Build Coastguard Worker {
662*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
663*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = conn->proto.ldapc;
664*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
665*6236dae4SAndroid Build Coastguard Worker   saslprogress progress;
666*6236dae4SAndroid Build Coastguard Worker   int rc;
667*6236dae4SAndroid Build Coastguard Worker 
668*6236dae4SAndroid Build Coastguard Worker   li->servercred = NULL;
669*6236dae4SAndroid Build Coastguard Worker   rc = ldap_parse_sasl_bind_result(li->ld, msg, &li->servercred, 0);
670*6236dae4SAndroid Build Coastguard Worker   if(rc != LDAP_SUCCESS) {
671*6236dae4SAndroid Build Coastguard Worker     failf(data, "LDAP local: sasl ldap_parse_result %s", ldap_err2string(rc));
672*6236dae4SAndroid Build Coastguard Worker     result = oldap_map_error(rc, CURLE_LOGIN_DENIED);
673*6236dae4SAndroid Build Coastguard Worker   }
674*6236dae4SAndroid Build Coastguard Worker   else {
675*6236dae4SAndroid Build Coastguard Worker     result = Curl_sasl_continue(&li->sasl, data, code, &progress);
676*6236dae4SAndroid Build Coastguard Worker     if(!result && progress != SASL_INPROGRESS)
677*6236dae4SAndroid Build Coastguard Worker       oldap_state(data, OLDAP_STOP);
678*6236dae4SAndroid Build Coastguard Worker   }
679*6236dae4SAndroid Build Coastguard Worker 
680*6236dae4SAndroid Build Coastguard Worker   if(li->servercred)
681*6236dae4SAndroid Build Coastguard Worker     ber_bvfree(li->servercred);
682*6236dae4SAndroid Build Coastguard Worker   return result;
683*6236dae4SAndroid Build Coastguard Worker }
684*6236dae4SAndroid Build Coastguard Worker 
685*6236dae4SAndroid Build Coastguard Worker /* Handle a simple bind response. */
oldap_state_bind_resp(struct Curl_easy * data,LDAPMessage * msg,int code)686*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_state_bind_resp(struct Curl_easy *data, LDAPMessage *msg,
687*6236dae4SAndroid Build Coastguard Worker                                       int code)
688*6236dae4SAndroid Build Coastguard Worker {
689*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
690*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = conn->proto.ldapc;
691*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
692*6236dae4SAndroid Build Coastguard Worker   struct berval *bv = NULL;
693*6236dae4SAndroid Build Coastguard Worker   int rc;
694*6236dae4SAndroid Build Coastguard Worker 
695*6236dae4SAndroid Build Coastguard Worker   if(code != LDAP_SUCCESS)
696*6236dae4SAndroid Build Coastguard Worker     return oldap_map_error(code, CURLE_LDAP_CANNOT_BIND);
697*6236dae4SAndroid Build Coastguard Worker 
698*6236dae4SAndroid Build Coastguard Worker   rc = ldap_parse_sasl_bind_result(li->ld, msg, &bv, 0);
699*6236dae4SAndroid Build Coastguard Worker   if(rc != LDAP_SUCCESS) {
700*6236dae4SAndroid Build Coastguard Worker     failf(data, "LDAP local: bind ldap_parse_sasl_bind_result %s",
701*6236dae4SAndroid Build Coastguard Worker           ldap_err2string(rc));
702*6236dae4SAndroid Build Coastguard Worker     result = oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND);
703*6236dae4SAndroid Build Coastguard Worker   }
704*6236dae4SAndroid Build Coastguard Worker   else
705*6236dae4SAndroid Build Coastguard Worker     oldap_state(data, OLDAP_STOP);
706*6236dae4SAndroid Build Coastguard Worker 
707*6236dae4SAndroid Build Coastguard Worker   if(bv)
708*6236dae4SAndroid Build Coastguard Worker     ber_bvfree(bv);
709*6236dae4SAndroid Build Coastguard Worker   return result;
710*6236dae4SAndroid Build Coastguard Worker }
711*6236dae4SAndroid Build Coastguard Worker 
oldap_connecting(struct Curl_easy * data,bool * done)712*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
713*6236dae4SAndroid Build Coastguard Worker {
714*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
715*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
716*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = conn->proto.ldapc;
717*6236dae4SAndroid Build Coastguard Worker   LDAPMessage *msg = NULL;
718*6236dae4SAndroid Build Coastguard Worker   struct timeval tv = {0, 0};
719*6236dae4SAndroid Build Coastguard Worker   int code = LDAP_SUCCESS;
720*6236dae4SAndroid Build Coastguard Worker   int rc;
721*6236dae4SAndroid Build Coastguard Worker 
722*6236dae4SAndroid Build Coastguard Worker   if(li->state != OLDAP_SSL && li->state != OLDAP_TLS) {
723*6236dae4SAndroid Build Coastguard Worker     /* Get response to last command. */
724*6236dae4SAndroid Build Coastguard Worker     rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, &tv, &msg);
725*6236dae4SAndroid Build Coastguard Worker     switch(rc) {
726*6236dae4SAndroid Build Coastguard Worker     case 0:                               /* Timed out. */
727*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
728*6236dae4SAndroid Build Coastguard Worker     case LDAP_RES_SEARCH_ENTRY:
729*6236dae4SAndroid Build Coastguard Worker     case LDAP_RES_SEARCH_REFERENCE:
730*6236dae4SAndroid Build Coastguard Worker       break;
731*6236dae4SAndroid Build Coastguard Worker     default:
732*6236dae4SAndroid Build Coastguard Worker       li->msgid = 0;                      /* Nothing to abandon upon error. */
733*6236dae4SAndroid Build Coastguard Worker       if(rc < 0) {
734*6236dae4SAndroid Build Coastguard Worker         failf(data, "LDAP local: connecting ldap_result %s",
735*6236dae4SAndroid Build Coastguard Worker               ldap_err2string(rc));
736*6236dae4SAndroid Build Coastguard Worker         return oldap_map_error(rc, CURLE_COULDNT_CONNECT);
737*6236dae4SAndroid Build Coastguard Worker       }
738*6236dae4SAndroid Build Coastguard Worker       break;
739*6236dae4SAndroid Build Coastguard Worker     }
740*6236dae4SAndroid Build Coastguard Worker 
741*6236dae4SAndroid Build Coastguard Worker     /* Get error code from message. */
742*6236dae4SAndroid Build Coastguard Worker     rc = ldap_parse_result(li->ld, msg, &code, NULL, NULL, NULL, NULL, 0);
743*6236dae4SAndroid Build Coastguard Worker     if(rc)
744*6236dae4SAndroid Build Coastguard Worker       code = rc;
745*6236dae4SAndroid Build Coastguard Worker     else {
746*6236dae4SAndroid Build Coastguard Worker       /* store the latest code for later retrieval */
747*6236dae4SAndroid Build Coastguard Worker       data->info.httpcode = code;
748*6236dae4SAndroid Build Coastguard Worker     }
749*6236dae4SAndroid Build Coastguard Worker 
750*6236dae4SAndroid Build Coastguard Worker     /* If protocol version 3 is not supported, fallback to version 2. */
751*6236dae4SAndroid Build Coastguard Worker     if(code == LDAP_PROTOCOL_ERROR && li->state != OLDAP_BINDV2 &&
752*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SSL
753*6236dae4SAndroid Build Coastguard Worker        (ssl_installed(conn) || data->set.use_ssl <= CURLUSESSL_TRY) &&
754*6236dae4SAndroid Build Coastguard Worker #endif
755*6236dae4SAndroid Build Coastguard Worker        li->sasl.prefmech == SASL_AUTH_NONE) {
756*6236dae4SAndroid Build Coastguard Worker       static const int version = LDAP_VERSION2;
757*6236dae4SAndroid Build Coastguard Worker 
758*6236dae4SAndroid Build Coastguard Worker       ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
759*6236dae4SAndroid Build Coastguard Worker       ldap_msgfree(msg);
760*6236dae4SAndroid Build Coastguard Worker       return oldap_perform_bind(data, OLDAP_BINDV2);
761*6236dae4SAndroid Build Coastguard Worker     }
762*6236dae4SAndroid Build Coastguard Worker   }
763*6236dae4SAndroid Build Coastguard Worker 
764*6236dae4SAndroid Build Coastguard Worker   /* Handle response message according to current state. */
765*6236dae4SAndroid Build Coastguard Worker   switch(li->state) {
766*6236dae4SAndroid Build Coastguard Worker 
767*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SSL
768*6236dae4SAndroid Build Coastguard Worker   case OLDAP_SSL:
769*6236dae4SAndroid Build Coastguard Worker     result = oldap_ssl_connect(data, OLDAP_SSL);
770*6236dae4SAndroid Build Coastguard Worker     if(!result && ssl_installed(conn)) {
771*6236dae4SAndroid Build Coastguard Worker       if(li->sasl.prefmech != SASL_AUTH_NONE)
772*6236dae4SAndroid Build Coastguard Worker         result = oldap_perform_mechs(data);
773*6236dae4SAndroid Build Coastguard Worker       else
774*6236dae4SAndroid Build Coastguard Worker         result = oldap_perform_bind(data, OLDAP_BIND);
775*6236dae4SAndroid Build Coastguard Worker     }
776*6236dae4SAndroid Build Coastguard Worker     break;
777*6236dae4SAndroid Build Coastguard Worker   case OLDAP_STARTTLS:
778*6236dae4SAndroid Build Coastguard Worker     if(code != LDAP_SUCCESS) {
779*6236dae4SAndroid Build Coastguard Worker       if(data->set.use_ssl != CURLUSESSL_TRY)
780*6236dae4SAndroid Build Coastguard Worker         result = oldap_map_error(code, CURLE_USE_SSL_FAILED);
781*6236dae4SAndroid Build Coastguard Worker       else if(li->sasl.prefmech != SASL_AUTH_NONE)
782*6236dae4SAndroid Build Coastguard Worker         result = oldap_perform_mechs(data);
783*6236dae4SAndroid Build Coastguard Worker       else
784*6236dae4SAndroid Build Coastguard Worker         result = oldap_perform_bind(data, OLDAP_BIND);
785*6236dae4SAndroid Build Coastguard Worker       break;
786*6236dae4SAndroid Build Coastguard Worker     }
787*6236dae4SAndroid Build Coastguard Worker     result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
788*6236dae4SAndroid Build Coastguard Worker     if(result)
789*6236dae4SAndroid Build Coastguard Worker       break;
790*6236dae4SAndroid Build Coastguard Worker     FALLTHROUGH();
791*6236dae4SAndroid Build Coastguard Worker   case OLDAP_TLS:
792*6236dae4SAndroid Build Coastguard Worker     result = oldap_ssl_connect(data, OLDAP_TLS);
793*6236dae4SAndroid Build Coastguard Worker     if(result)
794*6236dae4SAndroid Build Coastguard Worker       result = oldap_map_error(code, CURLE_USE_SSL_FAILED);
795*6236dae4SAndroid Build Coastguard Worker     else if(ssl_installed(conn)) {
796*6236dae4SAndroid Build Coastguard Worker       conn->bits.tls_upgraded = TRUE;
797*6236dae4SAndroid Build Coastguard Worker       if(li->sasl.prefmech != SASL_AUTH_NONE)
798*6236dae4SAndroid Build Coastguard Worker         result = oldap_perform_mechs(data);
799*6236dae4SAndroid Build Coastguard Worker       else if(data->state.aptr.user)
800*6236dae4SAndroid Build Coastguard Worker         result = oldap_perform_bind(data, OLDAP_BIND);
801*6236dae4SAndroid Build Coastguard Worker       else {
802*6236dae4SAndroid Build Coastguard Worker         /* Version 3 supported: no bind required */
803*6236dae4SAndroid Build Coastguard Worker         oldap_state(data, OLDAP_STOP);
804*6236dae4SAndroid Build Coastguard Worker         result = CURLE_OK;
805*6236dae4SAndroid Build Coastguard Worker       }
806*6236dae4SAndroid Build Coastguard Worker     }
807*6236dae4SAndroid Build Coastguard Worker     break;
808*6236dae4SAndroid Build Coastguard Worker #endif
809*6236dae4SAndroid Build Coastguard Worker 
810*6236dae4SAndroid Build Coastguard Worker   case OLDAP_MECHS:
811*6236dae4SAndroid Build Coastguard Worker     result = oldap_state_mechs_resp(data, msg, code);
812*6236dae4SAndroid Build Coastguard Worker     break;
813*6236dae4SAndroid Build Coastguard Worker   case OLDAP_SASL:
814*6236dae4SAndroid Build Coastguard Worker     result = oldap_state_sasl_resp(data, msg, code);
815*6236dae4SAndroid Build Coastguard Worker     break;
816*6236dae4SAndroid Build Coastguard Worker   case OLDAP_BIND:
817*6236dae4SAndroid Build Coastguard Worker   case OLDAP_BINDV2:
818*6236dae4SAndroid Build Coastguard Worker     result = oldap_state_bind_resp(data, msg, code);
819*6236dae4SAndroid Build Coastguard Worker     break;
820*6236dae4SAndroid Build Coastguard Worker   default:
821*6236dae4SAndroid Build Coastguard Worker     /* internal error */
822*6236dae4SAndroid Build Coastguard Worker     result = CURLE_COULDNT_CONNECT;
823*6236dae4SAndroid Build Coastguard Worker     break;
824*6236dae4SAndroid Build Coastguard Worker   }
825*6236dae4SAndroid Build Coastguard Worker 
826*6236dae4SAndroid Build Coastguard Worker   ldap_msgfree(msg);
827*6236dae4SAndroid Build Coastguard Worker 
828*6236dae4SAndroid Build Coastguard Worker   *done = li->state == OLDAP_STOP;
829*6236dae4SAndroid Build Coastguard Worker   if(*done)
830*6236dae4SAndroid Build Coastguard Worker     conn->recv[FIRSTSOCKET] = oldap_recv;
831*6236dae4SAndroid Build Coastguard Worker 
832*6236dae4SAndroid Build Coastguard Worker   if(result && li->msgid) {
833*6236dae4SAndroid Build Coastguard Worker     ldap_abandon_ext(li->ld, li->msgid, NULL, NULL);
834*6236dae4SAndroid Build Coastguard Worker     li->msgid = 0;
835*6236dae4SAndroid Build Coastguard Worker   }
836*6236dae4SAndroid Build Coastguard Worker   return result;
837*6236dae4SAndroid Build Coastguard Worker }
838*6236dae4SAndroid Build Coastguard Worker 
oldap_disconnect(struct Curl_easy * data,struct connectdata * conn,bool dead_connection)839*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_disconnect(struct Curl_easy *data,
840*6236dae4SAndroid Build Coastguard Worker                                  struct connectdata *conn,
841*6236dae4SAndroid Build Coastguard Worker                                  bool dead_connection)
842*6236dae4SAndroid Build Coastguard Worker {
843*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = conn->proto.ldapc;
844*6236dae4SAndroid Build Coastguard Worker   (void) dead_connection;
845*6236dae4SAndroid Build Coastguard Worker #ifndef USE_SSL
846*6236dae4SAndroid Build Coastguard Worker   (void)data;
847*6236dae4SAndroid Build Coastguard Worker #endif
848*6236dae4SAndroid Build Coastguard Worker 
849*6236dae4SAndroid Build Coastguard Worker   if(li) {
850*6236dae4SAndroid Build Coastguard Worker     if(li->ld) {
851*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SSL
852*6236dae4SAndroid Build Coastguard Worker       if(ssl_installed(conn)) {
853*6236dae4SAndroid Build Coastguard Worker         Sockbuf *sb;
854*6236dae4SAndroid Build Coastguard Worker         ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
855*6236dae4SAndroid Build Coastguard Worker         ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data);
856*6236dae4SAndroid Build Coastguard Worker       }
857*6236dae4SAndroid Build Coastguard Worker #endif
858*6236dae4SAndroid Build Coastguard Worker       ldap_unbind_ext(li->ld, NULL, NULL);
859*6236dae4SAndroid Build Coastguard Worker       li->ld = NULL;
860*6236dae4SAndroid Build Coastguard Worker     }
861*6236dae4SAndroid Build Coastguard Worker     Curl_sasl_cleanup(conn, li->sasl.authused);
862*6236dae4SAndroid Build Coastguard Worker     conn->proto.ldapc = NULL;
863*6236dae4SAndroid Build Coastguard Worker     free(li);
864*6236dae4SAndroid Build Coastguard Worker   }
865*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
866*6236dae4SAndroid Build Coastguard Worker }
867*6236dae4SAndroid Build Coastguard Worker 
oldap_do(struct Curl_easy * data,bool * done)868*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_do(struct Curl_easy *data, bool *done)
869*6236dae4SAndroid Build Coastguard Worker {
870*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
871*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = conn->proto.ldapc;
872*6236dae4SAndroid Build Coastguard Worker   struct ldapreqinfo *lr;
873*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
874*6236dae4SAndroid Build Coastguard Worker   int rc;
875*6236dae4SAndroid Build Coastguard Worker   LDAPURLDesc *lud;
876*6236dae4SAndroid Build Coastguard Worker   int msgid;
877*6236dae4SAndroid Build Coastguard Worker 
878*6236dae4SAndroid Build Coastguard Worker   connkeep(conn, "OpenLDAP do");
879*6236dae4SAndroid Build Coastguard Worker 
880*6236dae4SAndroid Build Coastguard Worker   infof(data, "LDAP local: %s", data->state.url);
881*6236dae4SAndroid Build Coastguard Worker 
882*6236dae4SAndroid Build Coastguard Worker   result = oldap_url_parse(data, &lud);
883*6236dae4SAndroid Build Coastguard Worker   if(!result) {
884*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SSL
885*6236dae4SAndroid Build Coastguard Worker     if(ssl_installed(conn)) {
886*6236dae4SAndroid Build Coastguard Worker       Sockbuf *sb;
887*6236dae4SAndroid Build Coastguard Worker       /* re-install the libcurl SSL handlers into the sockbuf. */
888*6236dae4SAndroid Build Coastguard Worker       ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
889*6236dae4SAndroid Build Coastguard Worker       ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data);
890*6236dae4SAndroid Build Coastguard Worker     }
891*6236dae4SAndroid Build Coastguard Worker #endif
892*6236dae4SAndroid Build Coastguard Worker 
893*6236dae4SAndroid Build Coastguard Worker     rc = ldap_search_ext(li->ld, lud->lud_dn, lud->lud_scope,
894*6236dae4SAndroid Build Coastguard Worker                          lud->lud_filter, lud->lud_attrs, 0,
895*6236dae4SAndroid Build Coastguard Worker                          NULL, NULL, NULL, 0, &msgid);
896*6236dae4SAndroid Build Coastguard Worker     ldap_free_urldesc(lud);
897*6236dae4SAndroid Build Coastguard Worker     if(rc != LDAP_SUCCESS) {
898*6236dae4SAndroid Build Coastguard Worker       failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc));
899*6236dae4SAndroid Build Coastguard Worker       result = CURLE_LDAP_SEARCH_FAILED;
900*6236dae4SAndroid Build Coastguard Worker     }
901*6236dae4SAndroid Build Coastguard Worker     else {
902*6236dae4SAndroid Build Coastguard Worker       lr = calloc(1, sizeof(struct ldapreqinfo));
903*6236dae4SAndroid Build Coastguard Worker       if(!lr) {
904*6236dae4SAndroid Build Coastguard Worker         ldap_abandon_ext(li->ld, msgid, NULL, NULL);
905*6236dae4SAndroid Build Coastguard Worker         result = CURLE_OUT_OF_MEMORY;
906*6236dae4SAndroid Build Coastguard Worker       }
907*6236dae4SAndroid Build Coastguard Worker       else {
908*6236dae4SAndroid Build Coastguard Worker         lr->msgid = msgid;
909*6236dae4SAndroid Build Coastguard Worker         data->req.p.ldap = lr;
910*6236dae4SAndroid Build Coastguard Worker         Curl_xfer_setup1(data, CURL_XFER_RECV, -1, FALSE);
911*6236dae4SAndroid Build Coastguard Worker         *done = TRUE;
912*6236dae4SAndroid Build Coastguard Worker       }
913*6236dae4SAndroid Build Coastguard Worker     }
914*6236dae4SAndroid Build Coastguard Worker   }
915*6236dae4SAndroid Build Coastguard Worker   return result;
916*6236dae4SAndroid Build Coastguard Worker }
917*6236dae4SAndroid Build Coastguard Worker 
oldap_done(struct Curl_easy * data,CURLcode res,bool premature)918*6236dae4SAndroid Build Coastguard Worker static CURLcode oldap_done(struct Curl_easy *data, CURLcode res,
919*6236dae4SAndroid Build Coastguard Worker                            bool premature)
920*6236dae4SAndroid Build Coastguard Worker {
921*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
922*6236dae4SAndroid Build Coastguard Worker   struct ldapreqinfo *lr = data->req.p.ldap;
923*6236dae4SAndroid Build Coastguard Worker 
924*6236dae4SAndroid Build Coastguard Worker   (void)res;
925*6236dae4SAndroid Build Coastguard Worker   (void)premature;
926*6236dae4SAndroid Build Coastguard Worker 
927*6236dae4SAndroid Build Coastguard Worker   if(lr) {
928*6236dae4SAndroid Build Coastguard Worker     /* if there was a search in progress, abandon it */
929*6236dae4SAndroid Build Coastguard Worker     if(lr->msgid) {
930*6236dae4SAndroid Build Coastguard Worker       struct ldapconninfo *li = conn->proto.ldapc;
931*6236dae4SAndroid Build Coastguard Worker       ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL);
932*6236dae4SAndroid Build Coastguard Worker       lr->msgid = 0;
933*6236dae4SAndroid Build Coastguard Worker     }
934*6236dae4SAndroid Build Coastguard Worker     data->req.p.ldap = NULL;
935*6236dae4SAndroid Build Coastguard Worker     free(lr);
936*6236dae4SAndroid Build Coastguard Worker   }
937*6236dae4SAndroid Build Coastguard Worker 
938*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
939*6236dae4SAndroid Build Coastguard Worker }
940*6236dae4SAndroid Build Coastguard Worker 
client_write(struct Curl_easy * data,const char * prefix,size_t plen,const char * value,size_t len,const char * suffix,size_t slen)941*6236dae4SAndroid Build Coastguard Worker static CURLcode client_write(struct Curl_easy *data,
942*6236dae4SAndroid Build Coastguard Worker                              const char *prefix, size_t plen,
943*6236dae4SAndroid Build Coastguard Worker                              const char *value, size_t len,
944*6236dae4SAndroid Build Coastguard Worker                              const char *suffix, size_t slen)
945*6236dae4SAndroid Build Coastguard Worker {
946*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
947*6236dae4SAndroid Build Coastguard Worker 
948*6236dae4SAndroid Build Coastguard Worker   if(prefix) {
949*6236dae4SAndroid Build Coastguard Worker     /* If we have a zero-length value and the prefix ends with a space
950*6236dae4SAndroid Build Coastguard Worker        separator, drop the latter. */
951*6236dae4SAndroid Build Coastguard Worker     if(!len && plen && prefix[plen - 1] == ' ')
952*6236dae4SAndroid Build Coastguard Worker       plen--;
953*6236dae4SAndroid Build Coastguard Worker     result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) prefix, plen);
954*6236dae4SAndroid Build Coastguard Worker   }
955*6236dae4SAndroid Build Coastguard Worker   if(!result && value) {
956*6236dae4SAndroid Build Coastguard Worker     result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) value, len);
957*6236dae4SAndroid Build Coastguard Worker   }
958*6236dae4SAndroid Build Coastguard Worker   if(!result && suffix) {
959*6236dae4SAndroid Build Coastguard Worker     result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) suffix, slen);
960*6236dae4SAndroid Build Coastguard Worker   }
961*6236dae4SAndroid Build Coastguard Worker   return result;
962*6236dae4SAndroid Build Coastguard Worker }
963*6236dae4SAndroid Build Coastguard Worker 
oldap_recv(struct Curl_easy * data,int sockindex,char * buf,size_t len,CURLcode * err)964*6236dae4SAndroid Build Coastguard Worker static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
965*6236dae4SAndroid Build Coastguard Worker                           size_t len, CURLcode *err)
966*6236dae4SAndroid Build Coastguard Worker {
967*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
968*6236dae4SAndroid Build Coastguard Worker   struct ldapconninfo *li = conn->proto.ldapc;
969*6236dae4SAndroid Build Coastguard Worker   struct ldapreqinfo *lr = data->req.p.ldap;
970*6236dae4SAndroid Build Coastguard Worker   int rc;
971*6236dae4SAndroid Build Coastguard Worker   LDAPMessage *msg = NULL;
972*6236dae4SAndroid Build Coastguard Worker   BerElement *ber = NULL;
973*6236dae4SAndroid Build Coastguard Worker   struct timeval tv = {0, 0};
974*6236dae4SAndroid Build Coastguard Worker   struct berval bv, *bvals;
975*6236dae4SAndroid Build Coastguard Worker   bool binary = FALSE;
976*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_AGAIN;
977*6236dae4SAndroid Build Coastguard Worker   int code;
978*6236dae4SAndroid Build Coastguard Worker   char *info = NULL;
979*6236dae4SAndroid Build Coastguard Worker 
980*6236dae4SAndroid Build Coastguard Worker   (void)len;
981*6236dae4SAndroid Build Coastguard Worker   (void)buf;
982*6236dae4SAndroid Build Coastguard Worker   (void)sockindex;
983*6236dae4SAndroid Build Coastguard Worker 
984*6236dae4SAndroid Build Coastguard Worker   rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_ONE, &tv, &msg);
985*6236dae4SAndroid Build Coastguard Worker   if(rc < 0) {
986*6236dae4SAndroid Build Coastguard Worker     failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc));
987*6236dae4SAndroid Build Coastguard Worker     result = CURLE_RECV_ERROR;
988*6236dae4SAndroid Build Coastguard Worker   }
989*6236dae4SAndroid Build Coastguard Worker 
990*6236dae4SAndroid Build Coastguard Worker   *err = result;
991*6236dae4SAndroid Build Coastguard Worker 
992*6236dae4SAndroid Build Coastguard Worker   /* error or timed out */
993*6236dae4SAndroid Build Coastguard Worker   if(!msg)
994*6236dae4SAndroid Build Coastguard Worker     return -1;
995*6236dae4SAndroid Build Coastguard Worker 
996*6236dae4SAndroid Build Coastguard Worker   result = CURLE_OK;
997*6236dae4SAndroid Build Coastguard Worker 
998*6236dae4SAndroid Build Coastguard Worker   switch(ldap_msgtype(msg)) {
999*6236dae4SAndroid Build Coastguard Worker   case LDAP_RES_SEARCH_RESULT:
1000*6236dae4SAndroid Build Coastguard Worker     lr->msgid = 0;
1001*6236dae4SAndroid Build Coastguard Worker     rc = ldap_parse_result(li->ld, msg, &code, NULL, &info, NULL, NULL, 0);
1002*6236dae4SAndroid Build Coastguard Worker     if(rc) {
1003*6236dae4SAndroid Build Coastguard Worker       failf(data, "LDAP local: search ldap_parse_result %s",
1004*6236dae4SAndroid Build Coastguard Worker             ldap_err2string(rc));
1005*6236dae4SAndroid Build Coastguard Worker       result = CURLE_LDAP_SEARCH_FAILED;
1006*6236dae4SAndroid Build Coastguard Worker       break;
1007*6236dae4SAndroid Build Coastguard Worker     }
1008*6236dae4SAndroid Build Coastguard Worker 
1009*6236dae4SAndroid Build Coastguard Worker     /* store the latest code for later retrieval */
1010*6236dae4SAndroid Build Coastguard Worker     data->info.httpcode = code;
1011*6236dae4SAndroid Build Coastguard Worker 
1012*6236dae4SAndroid Build Coastguard Worker     switch(code) {
1013*6236dae4SAndroid Build Coastguard Worker     case LDAP_SIZELIMIT_EXCEEDED:
1014*6236dae4SAndroid Build Coastguard Worker       infof(data, "There are more than %d entries", lr->nument);
1015*6236dae4SAndroid Build Coastguard Worker       FALLTHROUGH();
1016*6236dae4SAndroid Build Coastguard Worker     case LDAP_SUCCESS:
1017*6236dae4SAndroid Build Coastguard Worker       data->req.size = data->req.bytecount;
1018*6236dae4SAndroid Build Coastguard Worker       break;
1019*6236dae4SAndroid Build Coastguard Worker     default:
1020*6236dae4SAndroid Build Coastguard Worker       failf(data, "LDAP remote: search failed %s %s", ldap_err2string(code),
1021*6236dae4SAndroid Build Coastguard Worker             info ? info : "");
1022*6236dae4SAndroid Build Coastguard Worker       result = CURLE_LDAP_SEARCH_FAILED;
1023*6236dae4SAndroid Build Coastguard Worker       break;
1024*6236dae4SAndroid Build Coastguard Worker     }
1025*6236dae4SAndroid Build Coastguard Worker     if(info)
1026*6236dae4SAndroid Build Coastguard Worker       ldap_memfree(info);
1027*6236dae4SAndroid Build Coastguard Worker     break;
1028*6236dae4SAndroid Build Coastguard Worker   case LDAP_RES_SEARCH_ENTRY:
1029*6236dae4SAndroid Build Coastguard Worker     lr->nument++;
1030*6236dae4SAndroid Build Coastguard Worker     rc = ldap_get_dn_ber(li->ld, msg, &ber, &bv);
1031*6236dae4SAndroid Build Coastguard Worker     if(rc < 0) {
1032*6236dae4SAndroid Build Coastguard Worker       result = CURLE_RECV_ERROR;
1033*6236dae4SAndroid Build Coastguard Worker       break;
1034*6236dae4SAndroid Build Coastguard Worker     }
1035*6236dae4SAndroid Build Coastguard Worker 
1036*6236dae4SAndroid Build Coastguard Worker     result = client_write(data, STRCONST("DN: "), bv.bv_val, bv.bv_len,
1037*6236dae4SAndroid Build Coastguard Worker                           STRCONST("\n"));
1038*6236dae4SAndroid Build Coastguard Worker     if(result)
1039*6236dae4SAndroid Build Coastguard Worker       break;
1040*6236dae4SAndroid Build Coastguard Worker 
1041*6236dae4SAndroid Build Coastguard Worker     for(rc = ldap_get_attribute_ber(li->ld, msg, ber, &bv, &bvals);
1042*6236dae4SAndroid Build Coastguard Worker         rc == LDAP_SUCCESS;
1043*6236dae4SAndroid Build Coastguard Worker         rc = ldap_get_attribute_ber(li->ld, msg, ber, &bv, &bvals)) {
1044*6236dae4SAndroid Build Coastguard Worker       int i;
1045*6236dae4SAndroid Build Coastguard Worker 
1046*6236dae4SAndroid Build Coastguard Worker       if(!bv.bv_val)
1047*6236dae4SAndroid Build Coastguard Worker         break;
1048*6236dae4SAndroid Build Coastguard Worker 
1049*6236dae4SAndroid Build Coastguard Worker       if(!bvals) {
1050*6236dae4SAndroid Build Coastguard Worker         result = client_write(data, STRCONST("\t"), bv.bv_val, bv.bv_len,
1051*6236dae4SAndroid Build Coastguard Worker                               STRCONST(":\n"));
1052*6236dae4SAndroid Build Coastguard Worker         if(result)
1053*6236dae4SAndroid Build Coastguard Worker           break;
1054*6236dae4SAndroid Build Coastguard Worker         continue;
1055*6236dae4SAndroid Build Coastguard Worker       }
1056*6236dae4SAndroid Build Coastguard Worker 
1057*6236dae4SAndroid Build Coastguard Worker       binary = bv.bv_len > 7 &&
1058*6236dae4SAndroid Build Coastguard Worker         !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7);
1059*6236dae4SAndroid Build Coastguard Worker 
1060*6236dae4SAndroid Build Coastguard Worker       for(i = 0; bvals[i].bv_val != NULL; i++) {
1061*6236dae4SAndroid Build Coastguard Worker         bool binval = FALSE;
1062*6236dae4SAndroid Build Coastguard Worker 
1063*6236dae4SAndroid Build Coastguard Worker         result = client_write(data, STRCONST("\t"), bv.bv_val, bv.bv_len,
1064*6236dae4SAndroid Build Coastguard Worker                               STRCONST(":"));
1065*6236dae4SAndroid Build Coastguard Worker         if(result)
1066*6236dae4SAndroid Build Coastguard Worker           break;
1067*6236dae4SAndroid Build Coastguard Worker 
1068*6236dae4SAndroid Build Coastguard Worker         if(!binary) {
1069*6236dae4SAndroid Build Coastguard Worker           /* check for leading or trailing whitespace */
1070*6236dae4SAndroid Build Coastguard Worker           if(ISBLANK(bvals[i].bv_val[0]) ||
1071*6236dae4SAndroid Build Coastguard Worker              ISBLANK(bvals[i].bv_val[bvals[i].bv_len - 1]))
1072*6236dae4SAndroid Build Coastguard Worker             binval = TRUE;
1073*6236dae4SAndroid Build Coastguard Worker           else {
1074*6236dae4SAndroid Build Coastguard Worker             /* check for unprintable characters */
1075*6236dae4SAndroid Build Coastguard Worker             unsigned int j;
1076*6236dae4SAndroid Build Coastguard Worker             for(j = 0; j < bvals[i].bv_len; j++)
1077*6236dae4SAndroid Build Coastguard Worker               if(!ISPRINT(bvals[i].bv_val[j])) {
1078*6236dae4SAndroid Build Coastguard Worker                 binval = TRUE;
1079*6236dae4SAndroid Build Coastguard Worker                 break;
1080*6236dae4SAndroid Build Coastguard Worker               }
1081*6236dae4SAndroid Build Coastguard Worker           }
1082*6236dae4SAndroid Build Coastguard Worker         }
1083*6236dae4SAndroid Build Coastguard Worker         if(binary || binval) {
1084*6236dae4SAndroid Build Coastguard Worker           char *val_b64 = NULL;
1085*6236dae4SAndroid Build Coastguard Worker           size_t val_b64_sz = 0;
1086*6236dae4SAndroid Build Coastguard Worker 
1087*6236dae4SAndroid Build Coastguard Worker           /* Binary value, encode to base64. */
1088*6236dae4SAndroid Build Coastguard Worker           if(bvals[i].bv_len)
1089*6236dae4SAndroid Build Coastguard Worker             result = Curl_base64_encode(bvals[i].bv_val, bvals[i].bv_len,
1090*6236dae4SAndroid Build Coastguard Worker                                         &val_b64, &val_b64_sz);
1091*6236dae4SAndroid Build Coastguard Worker           if(!result)
1092*6236dae4SAndroid Build Coastguard Worker             result = client_write(data, STRCONST(": "), val_b64, val_b64_sz,
1093*6236dae4SAndroid Build Coastguard Worker                                   STRCONST("\n"));
1094*6236dae4SAndroid Build Coastguard Worker           free(val_b64);
1095*6236dae4SAndroid Build Coastguard Worker         }
1096*6236dae4SAndroid Build Coastguard Worker         else
1097*6236dae4SAndroid Build Coastguard Worker           result = client_write(data, STRCONST(" "),
1098*6236dae4SAndroid Build Coastguard Worker                                 bvals[i].bv_val, bvals[i].bv_len,
1099*6236dae4SAndroid Build Coastguard Worker                                 STRCONST("\n"));
1100*6236dae4SAndroid Build Coastguard Worker         if(result)
1101*6236dae4SAndroid Build Coastguard Worker           break;
1102*6236dae4SAndroid Build Coastguard Worker       }
1103*6236dae4SAndroid Build Coastguard Worker 
1104*6236dae4SAndroid Build Coastguard Worker       ber_memfree(bvals);
1105*6236dae4SAndroid Build Coastguard Worker       bvals = NULL;
1106*6236dae4SAndroid Build Coastguard Worker       if(!result)
1107*6236dae4SAndroid Build Coastguard Worker         result = client_write(data, STRCONST("\n"), NULL, 0, NULL, 0);
1108*6236dae4SAndroid Build Coastguard Worker       if(result)
1109*6236dae4SAndroid Build Coastguard Worker         break;
1110*6236dae4SAndroid Build Coastguard Worker     }
1111*6236dae4SAndroid Build Coastguard Worker 
1112*6236dae4SAndroid Build Coastguard Worker     ber_free(ber, 0);
1113*6236dae4SAndroid Build Coastguard Worker 
1114*6236dae4SAndroid Build Coastguard Worker     if(!result)
1115*6236dae4SAndroid Build Coastguard Worker       result = client_write(data, STRCONST("\n"), NULL, 0, NULL, 0);
1116*6236dae4SAndroid Build Coastguard Worker     if(!result)
1117*6236dae4SAndroid Build Coastguard Worker       result = CURLE_AGAIN;
1118*6236dae4SAndroid Build Coastguard Worker     break;
1119*6236dae4SAndroid Build Coastguard Worker   }
1120*6236dae4SAndroid Build Coastguard Worker 
1121*6236dae4SAndroid Build Coastguard Worker   ldap_msgfree(msg);
1122*6236dae4SAndroid Build Coastguard Worker   *err = result;
1123*6236dae4SAndroid Build Coastguard Worker   return result ? -1 : 0;
1124*6236dae4SAndroid Build Coastguard Worker }
1125*6236dae4SAndroid Build Coastguard Worker 
1126*6236dae4SAndroid Build Coastguard Worker #ifdef USE_SSL
1127*6236dae4SAndroid Build Coastguard Worker static int
ldapsb_tls_setup(Sockbuf_IO_Desc * sbiod,void * arg)1128*6236dae4SAndroid Build Coastguard Worker ldapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg)
1129*6236dae4SAndroid Build Coastguard Worker {
1130*6236dae4SAndroid Build Coastguard Worker   sbiod->sbiod_pvt = arg;
1131*6236dae4SAndroid Build Coastguard Worker   return 0;
1132*6236dae4SAndroid Build Coastguard Worker }
1133*6236dae4SAndroid Build Coastguard Worker 
1134*6236dae4SAndroid Build Coastguard Worker static int
ldapsb_tls_remove(Sockbuf_IO_Desc * sbiod)1135*6236dae4SAndroid Build Coastguard Worker ldapsb_tls_remove(Sockbuf_IO_Desc *sbiod)
1136*6236dae4SAndroid Build Coastguard Worker {
1137*6236dae4SAndroid Build Coastguard Worker   sbiod->sbiod_pvt = NULL;
1138*6236dae4SAndroid Build Coastguard Worker   return 0;
1139*6236dae4SAndroid Build Coastguard Worker }
1140*6236dae4SAndroid Build Coastguard Worker 
1141*6236dae4SAndroid Build Coastguard Worker /* We do not need to do anything because libcurl does it already */
1142*6236dae4SAndroid Build Coastguard Worker static int
ldapsb_tls_close(Sockbuf_IO_Desc * sbiod)1143*6236dae4SAndroid Build Coastguard Worker ldapsb_tls_close(Sockbuf_IO_Desc *sbiod)
1144*6236dae4SAndroid Build Coastguard Worker {
1145*6236dae4SAndroid Build Coastguard Worker   (void)sbiod;
1146*6236dae4SAndroid Build Coastguard Worker   return 0;
1147*6236dae4SAndroid Build Coastguard Worker }
1148*6236dae4SAndroid Build Coastguard Worker 
1149*6236dae4SAndroid Build Coastguard Worker static int
ldapsb_tls_ctrl(Sockbuf_IO_Desc * sbiod,int opt,void * arg)1150*6236dae4SAndroid Build Coastguard Worker ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
1151*6236dae4SAndroid Build Coastguard Worker {
1152*6236dae4SAndroid Build Coastguard Worker   (void)arg;
1153*6236dae4SAndroid Build Coastguard Worker   if(opt == LBER_SB_OPT_DATA_READY) {
1154*6236dae4SAndroid Build Coastguard Worker     struct Curl_easy *data = sbiod->sbiod_pvt;
1155*6236dae4SAndroid Build Coastguard Worker     return Curl_conn_data_pending(data, FIRSTSOCKET);
1156*6236dae4SAndroid Build Coastguard Worker   }
1157*6236dae4SAndroid Build Coastguard Worker   return 0;
1158*6236dae4SAndroid Build Coastguard Worker }
1159*6236dae4SAndroid Build Coastguard Worker 
1160*6236dae4SAndroid Build Coastguard Worker static ber_slen_t
ldapsb_tls_read(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)1161*6236dae4SAndroid Build Coastguard Worker ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
1162*6236dae4SAndroid Build Coastguard Worker {
1163*6236dae4SAndroid Build Coastguard Worker   struct Curl_easy *data = sbiod->sbiod_pvt;
1164*6236dae4SAndroid Build Coastguard Worker   ber_slen_t ret = 0;
1165*6236dae4SAndroid Build Coastguard Worker   if(data) {
1166*6236dae4SAndroid Build Coastguard Worker     struct connectdata *conn = data->conn;
1167*6236dae4SAndroid Build Coastguard Worker     if(conn) {
1168*6236dae4SAndroid Build Coastguard Worker       struct ldapconninfo *li = conn->proto.ldapc;
1169*6236dae4SAndroid Build Coastguard Worker       CURLcode err = CURLE_RECV_ERROR;
1170*6236dae4SAndroid Build Coastguard Worker 
1171*6236dae4SAndroid Build Coastguard Worker       ret = (li->recv)(data, FIRSTSOCKET, buf, len, &err);
1172*6236dae4SAndroid Build Coastguard Worker       if(ret < 0 && err == CURLE_AGAIN) {
1173*6236dae4SAndroid Build Coastguard Worker         SET_SOCKERRNO(EWOULDBLOCK);
1174*6236dae4SAndroid Build Coastguard Worker       }
1175*6236dae4SAndroid Build Coastguard Worker     }
1176*6236dae4SAndroid Build Coastguard Worker   }
1177*6236dae4SAndroid Build Coastguard Worker   return ret;
1178*6236dae4SAndroid Build Coastguard Worker }
1179*6236dae4SAndroid Build Coastguard Worker 
1180*6236dae4SAndroid Build Coastguard Worker static ber_slen_t
ldapsb_tls_write(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)1181*6236dae4SAndroid Build Coastguard Worker ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
1182*6236dae4SAndroid Build Coastguard Worker {
1183*6236dae4SAndroid Build Coastguard Worker   struct Curl_easy *data = sbiod->sbiod_pvt;
1184*6236dae4SAndroid Build Coastguard Worker   ber_slen_t ret = 0;
1185*6236dae4SAndroid Build Coastguard Worker   if(data) {
1186*6236dae4SAndroid Build Coastguard Worker     struct connectdata *conn = data->conn;
1187*6236dae4SAndroid Build Coastguard Worker     if(conn) {
1188*6236dae4SAndroid Build Coastguard Worker       struct ldapconninfo *li = conn->proto.ldapc;
1189*6236dae4SAndroid Build Coastguard Worker       CURLcode err = CURLE_SEND_ERROR;
1190*6236dae4SAndroid Build Coastguard Worker       ret = (li->send)(data, FIRSTSOCKET, buf, len, FALSE, &err);
1191*6236dae4SAndroid Build Coastguard Worker       if(ret < 0 && err == CURLE_AGAIN) {
1192*6236dae4SAndroid Build Coastguard Worker         SET_SOCKERRNO(EWOULDBLOCK);
1193*6236dae4SAndroid Build Coastguard Worker       }
1194*6236dae4SAndroid Build Coastguard Worker     }
1195*6236dae4SAndroid Build Coastguard Worker   }
1196*6236dae4SAndroid Build Coastguard Worker   return ret;
1197*6236dae4SAndroid Build Coastguard Worker }
1198*6236dae4SAndroid Build Coastguard Worker 
1199*6236dae4SAndroid Build Coastguard Worker static Sockbuf_IO ldapsb_tls =
1200*6236dae4SAndroid Build Coastguard Worker {
1201*6236dae4SAndroid Build Coastguard Worker   ldapsb_tls_setup,
1202*6236dae4SAndroid Build Coastguard Worker   ldapsb_tls_remove,
1203*6236dae4SAndroid Build Coastguard Worker   ldapsb_tls_ctrl,
1204*6236dae4SAndroid Build Coastguard Worker   ldapsb_tls_read,
1205*6236dae4SAndroid Build Coastguard Worker   ldapsb_tls_write,
1206*6236dae4SAndroid Build Coastguard Worker   ldapsb_tls_close
1207*6236dae4SAndroid Build Coastguard Worker };
1208*6236dae4SAndroid Build Coastguard Worker #endif /* USE_SSL */
1209*6236dae4SAndroid Build Coastguard Worker 
1210*6236dae4SAndroid Build Coastguard Worker #endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */
1211