source: asp3_tinet_ecnl_arm/trunk/curl-7.57.0/lib/openldap.c@ 352

Last change on this file since 352 was 352, checked in by coas-nagasima, 6 years ago

arm向けASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 19.6 KB
Line 
1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 2010, 2017, Howard Chu, <hyc@openldap.org>
9 * Copyright (C) 2011 - 2016, 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#ifndef _LDAP_PVT_H
55extern int ldap_pvt_url_scheme2proto(const char *);
56extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url,
57 LDAP **ld);
58#endif
59
60static CURLcode ldap_setup_connection(struct connectdata *conn);
61static CURLcode ldap_do(struct connectdata *conn, bool *done);
62static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool);
63static CURLcode ldap_connect(struct connectdata *conn, bool *done);
64static CURLcode ldap_connecting(struct connectdata *conn, bool *done);
65static CURLcode ldap_disconnect(struct connectdata *conn, bool dead);
66
67static Curl_recv ldap_recv;
68
69/*
70 * LDAP protocol handler.
71 */
72
73const struct Curl_handler Curl_handler_ldap = {
74 "LDAP", /* scheme */
75 ldap_setup_connection, /* setup_connection */
76 ldap_do, /* do_it */
77 ldap_done, /* done */
78 ZERO_NULL, /* do_more */
79 ldap_connect, /* connect_it */
80 ldap_connecting, /* connecting */
81 ZERO_NULL, /* doing */
82 ZERO_NULL, /* proto_getsock */
83 ZERO_NULL, /* doing_getsock */
84 ZERO_NULL, /* domore_getsock */
85 ZERO_NULL, /* perform_getsock */
86 ldap_disconnect, /* disconnect */
87 ZERO_NULL, /* readwrite */
88 ZERO_NULL, /* connection_check */
89 PORT_LDAP, /* defport */
90 CURLPROTO_LDAP, /* protocol */
91 PROTOPT_NONE /* flags */
92};
93
94#ifdef USE_SSL
95/*
96 * LDAPS protocol handler.
97 */
98
99const struct Curl_handler Curl_handler_ldaps = {
100 "LDAPS", /* scheme */
101 ldap_setup_connection, /* setup_connection */
102 ldap_do, /* do_it */
103 ldap_done, /* done */
104 ZERO_NULL, /* do_more */
105 ldap_connect, /* connect_it */
106 ldap_connecting, /* connecting */
107 ZERO_NULL, /* doing */
108 ZERO_NULL, /* proto_getsock */
109 ZERO_NULL, /* doing_getsock */
110 ZERO_NULL, /* domore_getsock */
111 ZERO_NULL, /* perform_getsock */
112 ldap_disconnect, /* disconnect */
113 ZERO_NULL, /* readwrite */
114 ZERO_NULL, /* connection_check */
115 PORT_LDAPS, /* defport */
116 CURLPROTO_LDAP, /* protocol */
117 PROTOPT_SSL /* flags */
118};
119#endif
120
121static const char *url_errs[] = {
122 "success",
123 "out of memory",
124 "bad parameter",
125 "unrecognized scheme",
126 "unbalanced delimiter",
127 "bad URL",
128 "bad host or port",
129 "bad or missing attributes",
130 "bad or missing scope",
131 "bad or missing filter",
132 "bad or missing extensions"
133};
134
135typedef struct ldapconninfo {
136 LDAP *ld;
137 Curl_recv *recv; /* for stacking SSL handler */
138 Curl_send *send;
139 int proto;
140 int msgid;
141 bool ssldone;
142 bool sslinst;
143 bool didbind;
144} ldapconninfo;
145
146typedef struct ldapreqinfo {
147 int msgid;
148 int nument;
149} ldapreqinfo;
150
151static CURLcode ldap_setup_connection(struct connectdata *conn)
152{
153 ldapconninfo *li;
154 LDAPURLDesc *lud;
155 struct Curl_easy *data = conn->data;
156 int rc, proto;
157 CURLcode status;
158
159 rc = ldap_url_parse(data->change.url, &lud);
160 if(rc != LDAP_URL_SUCCESS) {
161 const char *msg = "url parsing problem";
162 status = CURLE_URL_MALFORMAT;
163 if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) {
164 if(rc == LDAP_URL_ERR_MEM)
165 status = CURLE_OUT_OF_MEMORY;
166 msg = url_errs[rc];
167 }
168 failf(conn->data, "LDAP local: %s", msg);
169 return status;
170 }
171 proto = ldap_pvt_url_scheme2proto(lud->lud_scheme);
172 ldap_free_urldesc(lud);
173
174 li = calloc(1, sizeof(ldapconninfo));
175 if(!li)
176 return CURLE_OUT_OF_MEMORY;
177 li->proto = proto;
178 conn->proto.generic = li;
179 connkeep(conn, "OpenLDAP default");
180 /* TODO:
181 * - provide option to choose SASL Binds instead of Simple
182 */
183 return CURLE_OK;
184}
185
186#ifdef USE_SSL
187static Sockbuf_IO ldapsb_tls;
188#endif
189
190static CURLcode ldap_connect(struct connectdata *conn, bool *done)
191{
192 ldapconninfo *li = conn->proto.generic;
193 struct Curl_easy *data = conn->data;
194 int rc, proto = LDAP_VERSION3;
195 char hosturl[1024];
196 char *ptr;
197
198 (void)done;
199
200 strcpy(hosturl, "ldap");
201 ptr = hosturl + 4;
202 if(conn->handler->flags & PROTOPT_SSL)
203 *ptr++ = 's';
204 snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
205 conn->host.name, conn->remote_port);
206
207 rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld);
208 if(rc) {
209 failf(data, "LDAP local: Cannot connect to %s, %s",
210 hosturl, ldap_err2string(rc));
211 return CURLE_COULDNT_CONNECT;
212 }
213
214 ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
215
216#ifdef USE_SSL
217 if(conn->handler->flags & PROTOPT_SSL) {
218 CURLcode result;
219 result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone);
220 if(result)
221 return result;
222 }
223#endif
224
225 return CURLE_OK;
226}
227
228static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
229{
230 ldapconninfo *li = conn->proto.generic;
231 struct Curl_easy *data = conn->data;
232 LDAPMessage *msg = NULL;
233 struct timeval tv = {0, 1}, *tvp;
234 int rc, err;
235 char *info = NULL;
236
237#ifdef USE_SSL
238 if(conn->handler->flags & PROTOPT_SSL) {
239 /* Is the SSL handshake complete yet? */
240 if(!li->ssldone) {
241 CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET,
242 &li->ssldone);
243 if(result || !li->ssldone)
244 return result;
245 }
246
247 /* Have we installed the libcurl SSL handlers into the sockbuf yet? */
248 if(!li->sslinst) {
249 Sockbuf *sb;
250 ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
251 ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, conn);
252 li->sslinst = TRUE;
253 li->recv = conn->recv[FIRSTSOCKET];
254 li->send = conn->send[FIRSTSOCKET];
255 }
256 }
257#endif
258
259 tvp = &tv;
260
261retry:
262 if(!li->didbind) {
263 char *binddn;
264 struct berval passwd;
265
266 if(conn->bits.user_passwd) {
267 binddn = conn->user;
268 passwd.bv_val = conn->passwd;
269 passwd.bv_len = strlen(passwd.bv_val);
270 }
271 else {
272 binddn = NULL;
273 passwd.bv_val = NULL;
274 passwd.bv_len = 0;
275 }
276 rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd,
277 NULL, NULL, &li->msgid);
278 if(rc)
279 return CURLE_LDAP_CANNOT_BIND;
280 li->didbind = TRUE;
281 if(tvp)
282 return CURLE_OK;
283 }
284
285 rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, tvp, &msg);
286 if(rc < 0) {
287 failf(data, "LDAP local: bind ldap_result %s", ldap_err2string(rc));
288 return CURLE_LDAP_CANNOT_BIND;
289 }
290 if(rc == 0) {
291 /* timed out */
292 return CURLE_OK;
293 }
294
295 rc = ldap_parse_result(li->ld, msg, &err, NULL, &info, NULL, NULL, 1);
296 if(rc) {
297 failf(data, "LDAP local: bind ldap_parse_result %s", ldap_err2string(rc));
298 return CURLE_LDAP_CANNOT_BIND;
299 }
300
301 /* Try to fallback to LDAPv2? */
302 if(err == LDAP_PROTOCOL_ERROR) {
303 int proto;
304 ldap_get_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
305 if(proto == LDAP_VERSION3) {
306 if(info) {
307 ldap_memfree(info);
308 info = NULL;
309 }
310 proto = LDAP_VERSION2;
311 ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
312 li->didbind = FALSE;
313 goto retry;
314 }
315 }
316
317 if(err) {
318 failf(data, "LDAP remote: bind failed %s %s", ldap_err2string(rc),
319 info ? info : "");
320 if(info)
321 ldap_memfree(info);
322 return CURLE_LOGIN_DENIED;
323 }
324
325 if(info)
326 ldap_memfree(info);
327 conn->recv[FIRSTSOCKET] = ldap_recv;
328 *done = TRUE;
329
330 return CURLE_OK;
331}
332
333static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection)
334{
335 ldapconninfo *li = conn->proto.generic;
336 (void) dead_connection;
337
338 if(li) {
339 if(li->ld) {
340 ldap_unbind_ext(li->ld, NULL, NULL);
341 li->ld = NULL;
342 }
343 conn->proto.generic = NULL;
344 free(li);
345 }
346 return CURLE_OK;
347}
348
349static CURLcode ldap_do(struct connectdata *conn, bool *done)
350{
351 ldapconninfo *li = conn->proto.generic;
352 ldapreqinfo *lr;
353 CURLcode status = CURLE_OK;
354 int rc = 0;
355 LDAPURLDesc *ludp = NULL;
356 int msgid;
357 struct Curl_easy *data = conn->data;
358
359 connkeep(conn, "OpenLDAP do");
360
361 infof(data, "LDAP local: %s\n", data->change.url);
362
363 rc = ldap_url_parse(data->change.url, &ludp);
364 if(rc != LDAP_URL_SUCCESS) {
365 const char *msg = "url parsing problem";
366 status = CURLE_URL_MALFORMAT;
367 if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) {
368 if(rc == LDAP_URL_ERR_MEM)
369 status = CURLE_OUT_OF_MEMORY;
370 msg = url_errs[rc];
371 }
372 failf(conn->data, "LDAP local: %s", msg);
373 return status;
374 }
375
376 rc = ldap_search_ext(li->ld, ludp->lud_dn, ludp->lud_scope,
377 ludp->lud_filter, ludp->lud_attrs, 0,
378 NULL, NULL, NULL, 0, &msgid);
379 ldap_free_urldesc(ludp);
380 if(rc != LDAP_SUCCESS) {
381 failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc));
382 return CURLE_LDAP_SEARCH_FAILED;
383 }
384 lr = calloc(1, sizeof(ldapreqinfo));
385 if(!lr)
386 return CURLE_OUT_OF_MEMORY;
387 lr->msgid = msgid;
388 data->req.protop = lr;
389 Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
390 *done = TRUE;
391 return CURLE_OK;
392}
393
394static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
395 bool premature)
396{
397 ldapreqinfo *lr = conn->data->req.protop;
398
399 (void)res;
400 (void)premature;
401
402 if(lr) {
403 /* if there was a search in progress, abandon it */
404 if(lr->msgid) {
405 ldapconninfo *li = conn->proto.generic;
406 ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL);
407 lr->msgid = 0;
408 }
409 conn->data->req.protop = NULL;
410 free(lr);
411 }
412
413 return CURLE_OK;
414}
415
416static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
417 size_t len, CURLcode *err)
418{
419 ldapconninfo *li = conn->proto.generic;
420 struct Curl_easy *data = conn->data;
421 ldapreqinfo *lr = data->req.protop;
422 int rc, ret;
423 LDAPMessage *msg = NULL;
424 LDAPMessage *ent;
425 BerElement *ber = NULL;
426 struct timeval tv = {0, 1};
427
428 (void)len;
429 (void)buf;
430 (void)sockindex;
431
432 rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &msg);
433 if(rc < 0) {
434 failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc));
435 *err = CURLE_RECV_ERROR;
436 return -1;
437 }
438
439 *err = CURLE_AGAIN;
440 ret = -1;
441
442 /* timed out */
443 if(!msg)
444 return ret;
445
446 for(ent = ldap_first_message(li->ld, msg); ent;
447 ent = ldap_next_message(li->ld, ent)) {
448 struct berval bv, *bvals, **bvp = &bvals;
449 int binary = 0, msgtype;
450 CURLcode writeerr;
451
452 msgtype = ldap_msgtype(ent);
453 if(msgtype == LDAP_RES_SEARCH_RESULT) {
454 int code;
455 char *info = NULL;
456 rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0);
457 if(rc) {
458 failf(data, "LDAP local: search ldap_parse_result %s",
459 ldap_err2string(rc));
460 *err = CURLE_LDAP_SEARCH_FAILED;
461 }
462 else if(code && code != LDAP_SIZELIMIT_EXCEEDED) {
463 failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc),
464 info ? info : "");
465 *err = CURLE_LDAP_SEARCH_FAILED;
466 }
467 else {
468 /* successful */
469 if(code == LDAP_SIZELIMIT_EXCEEDED)
470 infof(data, "There are more than %d entries\n", lr->nument);
471 data->req.size = data->req.bytecount;
472 *err = CURLE_OK;
473 ret = 0;
474 }
475 lr->msgid = 0;
476 ldap_memfree(info);
477 break;
478 }
479 else if(msgtype != LDAP_RES_SEARCH_ENTRY)
480 continue;
481
482 lr->nument++;
483 rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv);
484 if(rc < 0) {
485 /* TODO: verify that this is really how this return code should be
486 handled */
487 *err = CURLE_RECV_ERROR;
488 return -1;
489 }
490 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
491 if(writeerr) {
492 *err = writeerr;
493 return -1;
494 }
495
496 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
497 bv.bv_len);
498 if(writeerr) {
499 *err = writeerr;
500 return -1;
501 }
502
503 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
504 if(writeerr) {
505 *err = writeerr;
506 return -1;
507 }
508 data->req.bytecount += bv.bv_len + 5;
509
510 for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp);
511 rc == LDAP_SUCCESS;
512 rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) {
513 int i;
514
515 if(bv.bv_val == NULL) break;
516
517 if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7))
518 binary = 1;
519 else
520 binary = 0;
521
522 for(i = 0; bvals[i].bv_val != NULL; i++) {
523 int binval = 0;
524 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
525 if(writeerr) {
526 *err = writeerr;
527 return -1;
528 }
529
530 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
531 bv.bv_len);
532 if(writeerr) {
533 *err = writeerr;
534 return -1;
535 }
536
537 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1);
538 if(writeerr) {
539 *err = writeerr;
540 return -1;
541 }
542 data->req.bytecount += bv.bv_len + 2;
543
544 if(!binary) {
545 /* check for leading or trailing whitespace */
546 if(ISSPACE(bvals[i].bv_val[0]) ||
547 ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1]))
548 binval = 1;
549 else {
550 /* check for unprintable characters */
551 unsigned int j;
552 for(j = 0; j<bvals[i].bv_len; j++)
553 if(!ISPRINT(bvals[i].bv_val[j])) {
554 binval = 1;
555 break;
556 }
557 }
558 }
559 if(binary || binval) {
560 char *val_b64 = NULL;
561 size_t val_b64_sz = 0;
562 /* Binary value, encode to base64. */
563 CURLcode error = Curl_base64_encode(data,
564 bvals[i].bv_val,
565 bvals[i].bv_len,
566 &val_b64,
567 &val_b64_sz);
568 if(error) {
569 ber_memfree(bvals);
570 ber_free(ber, 0);
571 ldap_msgfree(msg);
572 *err = error;
573 return -1;
574 }
575 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY,
576 (char *)": ", 2);
577 if(writeerr) {
578 *err = writeerr;
579 return -1;
580 }
581
582 data->req.bytecount += 2;
583 if(val_b64_sz > 0) {
584 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
585 val_b64_sz);
586 if(writeerr) {
587 *err = writeerr;
588 return -1;
589 }
590 free(val_b64);
591 data->req.bytecount += val_b64_sz;
592 }
593 }
594 else {
595 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1);
596 if(writeerr) {
597 *err = writeerr;
598 return -1;
599 }
600
601 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val,
602 bvals[i].bv_len);
603 if(writeerr) {
604 *err = writeerr;
605 return -1;
606 }
607
608 data->req.bytecount += bvals[i].bv_len + 1;
609 }
610 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
611 if(writeerr) {
612 *err = writeerr;
613 return -1;
614 }
615
616 data->req.bytecount++;
617 }
618 ber_memfree(bvals);
619 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
620 if(writeerr) {
621 *err = writeerr;
622 return -1;
623 }
624 data->req.bytecount++;
625 }
626 writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
627 if(writeerr) {
628 *err = writeerr;
629 return -1;
630 }
631 data->req.bytecount++;
632 ber_free(ber, 0);
633 }
634 ldap_msgfree(msg);
635 return ret;
636}
637
638#ifdef USE_SSL
639static int
640ldapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg)
641{
642 sbiod->sbiod_pvt = arg;
643 return 0;
644}
645
646static int
647ldapsb_tls_remove(Sockbuf_IO_Desc *sbiod)
648{
649 sbiod->sbiod_pvt = NULL;
650 return 0;
651}
652
653/* We don't need to do anything because libcurl does it already */
654static int
655ldapsb_tls_close(Sockbuf_IO_Desc *sbiod)
656{
657 (void)sbiod;
658 return 0;
659}
660
661static int
662ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
663{
664 (void)arg;
665 if(opt == LBER_SB_OPT_DATA_READY) {
666 struct connectdata *conn = sbiod->sbiod_pvt;
667 return Curl_ssl_data_pending(conn, FIRSTSOCKET);
668 }
669 return 0;
670}
671
672static ber_slen_t
673ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
674{
675 struct connectdata *conn = sbiod->sbiod_pvt;
676 ldapconninfo *li = conn->proto.generic;
677 ber_slen_t ret;
678 CURLcode err = CURLE_RECV_ERROR;
679
680 ret = (li->recv)(conn, FIRSTSOCKET, buf, len, &err);
681 if(ret < 0 && err == CURLE_AGAIN) {
682 SET_SOCKERRNO(EWOULDBLOCK);
683 }
684 return ret;
685}
686
687static ber_slen_t
688ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
689{
690 struct connectdata *conn = sbiod->sbiod_pvt;
691 ldapconninfo *li = conn->proto.generic;
692 ber_slen_t ret;
693 CURLcode err = CURLE_SEND_ERROR;
694
695 ret = (li->send)(conn, FIRSTSOCKET, buf, len, &err);
696 if(ret < 0 && err == CURLE_AGAIN) {
697 SET_SOCKERRNO(EWOULDBLOCK);
698 }
699 return ret;
700}
701
702static Sockbuf_IO ldapsb_tls =
703{
704 ldapsb_tls_setup,
705 ldapsb_tls_remove,
706 ldapsb_tls_ctrl,
707 ldapsb_tls_read,
708 ldapsb_tls_write,
709 ldapsb_tls_close
710};
711#endif /* USE_SSL */
712
713#endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */
Note: See TracBrowser for help on using the repository browser.