Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/curl/lib/openldap.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 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 */ |
