00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025 #if !defined(CURL_DISABLE_LDAP) && !defined(USE_OPENLDAP)
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifdef USE_WIN32_LDAP
00039 # include <winldap.h>
00040 # ifndef LDAP_VENDOR_NAME
00041 # error Your Platform SDK is NOT sufficient for LDAP support! \
00042 Update your Platform SDK, or disable LDAP support!
00043 # else
00044 # include <winber.h>
00045 # endif
00046 #else
00047 # define LDAP_DEPRECATED 1
00048 # ifdef HAVE_LBER_H
00049 # include <lber.h>
00050 # endif
00051 # include <ldap.h>
00052 # if (defined(HAVE_LDAP_SSL) && defined(HAVE_LDAP_SSL_H))
00053 # include <ldap_ssl.h>
00054 # endif
00055 #endif
00056
00057
00058
00059
00060 #ifdef HAVE_BORINGSSL
00061 # undef X509_NAME
00062 # undef X509_CERT_PAIR
00063 # undef X509_EXTENSIONS
00064 #endif
00065
00066 #include "urldata.h"
00067 #include <curl/curl.h>
00068 #include "sendf.h"
00069 #include "escape.h"
00070 #include "progress.h"
00071 #include "transfer.h"
00072 #include "strcase.h"
00073 #include "strtok.h"
00074 #include "curl_ldap.h"
00075 #include "curl_multibyte.h"
00076 #include "curl_base64.h"
00077 #include "connect.h"
00078
00079 #include "curl_printf.h"
00080 #include "curl_memory.h"
00081 #include "memdebug.h"
00082
00083 #ifndef HAVE_LDAP_URL_PARSE
00084
00085
00086
00087 typedef struct {
00088 char *lud_host;
00089 int lud_port;
00090 #if defined(USE_WIN32_LDAP)
00091 TCHAR *lud_dn;
00092 TCHAR **lud_attrs;
00093 #else
00094 char *lud_dn;
00095 char **lud_attrs;
00096 #endif
00097 int lud_scope;
00098 #if defined(USE_WIN32_LDAP)
00099 TCHAR *lud_filter;
00100 #else
00101 char *lud_filter;
00102 #endif
00103 char **lud_exts;
00104 size_t lud_attrs_dups;
00105
00106
00107 } CURL_LDAPURLDesc;
00108
00109 #undef LDAPURLDesc
00110 #define LDAPURLDesc CURL_LDAPURLDesc
00111
00112 static int _ldap_url_parse(const struct connectdata *conn,
00113 LDAPURLDesc **ludp);
00114 static void _ldap_free_urldesc(LDAPURLDesc *ludp);
00115
00116 #undef ldap_free_urldesc
00117 #define ldap_free_urldesc _ldap_free_urldesc
00118 #endif
00119
00120 #ifdef DEBUG_LDAP
00121 #define LDAP_TRACE(x) do { \
00122 _ldap_trace("%u: ", __LINE__); \
00123 _ldap_trace x; \
00124 } WHILE_FALSE
00125
00126 static void _ldap_trace(const char *fmt, ...);
00127 #else
00128 #define LDAP_TRACE(x) Curl_nop_stmt
00129 #endif
00130
00131
00132 static CURLcode Curl_ldap(struct connectdata *conn, bool *done);
00133
00134
00135
00136
00137
00138 const struct Curl_handler Curl_handler_ldap = {
00139 "LDAP",
00140 ZERO_NULL,
00141 Curl_ldap,
00142 ZERO_NULL,
00143 ZERO_NULL,
00144 ZERO_NULL,
00145 ZERO_NULL,
00146 ZERO_NULL,
00147 ZERO_NULL,
00148 ZERO_NULL,
00149 ZERO_NULL,
00150 ZERO_NULL,
00151 ZERO_NULL,
00152 ZERO_NULL,
00153 PORT_LDAP,
00154 CURLPROTO_LDAP,
00155 PROTOPT_NONE
00156 };
00157
00158 #ifdef HAVE_LDAP_SSL
00159
00160
00161
00162
00163 const struct Curl_handler Curl_handler_ldaps = {
00164 "LDAPS",
00165 ZERO_NULL,
00166 Curl_ldap,
00167 ZERO_NULL,
00168 ZERO_NULL,
00169 ZERO_NULL,
00170 ZERO_NULL,
00171 ZERO_NULL,
00172 ZERO_NULL,
00173 ZERO_NULL,
00174 ZERO_NULL,
00175 ZERO_NULL,
00176 ZERO_NULL,
00177 ZERO_NULL,
00178 PORT_LDAPS,
00179 CURLPROTO_LDAPS,
00180 PROTOPT_SSL
00181 };
00182 #endif
00183
00184
00185 static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
00186 {
00187 CURLcode result = CURLE_OK;
00188 int rc = 0;
00189 LDAP *server = NULL;
00190 LDAPURLDesc *ludp = NULL;
00191 LDAPMessage *ldapmsg = NULL;
00192 LDAPMessage *entryIterator;
00193 int num = 0;
00194 struct Curl_easy *data=conn->data;
00195 int ldap_proto = LDAP_VERSION3;
00196 int ldap_ssl = 0;
00197 char *val_b64 = NULL;
00198 size_t val_b64_sz = 0;
00199 curl_off_t dlsize = 0;
00200 #ifdef LDAP_OPT_NETWORK_TIMEOUT
00201 struct timeval ldap_timeout = {10, 0};
00202 #endif
00203 #if defined(USE_WIN32_LDAP)
00204 TCHAR *host = NULL;
00205 TCHAR *user = NULL;
00206 TCHAR *passwd = NULL;
00207 #else
00208 char *host = NULL;
00209 char *user = NULL;
00210 char *passwd = NULL;
00211 #endif
00212
00213 *done = TRUE;
00214 infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n",
00215 LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
00216 infof(data, "LDAP local: %s\n", data->change.url);
00217
00218 #ifdef HAVE_LDAP_URL_PARSE
00219 rc = ldap_url_parse(data->change.url, &ludp);
00220 #else
00221 rc = _ldap_url_parse(conn, &ludp);
00222 #endif
00223 if(rc != 0) {
00224 failf(data, "LDAP local: %s", ldap_err2string(rc));
00225 result = CURLE_LDAP_INVALID_URL;
00226 goto quit;
00227 }
00228
00229
00230 if(conn->given->flags & PROTOPT_SSL)
00231 ldap_ssl = 1;
00232 infof(data, "LDAP local: trying to establish %s connection\n",
00233 ldap_ssl ? "encrypted" : "cleartext");
00234
00235 #if defined(USE_WIN32_LDAP)
00236 host = Curl_convert_UTF8_to_tchar(conn->host.name);
00237 if(!host) {
00238 result = CURLE_OUT_OF_MEMORY;
00239
00240 goto quit;
00241 }
00242
00243 if(conn->bits.user_passwd) {
00244 user = Curl_convert_UTF8_to_tchar(conn->user);
00245 passwd = Curl_convert_UTF8_to_tchar(conn->passwd);
00246 if(!user || !passwd) {
00247 result = CURLE_OUT_OF_MEMORY;
00248
00249 goto quit;
00250 }
00251 }
00252 #else
00253 host = conn->host.name;
00254
00255 if(conn->bits.user_passwd) {
00256 user = conn->user;
00257 passwd = conn->passwd;
00258 }
00259 #endif
00260
00261 #ifdef LDAP_OPT_NETWORK_TIMEOUT
00262 ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout);
00263 #endif
00264 ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
00265
00266 if(ldap_ssl) {
00267 #ifdef HAVE_LDAP_SSL
00268 #ifdef USE_WIN32_LDAP
00269
00270 server = ldap_sslinit(host, (int)conn->port, 1);
00271 ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
00272 #else
00273 int ldap_option;
00274 char *ldap_ca = conn->ssl_config.CAfile;
00275 #if defined(CURL_HAS_NOVELL_LDAPSDK)
00276 rc = ldapssl_client_init(NULL, NULL);
00277 if(rc != LDAP_SUCCESS) {
00278 failf(data, "LDAP local: ldapssl_client_init %s", ldap_err2string(rc));
00279 result = CURLE_SSL_CERTPROBLEM;
00280 goto quit;
00281 }
00282 if(conn->ssl_config.verifypeer) {
00283
00284 int cert_type = LDAPSSL_CERT_FILETYPE_B64;
00285 if((data->set.ssl.cert_type) &&
00286 (strcasecompare(data->set.ssl.cert_type, "DER")))
00287 cert_type = LDAPSSL_CERT_FILETYPE_DER;
00288 if(!ldap_ca) {
00289 failf(data, "LDAP local: ERROR %s CA cert not set!",
00290 (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"));
00291 result = CURLE_SSL_CERTPROBLEM;
00292 goto quit;
00293 }
00294 infof(data, "LDAP local: using %s CA cert '%s'\n",
00295 (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
00296 ldap_ca);
00297 rc = ldapssl_add_trusted_cert(ldap_ca, cert_type);
00298 if(rc != LDAP_SUCCESS) {
00299 failf(data, "LDAP local: ERROR setting %s CA cert: %s",
00300 (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
00301 ldap_err2string(rc));
00302 result = CURLE_SSL_CERTPROBLEM;
00303 goto quit;
00304 }
00305 ldap_option = LDAPSSL_VERIFY_SERVER;
00306 }
00307 else
00308 ldap_option = LDAPSSL_VERIFY_NONE;
00309 rc = ldapssl_set_verify_mode(ldap_option);
00310 if(rc != LDAP_SUCCESS) {
00311 failf(data, "LDAP local: ERROR setting cert verify mode: %s",
00312 ldap_err2string(rc));
00313 result = CURLE_SSL_CERTPROBLEM;
00314 goto quit;
00315 }
00316 server = ldapssl_init(host, (int)conn->port, 1);
00317 if(server == NULL) {
00318 failf(data, "LDAP local: Cannot connect to %s:%ld",
00319 conn->host.dispname, conn->port);
00320 result = CURLE_COULDNT_CONNECT;
00321 goto quit;
00322 }
00323 #elif defined(LDAP_OPT_X_TLS)
00324 if(conn->ssl_config.verifypeer) {
00325
00326 if((data->set.ssl.cert_type) &&
00327 (!strcasecompare(data->set.ssl.cert_type, "PEM"))) {
00328 failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!");
00329 result = CURLE_SSL_CERTPROBLEM;
00330 goto quit;
00331 }
00332 if(!ldap_ca) {
00333 failf(data, "LDAP local: ERROR PEM CA cert not set!");
00334 result = CURLE_SSL_CERTPROBLEM;
00335 goto quit;
00336 }
00337 infof(data, "LDAP local: using PEM CA cert: %s\n", ldap_ca);
00338 rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca);
00339 if(rc != LDAP_SUCCESS) {
00340 failf(data, "LDAP local: ERROR setting PEM CA cert: %s",
00341 ldap_err2string(rc));
00342 result = CURLE_SSL_CERTPROBLEM;
00343 goto quit;
00344 }
00345 ldap_option = LDAP_OPT_X_TLS_DEMAND;
00346 }
00347 else
00348 ldap_option = LDAP_OPT_X_TLS_NEVER;
00349
00350 rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &ldap_option);
00351 if(rc != LDAP_SUCCESS) {
00352 failf(data, "LDAP local: ERROR setting cert verify mode: %s",
00353 ldap_err2string(rc));
00354 result = CURLE_SSL_CERTPROBLEM;
00355 goto quit;
00356 }
00357 server = ldap_init(host, (int)conn->port);
00358 if(server == NULL) {
00359 failf(data, "LDAP local: Cannot connect to %s:%ld",
00360 conn->host.dispname, conn->port);
00361 result = CURLE_COULDNT_CONNECT;
00362 goto quit;
00363 }
00364 ldap_option = LDAP_OPT_X_TLS_HARD;
00365 rc = ldap_set_option(server, LDAP_OPT_X_TLS, &ldap_option);
00366 if(rc != LDAP_SUCCESS) {
00367 failf(data, "LDAP local: ERROR setting SSL/TLS mode: %s",
00368 ldap_err2string(rc));
00369 result = CURLE_SSL_CERTPROBLEM;
00370 goto quit;
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 #else
00382
00383
00384 failf(data, "LDAP local: SSL/TLS not supported with this version "
00385 "of the OpenLDAP toolkit\n");
00386 result = CURLE_SSL_CERTPROBLEM;
00387 goto quit;
00388 #endif
00389 #endif
00390 #endif
00391 }
00392 else {
00393 server = ldap_init(host, (int)conn->port);
00394 if(server == NULL) {
00395 failf(data, "LDAP local: Cannot connect to %s:%ld",
00396 conn->host.dispname, conn->port);
00397 result = CURLE_COULDNT_CONNECT;
00398 goto quit;
00399 }
00400 }
00401 #ifdef USE_WIN32_LDAP
00402 ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
00403 #endif
00404
00405 rc = ldap_simple_bind_s(server, user, passwd);
00406 if(!ldap_ssl && rc != 0) {
00407 ldap_proto = LDAP_VERSION2;
00408 ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
00409 rc = ldap_simple_bind_s(server, user, passwd);
00410 }
00411 if(rc != 0) {
00412 failf(data, "LDAP local: ldap_simple_bind_s %s", ldap_err2string(rc));
00413 result = CURLE_LDAP_CANNOT_BIND;
00414 goto quit;
00415 }
00416
00417 rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope,
00418 ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg);
00419
00420 if(rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) {
00421 failf(data, "LDAP remote: %s", ldap_err2string(rc));
00422 result = CURLE_LDAP_SEARCH_FAILED;
00423 goto quit;
00424 }
00425
00426 for(num = 0, entryIterator = ldap_first_entry(server, ldapmsg);
00427 entryIterator;
00428 entryIterator = ldap_next_entry(server, entryIterator), num++) {
00429 BerElement *ber = NULL;
00430 #if defined(USE_WIN32_LDAP)
00431 TCHAR *attribute;
00432 #else
00433 char *attribute;
00434 #endif
00435 int i;
00436
00437
00438 {
00439 char *name;
00440 size_t name_len;
00441 #if defined(USE_WIN32_LDAP)
00442 TCHAR *dn = ldap_get_dn(server, entryIterator);
00443 name = Curl_convert_tchar_to_UTF8(dn);
00444 if(!name) {
00445 ldap_memfree(dn);
00446
00447 result = CURLE_OUT_OF_MEMORY;
00448
00449 goto quit;
00450 }
00451 #else
00452 char *dn = name = ldap_get_dn(server, entryIterator);
00453 #endif
00454 name_len = strlen(name);
00455
00456 result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
00457 if(result) {
00458 #if defined(USE_WIN32_LDAP)
00459 Curl_unicodefree(name);
00460 #endif
00461 ldap_memfree(dn);
00462
00463 goto quit;
00464 }
00465
00466 result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *) name,
00467 name_len);
00468 if(result) {
00469 #if defined(USE_WIN32_LDAP)
00470 Curl_unicodefree(name);
00471 #endif
00472 ldap_memfree(dn);
00473
00474 goto quit;
00475 }
00476
00477 result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
00478 if(result) {
00479 #if defined(USE_WIN32_LDAP)
00480 Curl_unicodefree(name);
00481 #endif
00482 ldap_memfree(dn);
00483
00484 goto quit;
00485 }
00486
00487 dlsize += name_len + 5;
00488
00489 #if defined(USE_WIN32_LDAP)
00490 Curl_unicodefree(name);
00491 #endif
00492 ldap_memfree(dn);
00493 }
00494
00495
00496 for(attribute = ldap_first_attribute(server, entryIterator, &ber);
00497 attribute;
00498 attribute = ldap_next_attribute(server, entryIterator, ber)) {
00499 BerValue **vals;
00500 size_t attr_len;
00501 #if defined(USE_WIN32_LDAP)
00502 char *attr = Curl_convert_tchar_to_UTF8(attribute);
00503 if(!attr) {
00504 if(ber)
00505 ber_free(ber, 0);
00506
00507 result = CURLE_OUT_OF_MEMORY;
00508
00509 goto quit;
00510 }
00511 #else
00512 char *attr = attribute;
00513 #endif
00514 attr_len = strlen(attr);
00515
00516 vals = ldap_get_values_len(server, entryIterator, attribute);
00517 if(vals != NULL) {
00518 for(i = 0; (vals[i] != NULL); i++) {
00519 result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
00520 if(result) {
00521 ldap_value_free_len(vals);
00522 #if defined(USE_WIN32_LDAP)
00523 Curl_unicodefree(attr);
00524 #endif
00525 ldap_memfree(attribute);
00526 if(ber)
00527 ber_free(ber, 0);
00528
00529 goto quit;
00530 }
00531
00532 result = Curl_client_write(conn, CLIENTWRITE_BODY,
00533 (char *) attr, attr_len);
00534 if(result) {
00535 ldap_value_free_len(vals);
00536 #if defined(USE_WIN32_LDAP)
00537 Curl_unicodefree(attr);
00538 #endif
00539 ldap_memfree(attribute);
00540 if(ber)
00541 ber_free(ber, 0);
00542
00543 goto quit;
00544 }
00545
00546 result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
00547 if(result) {
00548 ldap_value_free_len(vals);
00549 #if defined(USE_WIN32_LDAP)
00550 Curl_unicodefree(attr);
00551 #endif
00552 ldap_memfree(attribute);
00553 if(ber)
00554 ber_free(ber, 0);
00555
00556 goto quit;
00557 }
00558
00559 dlsize += attr_len + 3;
00560
00561 if((attr_len > 7) &&
00562 (strcmp(";binary", (char *) attr + (attr_len - 7)) == 0)) {
00563
00564 result = Curl_base64_encode(data,
00565 vals[i]->bv_val,
00566 vals[i]->bv_len,
00567 &val_b64,
00568 &val_b64_sz);
00569 if(result) {
00570 ldap_value_free_len(vals);
00571 #if defined(USE_WIN32_LDAP)
00572 Curl_unicodefree(attr);
00573 #endif
00574 ldap_memfree(attribute);
00575 if(ber)
00576 ber_free(ber, 0);
00577
00578 goto quit;
00579 }
00580
00581 if(val_b64_sz > 0) {
00582 result = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
00583 val_b64_sz);
00584 free(val_b64);
00585 if(result) {
00586 ldap_value_free_len(vals);
00587 #if defined(USE_WIN32_LDAP)
00588 Curl_unicodefree(attr);
00589 #endif
00590 ldap_memfree(attribute);
00591 if(ber)
00592 ber_free(ber, 0);
00593
00594 goto quit;
00595 }
00596
00597 dlsize += val_b64_sz;
00598 }
00599 }
00600 else {
00601 result = Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val,
00602 vals[i]->bv_len);
00603 if(result) {
00604 ldap_value_free_len(vals);
00605 #if defined(USE_WIN32_LDAP)
00606 Curl_unicodefree(attr);
00607 #endif
00608 ldap_memfree(attribute);
00609 if(ber)
00610 ber_free(ber, 0);
00611
00612 goto quit;
00613 }
00614
00615 dlsize += vals[i]->bv_len;
00616 }
00617
00618 result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
00619 if(result) {
00620 ldap_value_free_len(vals);
00621 #if defined(USE_WIN32_LDAP)
00622 Curl_unicodefree(attr);
00623 #endif
00624 ldap_memfree(attribute);
00625 if(ber)
00626 ber_free(ber, 0);
00627
00628 goto quit;
00629 }
00630
00631 dlsize++;
00632 }
00633
00634
00635 ldap_value_free_len(vals);
00636 }
00637
00638
00639 #if defined(USE_WIN32_LDAP)
00640 Curl_unicodefree(attr);
00641 #endif
00642 ldap_memfree(attribute);
00643
00644 result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
00645 if(result)
00646 goto quit;
00647 dlsize++;
00648 Curl_pgrsSetDownloadCounter(data, dlsize);
00649 }
00650
00651 if(ber)
00652 ber_free(ber, 0);
00653 }
00654
00655 quit:
00656 if(ldapmsg) {
00657 ldap_msgfree(ldapmsg);
00658 LDAP_TRACE(("Received %d entries\n", num));
00659 }
00660 if(rc == LDAP_SIZELIMIT_EXCEEDED)
00661 infof(data, "There are more than %d entries\n", num);
00662 if(ludp)
00663 ldap_free_urldesc(ludp);
00664 if(server)
00665 ldap_unbind_s(server);
00666 #if defined(HAVE_LDAP_SSL) && defined(CURL_HAS_NOVELL_LDAPSDK)
00667 if(ldap_ssl)
00668 ldapssl_client_deinit();
00669 #endif
00670
00671 #if defined(USE_WIN32_LDAP)
00672 Curl_unicodefree(passwd);
00673 Curl_unicodefree(user);
00674 Curl_unicodefree(host);
00675 #endif
00676
00677
00678 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
00679 connclose(conn, "LDAP connection always disable re-use");
00680
00681 return result;
00682 }
00683
00684 #ifdef DEBUG_LDAP
00685 static void _ldap_trace(const char *fmt, ...)
00686 {
00687 static int do_trace = -1;
00688 va_list args;
00689
00690 if(do_trace == -1) {
00691 const char *env = getenv("CURL_TRACE");
00692 do_trace = (env && strtol(env, NULL, 10) > 0);
00693 }
00694 if(!do_trace)
00695 return;
00696
00697 va_start(args, fmt);
00698 vfprintf(stderr, fmt, args);
00699 va_end(args);
00700 }
00701 #endif
00702
00703 #ifndef HAVE_LDAP_URL_PARSE
00704
00705
00706
00707
00708 static int str2scope(const char *p)
00709 {
00710 if(strcasecompare(p, "one"))
00711 return LDAP_SCOPE_ONELEVEL;
00712 if(strcasecompare(p, "onetree"))
00713 return LDAP_SCOPE_ONELEVEL;
00714 if(strcasecompare(p, "base"))
00715 return LDAP_SCOPE_BASE;
00716 if(strcasecompare(p, "sub"))
00717 return LDAP_SCOPE_SUBTREE;
00718 if(strcasecompare(p, "subtree"))
00719 return LDAP_SCOPE_SUBTREE;
00720 return (-1);
00721 }
00722
00723
00724
00725
00726
00727 static bool split_str(char *str, char ***out, size_t *count)
00728 {
00729 char **res;
00730 char *lasts;
00731 char *s;
00732 size_t i;
00733 size_t items = 1;
00734
00735 s = strchr(str, ',');
00736 while(s) {
00737 items++;
00738 s = strchr(++s, ',');
00739 }
00740
00741 res = calloc(items, sizeof(char *));
00742 if(!res)
00743 return FALSE;
00744
00745 for(i = 0, s = strtok_r(str, ",", &lasts); s && i < items;
00746 s = strtok_r(NULL, ",", &lasts), i++)
00747 res[i] = s;
00748
00749 *out = res;
00750 *count = items;
00751
00752 return TRUE;
00753 }
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769 static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
00770 {
00771 int rc = LDAP_SUCCESS;
00772 char *path;
00773 char *p;
00774 char *q;
00775 size_t i;
00776
00777 if(!conn->data ||
00778 !conn->data->state.path ||
00779 conn->data->state.path[0] != '/' ||
00780 !checkprefix("LDAP", conn->data->change.url))
00781 return LDAP_INVALID_SYNTAX;
00782
00783 ludp->lud_scope = LDAP_SCOPE_BASE;
00784 ludp->lud_port = conn->remote_port;
00785 ludp->lud_host = conn->host.name;
00786
00787
00788 p = path = strdup(conn->data->state.path + 1);
00789 if(!path)
00790 return LDAP_NO_MEMORY;
00791
00792
00793 q = strchr(p, '?');
00794 if(q)
00795 *q++ = '\0';
00796
00797 if(*p) {
00798 char *dn = p;
00799 char *unescaped;
00800 CURLcode result;
00801
00802 LDAP_TRACE(("DN '%s'\n", dn));
00803
00804
00805 result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE);
00806 if(result) {
00807 rc = LDAP_NO_MEMORY;
00808
00809 goto quit;
00810 }
00811
00812 #if defined(USE_WIN32_LDAP)
00813
00814 ludp->lud_dn = Curl_convert_UTF8_to_tchar(unescaped);
00815
00816
00817 Curl_unicodefree(unescaped);
00818
00819 if(!ludp->lud_dn) {
00820 rc = LDAP_NO_MEMORY;
00821
00822 goto quit;
00823 }
00824 #else
00825 ludp->lud_dn = unescaped;
00826 #endif
00827 }
00828
00829 p = q;
00830 if(!p)
00831 goto quit;
00832
00833
00834 q = strchr(p, '?');
00835 if(q)
00836 *q++ = '\0';
00837
00838 if(*p) {
00839 char **attributes;
00840 size_t count = 0;
00841
00842
00843 if(!split_str(p, &attributes, &count)) {
00844 rc = LDAP_NO_MEMORY;
00845
00846 goto quit;
00847 }
00848
00849
00850 #if defined(USE_WIN32_LDAP)
00851 ludp->lud_attrs = calloc(count + 1, sizeof(TCHAR *));
00852 #else
00853 ludp->lud_attrs = calloc(count + 1, sizeof(char *));
00854 #endif
00855 if(!ludp->lud_attrs) {
00856 free(attributes);
00857
00858 rc = LDAP_NO_MEMORY;
00859
00860 goto quit;
00861 }
00862
00863 for(i = 0; i < count; i++) {
00864 char *unescaped;
00865 CURLcode result;
00866
00867 LDAP_TRACE(("attr[%d] '%s'\n", i, attributes[i]));
00868
00869
00870 result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
00871 FALSE);
00872 if(result) {
00873 free(attributes);
00874
00875 rc = LDAP_NO_MEMORY;
00876
00877 goto quit;
00878 }
00879
00880 #if defined(USE_WIN32_LDAP)
00881
00882 ludp->lud_attrs[i] = Curl_convert_UTF8_to_tchar(unescaped);
00883
00884
00885 Curl_unicodefree(unescaped);
00886
00887 if(!ludp->lud_attrs[i]) {
00888 free(attributes);
00889
00890 rc = LDAP_NO_MEMORY;
00891
00892 goto quit;
00893 }
00894 #else
00895 ludp->lud_attrs[i] = unescaped;
00896 #endif
00897
00898 ludp->lud_attrs_dups++;
00899 }
00900
00901 free(attributes);
00902 }
00903
00904 p = q;
00905 if(!p)
00906 goto quit;
00907
00908
00909 q = strchr(p, '?');
00910 if(q)
00911 *q++ = '\0';
00912
00913 if(*p) {
00914 ludp->lud_scope = str2scope(p);
00915 if(ludp->lud_scope == -1) {
00916 rc = LDAP_INVALID_SYNTAX;
00917
00918 goto quit;
00919 }
00920 LDAP_TRACE(("scope %d\n", ludp->lud_scope));
00921 }
00922
00923 p = q;
00924 if(!p)
00925 goto quit;
00926
00927
00928 q = strchr(p, '?');
00929 if(q)
00930 *q++ = '\0';
00931
00932 if(*p) {
00933 char *filter = p;
00934 char *unescaped;
00935 CURLcode result;
00936
00937 LDAP_TRACE(("filter '%s'\n", filter));
00938
00939
00940 result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE);
00941 if(result) {
00942 rc = LDAP_NO_MEMORY;
00943
00944 goto quit;
00945 }
00946
00947 #if defined(USE_WIN32_LDAP)
00948
00949 ludp->lud_filter = Curl_convert_UTF8_to_tchar(unescaped);
00950
00951
00952 Curl_unicodefree(unescaped);
00953
00954 if(!ludp->lud_filter) {
00955 rc = LDAP_NO_MEMORY;
00956
00957 goto quit;
00958 }
00959 #else
00960 ludp->lud_filter = unescaped;
00961 #endif
00962 }
00963
00964 p = q;
00965 if(p && !*p) {
00966 rc = LDAP_INVALID_SYNTAX;
00967
00968 goto quit;
00969 }
00970
00971 quit:
00972 free(path);
00973
00974 return rc;
00975 }
00976
00977 static int _ldap_url_parse(const struct connectdata *conn,
00978 LDAPURLDesc **ludpp)
00979 {
00980 LDAPURLDesc *ludp = calloc(1, sizeof(*ludp));
00981 int rc;
00982
00983 *ludpp = NULL;
00984 if(!ludp)
00985 return LDAP_NO_MEMORY;
00986
00987 rc = _ldap_url_parse2(conn, ludp);
00988 if(rc != LDAP_SUCCESS) {
00989 _ldap_free_urldesc(ludp);
00990 ludp = NULL;
00991 }
00992 *ludpp = ludp;
00993 return (rc);
00994 }
00995
00996 static void _ldap_free_urldesc(LDAPURLDesc *ludp)
00997 {
00998 size_t i;
00999
01000 if(!ludp)
01001 return;
01002
01003 free(ludp->lud_dn);
01004 free(ludp->lud_filter);
01005
01006 if(ludp->lud_attrs) {
01007 for(i = 0; i < ludp->lud_attrs_dups; i++)
01008 free(ludp->lud_attrs[i]);
01009 free(ludp->lud_attrs);
01010 }
01011
01012 free(ludp);
01013 }
01014 #endif
01015 #endif