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