1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
9 * Copyright (C) 2011 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
10 *
11 * This software is licensed as described in the file COPYING, which
12 * you should have received as part of this distribution. The terms
13 * are also available at https://curl.haxx.se/docs/copyright.html.
14 *
15 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
16 * copies of the Software, and permit persons to whom the Software is
17 * furnished to do so, under the terms of the COPYING file.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ***************************************************************************/
23
24 #include "curl_setup.h"
25
26 #if !defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP)
27
28 /*
29 * Notice that USE_OPENLDAP is only a source code selection switch. When
30 * libcurl is built with USE_OPENLDAP defined the libcurl source code that
31 * gets compiled is the code from openldap.c, otherwise the code that gets
32 * compiled is the code from ldap.c.
33 *
34 * When USE_OPENLDAP is defined a recent version of the OpenLDAP library
35 * might be required for compilation and runtime. In order to use ancient
36 * OpenLDAP library versions, USE_OPENLDAP shall not be defined.
37 */
38
39 #include <ldap.h>
40
41 #include "urldata.h"
42 #include <curl/curl.h>
43 #include "sendf.h"
44 #include "vtls/vtls.h"
45 #include "transfer.h"
46 #include "curl_ldap.h"
47 #include "curl_base64.h"
48 #include "connect.h"
49 /* The last 3 #include files should be in this order */
50 #include "curl_printf.h"
51 #include "curl_memory.h"
52 #include "memdebug.h"
53
54 /*
55 * Uncommenting this will enable the built-in debug logging of the openldap
56 * library. The debug log level can be set using the CURL_OPENLDAP_TRACE
57 * environment variable. The debug output is written to stderr.
58 *
59 * The library supports the following debug flags:
60 * LDAP_DEBUG_NONE 0x0000
61 * LDAP_DEBUG_TRACE 0x0001
62 * LDAP_DEBUG_CONSTRUCT 0x0002
63 * LDAP_DEBUG_DESTROY 0x0004
64 * LDAP_DEBUG_PARAMETER 0x0008
65 * LDAP_DEBUG_ANY 0xffff
66 *
67 * For example, use CURL_OPENLDAP_TRACE=0 for no debug,
68 * CURL_OPENLDAP_TRACE=2 for LDAP_DEBUG_CONSTRUCT messages only,
69 * CURL_OPENLDAP_TRACE=65535 for all debug message levels.
70 */
71 /* #define CURL_OPENLDAP_DEBUG */
72
73 #ifndef _LDAP_PVT_H
74 extern int ldap_pvt_url_scheme2proto(const char *);
75 extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url,
76 LDAP **ld);
77 #endif
78
79 static CURLcode ldap_setup_connection(struct connectdata *conn);
80 static CURLcode ldap_do(struct connectdata *conn, bool *done);
81 static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool);
82 static CURLcode ldap_connect(struct connectdata *conn, bool *done);
83 static CURLcode ldap_connecting(struct connectdata *conn, bool *done);
84 static CURLcode ldap_disconnect(struct connectdata *conn, bool dead);
85
86 static Curl_recv ldap_recv;
87
88 /*
89 * LDAP protocol handler.
90 */
91
92 const struct Curl_handler Curl_handler_ldap = {
93 "LDAP", /* scheme */
94 ldap_setup_connection, /* setup_connection */
95 ldap_do, /* do_it */
96 ldap_done, /* done */
97 ZERO_NULL, /* do_more */
98 ldap_connect, /* connect_it */
99 ldap_connecting, /* connecting */
100 ZERO_NULL, /* doing */
101 ZERO_NULL, /* proto_getsock */
102 ZERO_NULL, /* doing_getsock */
103 ZERO_NULL, /* domore_getsock */
104 ZERO_NULL, /* perform_getsock */
105 ldap_disconnect, /* disconnect */
106 ZERO_NULL, /* readwrite */
107 ZERO_NULL, /* connection_check */
108 PORT_LDAP, /* defport */
109 CURLPROTO_LDAP, /* protocol */
110 CURLPROTO_LDAP, /* family */
111 PROTOPT_NONE /* flags */
112 };
113
114 #ifdef USE_SSL
115 /*
116 * LDAPS protocol handler.
117 */
118
119 const struct Curl_handler Curl_handler_ldaps = {
120 "LDAPS", /* scheme */
121 ldap_setup_connection, /* setup_connection */
122 ldap_do, /* do_it */
123 ldap_done, /* done */
124 ZERO_NULL, /* do_more */
125 ldap_connect, /* connect_it */
126 ldap_connecting, /* connecting */
127 ZERO_NULL, /* doing */
128 ZERO_NULL, /* proto_getsock */
129 ZERO_NULL, /* doing_getsock */
130 ZERO_NULL, /* domore_getsock */
131 ZERO_NULL, /* perform_getsock */
132 ldap_disconnect, /* disconnect */
133 ZERO_NULL, /* readwrite */
134 ZERO_NULL, /* connection_check */
135 PORT_LDAPS, /* defport */
136 CURLPROTO_LDAPS, /* protocol */
137 CURLPROTO_LDAP, /* family */
138 PROTOPT_SSL /* flags */
139 };
140 #endif
141
142 static const char *url_errs[] = {
143 "success",
144 "out of memory",
145 "bad parameter",
146 "unrecognized scheme",
147 "unbalanced delimiter",
148 "bad URL",
149 "bad host or port",
150 "bad or missing attributes",
151 "bad or missing scope",
152 "bad or missing filter",
153 "bad or missing extensions"
154 };
155
156 struct ldapconninfo {
157 LDAP *ld;
158 Curl_recv *recv; /* for stacking SSL handler */
159 Curl_send *send;
160 int proto;
161 int msgid;
162 bool ssldone;
163 bool sslinst;
164 bool didbind;
165 };
166
167 struct ldapreqinfo {
168 int msgid;
169 int nument;
170 };
171
ldap_setup_connection(struct connectdata * conn)172 static CURLcode ldap_setup_connection(struct connectdata *conn)
173 {
174 struct ldapconninfo *li;
175 LDAPURLDesc *lud;
176 struct Curl_easy *data = conn->data;
177 int rc, proto;
178 CURLcode status;
179
180 rc = ldap_url_parse(data->change.url, &lud);
181 if(rc != LDAP_URL_SUCCESS) {
182 const char *msg = "url parsing problem";
183 status = CURLE_URL_MALFORMAT;
184 if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) {
185 if(rc == LDAP_URL_ERR_MEM)
186 status = CURLE_OUT_OF_MEMORY;
187 msg = url_errs[rc];
188 }
189 failf(conn->data, "LDAP local: %s", msg);
190 return status;
191 }
192 proto = ldap_pvt_url_scheme2proto(lud->lud_scheme);
193 ldap_free_urldesc(lud);
194
195 li = calloc(1, sizeof(struct ldapconninfo));
196 if(!li)
197 return CURLE_OUT_OF_MEMORY;
198 li->proto = proto;
199 conn->proto.ldapc = li;
200 connkeep(conn, "OpenLDAP default");
201 return CURLE_OK;
202 }
203
204 #ifdef USE_SSL
205 static Sockbuf_IO ldapsb_tls;
206 #endif
207
ldap_connect(struct connectdata * conn,bool * done)208 static CURLcode ldap_connect(struct connectdata *conn, bool *done)
209 {
210 struct ldapconninfo *li = conn->proto.ldapc;
211 struct Curl_easy *data = conn->data;
212 int rc, proto = LDAP_VERSION3;
213 char hosturl[1024];
214 char *ptr;
215
216 (void)done;
217
218 strcpy(hosturl, "ldap");
219 ptr = hosturl + 4;
220 if(conn->handler->flags & PROTOPT_SSL)
221 *ptr++ = 's';
222 msnprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
223 conn->host.name, conn->remote_port);
224
225 #ifdef CURL_OPENLDAP_DEBUG
226 static int do_trace = 0;
227 const char *env = getenv("CURL_OPENLDAP_TRACE");
228 do_trace = (env && strtol(env, NULL, 10) > 0);
229 if(do_trace) {
230 ldap_set_option(li->ld, LDAP_OPT_DEBUG_LEVEL, &do_trace);
231 }
232 #endif
233
234 rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld);
235 if(rc) {
236 failf(data, "LDAP local: Cannot connect to %s, %s",
237 hosturl, ldap_err2string(rc));
238 return CURLE_COULDNT_CONNECT;
239 }
240
241 ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
242
243 #ifdef USE_SSL
244 if(conn->handler->flags & PROTOPT_SSL) {
245 CURLcode result;
246 result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone);
247 if(result)
248 return result;
249 }
250 #endif
251
252 return CURLE_OK;
253 }
254
ldap_connecting(struct connectdata * conn,bool * done)255 static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
256 {
257 struct ldapconninfo *li = conn->proto.ldapc;
258 struct Curl_easy *data = conn->data;
259 LDAPMessage *msg = NULL;
260 struct timeval tv = {0, 1}, *tvp;
261 int rc, err;
262 char *info = NULL;
263
264 #ifdef USE_SSL
265 if(conn->handler->flags & PROTOPT_SSL) {
266 /* Is the SSL handshake complete yet? */
267 if(!li->ssldone) {
268 CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET,
269 &li->ssldone);
270 if(result || !li->ssldone)
271 return result;
272 }
273
274 /* Have we installed the libcurl SSL handlers into the sockbuf yet? */
275 if(!li->sslinst) {
276 Sockbuf *sb;
277 ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
278 ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, conn);
279 li->sslinst = TRUE;
280 li->recv = conn->recv[FIRSTSOCKET];
281 li->send = conn->send[FIRSTSOCKET];
282 }
283 }
284 #endif
285
286 tvp = &tv;
287
288 retry:
289 if(!li->didbind) {
290 char *binddn;
291 struct berval passwd;
292
293 if(conn->bits.user_passwd) {
294 binddn = conn->user;
295 passwd.bv_val = conn->passwd;
296 passwd.bv_len = strlen(passwd.bv_val);
297 }
298 else {
299 binddn = NULL;
300 passwd.bv_val = NULL;
301 passwd.bv_len = 0;
302 }
303 rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd,
304 NULL, NULL, &li->msgid);
305 if(rc)
306 return CURLE_LDAP_CANNOT_BIND;
307 li->didbind = TRUE;
308 if(tvp)
309 return CURLE_OK;
310 }
311
312 rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, tvp, &msg);
313 if(rc < 0) {
314 failf(data, "LDAP local: bind ldap_result %s", ldap_err2string(rc));
315 return CURLE_LDAP_CANNOT_BIND;
316 }
317 if(rc == 0) {
318 /* timed out */
319 return CURLE_OK;
320 }
321
322 rc = ldap_parse_result(li->ld, msg, &err, NULL, &info, NULL, NULL, 1);
323 if(rc) {
324 failf(data, "LDAP local: bind ldap_parse_result %s", ldap_err2string(rc));
325 return CURLE_LDAP_CANNOT_BIND;
326 }
327
328 /* Try to fallback to LDAPv2? */
329 if(err == LDAP_PROTOCOL_ERROR) {
330 int proto;
331 ldap_get_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
332 if(proto == LDAP_VERSION3) {
333 if(info) {
334 ldap_memfree(info);
335 info = NULL;
336 }
337 proto = LDAP_VERSION2;
338 ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
339 li->didbind = FALSE;
340 goto retry;
341 }
342 }
343
344 if(err) {
345 failf(data, "LDAP remote: bind failed %s %s", ldap_err2string(rc),
346 info ? info : "");
347 if(info)
348 ldap_memfree(info);
349 return CURLE_LOGIN_DENIED;
350 }
351
352 if(info)
353 ldap_memfree(info);
354 conn->recv[FIRSTSOCKET] = ldap_recv;
355 *done = TRUE;
356
357 return CURLE_OK;
358 }
359
ldap_disconnect(struct connectdata * conn,bool dead_connection)360 static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection)
361 {
362 struct ldapconninfo *li = conn->proto.ldapc;
363 (void) dead_connection;
364
365 if(li) {
366 if(li->ld) {
367 ldap_unbind_ext(li->ld, NULL, NULL);
368 li->ld = NULL;
369 }
370 conn->proto.ldapc = NULL;
371 free(li);
372 }
373 return CURLE_OK;
374 }
375
ldap_do(struct connectdata * conn,bool * done)376 static CURLcode ldap_do(struct connectdata *conn, bool *done)
377 {
378 struct ldapconninfo *li = conn->proto.ldapc;
379 struct ldapreqinfo *lr;
380 CURLcode status = CURLE_OK;
381 int rc = 0;
382 LDAPURLDesc *ludp = NULL;
383 int msgid;
384 struct Curl_easy *data = conn->data;
385
386 connkeep(conn, "OpenLDAP do");
387
388 infof(data, "LDAP local: %s\n", data->change.url);
389
390 rc = ldap_url_parse(data->change.url, &ludp);
391 if(rc != LDAP_URL_SUCCESS) {
392 const char *msg = "url parsing problem";
393 status = CURLE_URL_MALFORMAT;
394 if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) {
395 if(rc == LDAP_URL_ERR_MEM)
396 status = CURLE_OUT_OF_MEMORY;
397 msg = url_errs[rc];
398 }
399 failf(conn->data, "LDAP local: %s", msg);
400 return status;
401 }
402
403 rc = ldap_search_ext(li->ld, ludp->lud_dn, ludp->lud_scope,
404 ludp->lud_filter, ludp->lud_attrs, 0,
405 NULL, NULL, NULL, 0, &msgid);
406 ldap_free_urldesc(ludp);
407 if(rc != LDAP_SUCCESS) {
408 failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc));
409 return CURLE_LDAP_SEARCH_FAILED;
410 }
411 lr = calloc(1, sizeof(struct ldapreqinfo));
412 if(!lr)
413 return CURLE_OUT_OF_MEMORY;
414 lr->msgid = msgid;
415 data->req.protop = lr;
416 Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
417 *done = TRUE;
418 return CURLE_OK;
419 }
420
ldap_done(struct connectdata * conn,CURLcode res,bool premature)421 static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
422 bool premature)
423 {
424 struct ldapreqinfo *lr = conn->data->req.protop;
425
426 (void)res;
427 (void)premature;
428
429 if(lr) {
430 /* if there was a search in progress, abandon it */
431 if(lr->msgid) {
432 struct ldapconninfo *li = conn->proto.ldapc;
433 ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL);
434 lr->msgid = 0;
435 }
436 conn->data->req.protop = NULL;
437 free(lr);
438 }
439
440 return CURLE_OK;
441 }
442
ldap_recv(struct connectdata * conn,int sockindex,char * buf,size_t len,CURLcode * err)443 static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
444 size_t len, CURLcode *err)
445 {
446 struct ldapconninfo *li = conn->proto.ldapc;
447 struct Curl_easy *data = conn->data;
448 struct ldapreqinfo *lr = data->req.protop;
449 int rc, ret;
450 LDAPMessage *msg = NULL;
451 LDAPMessage *ent;
452 BerElement *ber = NULL;
453 struct timeval tv = {0, 1};
454
455 (void)len;
456 (void)buf;
457 (void)sockindex;
458
459 rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &msg);
460 if(rc < 0) {
461 failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc));
462 *err = CURLE_RECV_ERROR;
463 return -1;
464 }
465
466 *err = CURLE_AGAIN;
467 ret = -1;
468
469 /* timed out */
470 if(!msg)
471 return ret;
472
473 for(ent = ldap_first_message(li->ld, msg); ent;
474 ent = ldap_next_message(li->ld, ent)) {
475 struct berval bv, *bvals;
476 int binary = 0, msgtype;
477 CURLcode writeerr;
478
479 msgtype = ldap_msgtype(ent);
480 if(msgtype == LDAP_RES_SEARCH_RESULT) {
481 int code;
482 char *info = NULL;
483 rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0);
484 if(rc) {
485 failf(data, "LDAP local: search ldap_parse_result %s",
486 ldap_err2string(rc));
487 *err = CURLE_LDAP_SEARCH_FAILED;
488 }
489 else if(code && code != LDAP_SIZELIMIT_EXCEEDED) {
490 failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc),
491 info ? info : "");
492 *err = CURLE_LDAP_SEARCH_FAILED;
493 }
494 else {
495 /* successful */
496 if(code == LDAP_SIZELIMIT_EXCEEDED)
497 infof(data, "There are more than %d entries\n", lr->nument);
498 data->req.size = data->req.bytecount;
499 *err = CURLE_OK;
500 ret = 0;
501 }
502 lr->msgid = 0;
503 ldap_memfree(info);
504 break;
505 }
506 else if(msgtype != LDAP_RES_SEARCH_ENTRY)
507 continue;
508
509 lr->nument++;
510 rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv);
511 if(rc < 0) {
512 *err = CURLE_RECV_ERROR;
513 return -1;
514 }
515 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
516 if(writeerr) {
517 *err = writeerr;
518 return -1;
519 }
520
521 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
522 bv.bv_len);
523 if(writeerr) {
524 *err = writeerr;
525 return -1;
526 }
527
528 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
529 if(writeerr) {
530 *err = writeerr;
531 return -1;
532 }
533 data->req.bytecount += bv.bv_len + 5;
534
535 for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals);
536 rc == LDAP_SUCCESS;
537 rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals)) {
538 int i;
539
540 if(bv.bv_val == NULL)
541 break;
542
543 if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7))
544 binary = 1;
545 else
546 binary = 0;
547
548 if(bvals == NULL) {
549 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
550 if(writeerr) {
551 *err = writeerr;
552 return -1;
553 }
554 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
555 bv.bv_len);
556 if(writeerr) {
557 *err = writeerr;
558 return -1;
559 }
560 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":\n", 2);
561 if(writeerr) {
562 *err = writeerr;
563 return -1;
564 }
565 data->req.bytecount += bv.bv_len + 3;
566 continue;
567 }
568
569 for(i = 0; bvals[i].bv_val != NULL; i++) {
570 int binval = 0;
571 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
572 if(writeerr) {
573 *err = writeerr;
574 return -1;
575 }
576
577 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
578 bv.bv_len);
579 if(writeerr) {
580 *err = writeerr;
581 return -1;
582 }
583
584 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1);
585 if(writeerr) {
586 *err = writeerr;
587 return -1;
588 }
589 data->req.bytecount += bv.bv_len + 2;
590
591 if(!binary) {
592 /* check for leading or trailing whitespace */
593 if(ISSPACE(bvals[i].bv_val[0]) ||
594 ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1]))
595 binval = 1;
596 else {
597 /* check for unprintable characters */
598 unsigned int j;
599 for(j = 0; j<bvals[i].bv_len; j++)
600 if(!ISPRINT(bvals[i].bv_val[j])) {
601 binval = 1;
602 break;
603 }
604 }
605 }
606 if(binary || binval) {
607 char *val_b64 = NULL;
608 size_t val_b64_sz = 0;
609 /* Binary value, encode to base64. */
610 CURLcode error = Curl_base64_encode(data,
611 bvals[i].bv_val,
612 bvals[i].bv_len,
613 &val_b64,
614 &val_b64_sz);
615 if(error) {
616 ber_memfree(bvals);
617 ber_free(ber, 0);
618 ldap_msgfree(msg);
619 *err = error;
620 return -1;
621 }
622 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY,
623 (char *)": ", 2);
624 if(writeerr) {
625 *err = writeerr;
626 return -1;
627 }
628
629 data->req.bytecount += 2;
630 if(val_b64_sz > 0) {
631 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
632 val_b64_sz);
633 if(writeerr) {
634 *err = writeerr;
635 return -1;
636 }
637 free(val_b64);
638 data->req.bytecount += val_b64_sz;
639 }
640 }
641 else {
642 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1);
643 if(writeerr) {
644 *err = writeerr;
645 return -1;
646 }
647
648 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val,
649 bvals[i].bv_len);
650 if(writeerr) {
651 *err = writeerr;
652 return -1;
653 }
654
655 data->req.bytecount += bvals[i].bv_len + 1;
656 }
657 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
658 if(writeerr) {
659 *err = writeerr;
660 return -1;
661 }
662
663 data->req.bytecount++;
664 }
665 ber_memfree(bvals);
666 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
667 if(writeerr) {
668 *err = writeerr;
669 return -1;
670 }
671 data->req.bytecount++;
672 }
673 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
674 if(writeerr) {
675 *err = writeerr;
676 return -1;
677 }
678 data->req.bytecount++;
679 ber_free(ber, 0);
680 }
681 ldap_msgfree(msg);
682 return ret;
683 }
684
685 #ifdef USE_SSL
686 static int
ldapsb_tls_setup(Sockbuf_IO_Desc * sbiod,void * arg)687 ldapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg)
688 {
689 sbiod->sbiod_pvt = arg;
690 return 0;
691 }
692
693 static int
ldapsb_tls_remove(Sockbuf_IO_Desc * sbiod)694 ldapsb_tls_remove(Sockbuf_IO_Desc *sbiod)
695 {
696 sbiod->sbiod_pvt = NULL;
697 return 0;
698 }
699
700 /* We don't need to do anything because libcurl does it already */
701 static int
ldapsb_tls_close(Sockbuf_IO_Desc * sbiod)702 ldapsb_tls_close(Sockbuf_IO_Desc *sbiod)
703 {
704 (void)sbiod;
705 return 0;
706 }
707
708 static int
ldapsb_tls_ctrl(Sockbuf_IO_Desc * sbiod,int opt,void * arg)709 ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
710 {
711 (void)arg;
712 if(opt == LBER_SB_OPT_DATA_READY) {
713 struct connectdata *conn = sbiod->sbiod_pvt;
714 return Curl_ssl_data_pending(conn, FIRSTSOCKET);
715 }
716 return 0;
717 }
718
719 static ber_slen_t
ldapsb_tls_read(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)720 ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
721 {
722 struct connectdata *conn = sbiod->sbiod_pvt;
723 struct ldapconninfo *li = conn->proto.ldapc;
724 ber_slen_t ret;
725 CURLcode err = CURLE_RECV_ERROR;
726
727 ret = (li->recv)(conn, FIRSTSOCKET, buf, len, &err);
728 if(ret < 0 && err == CURLE_AGAIN) {
729 SET_SOCKERRNO(EWOULDBLOCK);
730 }
731 return ret;
732 }
733
734 static ber_slen_t
ldapsb_tls_write(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)735 ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
736 {
737 struct connectdata *conn = sbiod->sbiod_pvt;
738 struct ldapconninfo *li = conn->proto.ldapc;
739 ber_slen_t ret;
740 CURLcode err = CURLE_SEND_ERROR;
741
742 ret = (li->send)(conn, FIRSTSOCKET, buf, len, &err);
743 if(ret < 0 && err == CURLE_AGAIN) {
744 SET_SOCKERRNO(EWOULDBLOCK);
745 }
746 return ret;
747 }
748
749 static Sockbuf_IO ldapsb_tls =
750 {
751 ldapsb_tls_setup,
752 ldapsb_tls_remove,
753 ldapsb_tls_ctrl,
754 ldapsb_tls_read,
755 ldapsb_tls_write,
756 ldapsb_tls_close
757 };
758 #endif /* USE_SSL */
759
760 #endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */
761