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