113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * Copyright (C) Howard Chu, <hyc@openldap.org> 1013498266Sopenharmony_ci * 1113498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1213498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1313498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1413498266Sopenharmony_ci * 1513498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1613498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1713498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1813498266Sopenharmony_ci * 1913498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 2013498266Sopenharmony_ci * KIND, either express or implied. 2113498266Sopenharmony_ci * 2213498266Sopenharmony_ci * SPDX-License-Identifier: curl 2313498266Sopenharmony_ci * 2413498266Sopenharmony_ci ***************************************************************************/ 2513498266Sopenharmony_ci 2613498266Sopenharmony_ci#include "curl_setup.h" 2713498266Sopenharmony_ci 2813498266Sopenharmony_ci#if !defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP) 2913498266Sopenharmony_ci 3013498266Sopenharmony_ci/* 3113498266Sopenharmony_ci * Notice that USE_OPENLDAP is only a source code selection switch. When 3213498266Sopenharmony_ci * libcurl is built with USE_OPENLDAP defined the libcurl source code that 3313498266Sopenharmony_ci * gets compiled is the code from openldap.c, otherwise the code that gets 3413498266Sopenharmony_ci * compiled is the code from ldap.c. 3513498266Sopenharmony_ci * 3613498266Sopenharmony_ci * When USE_OPENLDAP is defined a recent version of the OpenLDAP library 3713498266Sopenharmony_ci * might be required for compilation and runtime. In order to use ancient 3813498266Sopenharmony_ci * OpenLDAP library versions, USE_OPENLDAP shall not be defined. 3913498266Sopenharmony_ci */ 4013498266Sopenharmony_ci 4113498266Sopenharmony_ci#include <ldap.h> 4213498266Sopenharmony_ci 4313498266Sopenharmony_ci#include "urldata.h" 4413498266Sopenharmony_ci#include <curl/curl.h> 4513498266Sopenharmony_ci#include "sendf.h" 4613498266Sopenharmony_ci#include "vtls/vtls.h" 4713498266Sopenharmony_ci#include "transfer.h" 4813498266Sopenharmony_ci#include "curl_ldap.h" 4913498266Sopenharmony_ci#include "curl_base64.h" 5013498266Sopenharmony_ci#include "cfilters.h" 5113498266Sopenharmony_ci#include "connect.h" 5213498266Sopenharmony_ci#include "curl_sasl.h" 5313498266Sopenharmony_ci#include "strcase.h" 5413498266Sopenharmony_ci/* The last 3 #include files should be in this order */ 5513498266Sopenharmony_ci#include "curl_printf.h" 5613498266Sopenharmony_ci#include "curl_memory.h" 5713498266Sopenharmony_ci#include "memdebug.h" 5813498266Sopenharmony_ci 5913498266Sopenharmony_ci/* 6013498266Sopenharmony_ci * Uncommenting this will enable the built-in debug logging of the openldap 6113498266Sopenharmony_ci * library. The debug log level can be set using the CURL_OPENLDAP_TRACE 6213498266Sopenharmony_ci * environment variable. The debug output is written to stderr. 6313498266Sopenharmony_ci * 6413498266Sopenharmony_ci * The library supports the following debug flags: 6513498266Sopenharmony_ci * LDAP_DEBUG_NONE 0x0000 6613498266Sopenharmony_ci * LDAP_DEBUG_TRACE 0x0001 6713498266Sopenharmony_ci * LDAP_DEBUG_CONSTRUCT 0x0002 6813498266Sopenharmony_ci * LDAP_DEBUG_DESTROY 0x0004 6913498266Sopenharmony_ci * LDAP_DEBUG_PARAMETER 0x0008 7013498266Sopenharmony_ci * LDAP_DEBUG_ANY 0xffff 7113498266Sopenharmony_ci * 7213498266Sopenharmony_ci * For example, use CURL_OPENLDAP_TRACE=0 for no debug, 7313498266Sopenharmony_ci * CURL_OPENLDAP_TRACE=2 for LDAP_DEBUG_CONSTRUCT messages only, 7413498266Sopenharmony_ci * CURL_OPENLDAP_TRACE=65535 for all debug message levels. 7513498266Sopenharmony_ci */ 7613498266Sopenharmony_ci/* #define CURL_OPENLDAP_DEBUG */ 7713498266Sopenharmony_ci 7813498266Sopenharmony_ci/* Machine states. */ 7913498266Sopenharmony_citypedef enum { 8013498266Sopenharmony_ci OLDAP_STOP, /* Do nothing state, stops the state machine */ 8113498266Sopenharmony_ci OLDAP_SSL, /* Performing SSL handshake. */ 8213498266Sopenharmony_ci OLDAP_STARTTLS, /* STARTTLS request sent. */ 8313498266Sopenharmony_ci OLDAP_TLS, /* Performing TLS handshake. */ 8413498266Sopenharmony_ci OLDAP_MECHS, /* Get SASL authentication mechanisms. */ 8513498266Sopenharmony_ci OLDAP_SASL, /* SASL binding reply. */ 8613498266Sopenharmony_ci OLDAP_BIND, /* Simple bind reply. */ 8713498266Sopenharmony_ci OLDAP_BINDV2, /* Simple bind reply in protocol version 2. */ 8813498266Sopenharmony_ci OLDAP_LAST /* Never used */ 8913498266Sopenharmony_ci} ldapstate; 9013498266Sopenharmony_ci 9113498266Sopenharmony_ci#ifndef _LDAP_PVT_H 9213498266Sopenharmony_ciextern int ldap_pvt_url_scheme2proto(const char *); 9313498266Sopenharmony_ciextern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, 9413498266Sopenharmony_ci LDAP **ld); 9513498266Sopenharmony_ci#endif 9613498266Sopenharmony_ci 9713498266Sopenharmony_cistatic CURLcode oldap_setup_connection(struct Curl_easy *data, 9813498266Sopenharmony_ci struct connectdata *conn); 9913498266Sopenharmony_cistatic CURLcode oldap_do(struct Curl_easy *data, bool *done); 10013498266Sopenharmony_cistatic CURLcode oldap_done(struct Curl_easy *data, CURLcode, bool); 10113498266Sopenharmony_cistatic CURLcode oldap_connect(struct Curl_easy *data, bool *done); 10213498266Sopenharmony_cistatic CURLcode oldap_connecting(struct Curl_easy *data, bool *done); 10313498266Sopenharmony_cistatic CURLcode oldap_disconnect(struct Curl_easy *data, 10413498266Sopenharmony_ci struct connectdata *conn, bool dead); 10513498266Sopenharmony_ci 10613498266Sopenharmony_cistatic CURLcode oldap_perform_auth(struct Curl_easy *data, const char *mech, 10713498266Sopenharmony_ci const struct bufref *initresp); 10813498266Sopenharmony_cistatic CURLcode oldap_continue_auth(struct Curl_easy *data, const char *mech, 10913498266Sopenharmony_ci const struct bufref *resp); 11013498266Sopenharmony_cistatic CURLcode oldap_cancel_auth(struct Curl_easy *data, const char *mech); 11113498266Sopenharmony_cistatic CURLcode oldap_get_message(struct Curl_easy *data, struct bufref *out); 11213498266Sopenharmony_ci 11313498266Sopenharmony_cistatic Curl_recv oldap_recv; 11413498266Sopenharmony_ci 11513498266Sopenharmony_ci/* 11613498266Sopenharmony_ci * LDAP protocol handler. 11713498266Sopenharmony_ci */ 11813498266Sopenharmony_ci 11913498266Sopenharmony_ciconst struct Curl_handler Curl_handler_ldap = { 12013498266Sopenharmony_ci "LDAP", /* scheme */ 12113498266Sopenharmony_ci oldap_setup_connection, /* setup_connection */ 12213498266Sopenharmony_ci oldap_do, /* do_it */ 12313498266Sopenharmony_ci oldap_done, /* done */ 12413498266Sopenharmony_ci ZERO_NULL, /* do_more */ 12513498266Sopenharmony_ci oldap_connect, /* connect_it */ 12613498266Sopenharmony_ci oldap_connecting, /* connecting */ 12713498266Sopenharmony_ci ZERO_NULL, /* doing */ 12813498266Sopenharmony_ci ZERO_NULL, /* proto_getsock */ 12913498266Sopenharmony_ci ZERO_NULL, /* doing_getsock */ 13013498266Sopenharmony_ci ZERO_NULL, /* domore_getsock */ 13113498266Sopenharmony_ci ZERO_NULL, /* perform_getsock */ 13213498266Sopenharmony_ci oldap_disconnect, /* disconnect */ 13313498266Sopenharmony_ci ZERO_NULL, /* write_resp */ 13413498266Sopenharmony_ci ZERO_NULL, /* connection_check */ 13513498266Sopenharmony_ci ZERO_NULL, /* attach connection */ 13613498266Sopenharmony_ci PORT_LDAP, /* defport */ 13713498266Sopenharmony_ci CURLPROTO_LDAP, /* protocol */ 13813498266Sopenharmony_ci CURLPROTO_LDAP, /* family */ 13913498266Sopenharmony_ci PROTOPT_NONE /* flags */ 14013498266Sopenharmony_ci}; 14113498266Sopenharmony_ci 14213498266Sopenharmony_ci#ifdef USE_SSL 14313498266Sopenharmony_ci/* 14413498266Sopenharmony_ci * LDAPS protocol handler. 14513498266Sopenharmony_ci */ 14613498266Sopenharmony_ci 14713498266Sopenharmony_ciconst struct Curl_handler Curl_handler_ldaps = { 14813498266Sopenharmony_ci "LDAPS", /* scheme */ 14913498266Sopenharmony_ci oldap_setup_connection, /* setup_connection */ 15013498266Sopenharmony_ci oldap_do, /* do_it */ 15113498266Sopenharmony_ci oldap_done, /* done */ 15213498266Sopenharmony_ci ZERO_NULL, /* do_more */ 15313498266Sopenharmony_ci oldap_connect, /* connect_it */ 15413498266Sopenharmony_ci oldap_connecting, /* connecting */ 15513498266Sopenharmony_ci ZERO_NULL, /* doing */ 15613498266Sopenharmony_ci ZERO_NULL, /* proto_getsock */ 15713498266Sopenharmony_ci ZERO_NULL, /* doing_getsock */ 15813498266Sopenharmony_ci ZERO_NULL, /* domore_getsock */ 15913498266Sopenharmony_ci ZERO_NULL, /* perform_getsock */ 16013498266Sopenharmony_ci oldap_disconnect, /* disconnect */ 16113498266Sopenharmony_ci ZERO_NULL, /* write_resp */ 16213498266Sopenharmony_ci ZERO_NULL, /* connection_check */ 16313498266Sopenharmony_ci ZERO_NULL, /* attach connection */ 16413498266Sopenharmony_ci PORT_LDAPS, /* defport */ 16513498266Sopenharmony_ci CURLPROTO_LDAPS, /* protocol */ 16613498266Sopenharmony_ci CURLPROTO_LDAP, /* family */ 16713498266Sopenharmony_ci PROTOPT_SSL /* flags */ 16813498266Sopenharmony_ci}; 16913498266Sopenharmony_ci#endif 17013498266Sopenharmony_ci 17113498266Sopenharmony_ci/* SASL parameters for the ldap protocol */ 17213498266Sopenharmony_cistatic const struct SASLproto saslldap = { 17313498266Sopenharmony_ci "ldap", /* The service name */ 17413498266Sopenharmony_ci oldap_perform_auth, /* Send authentication command */ 17513498266Sopenharmony_ci oldap_continue_auth, /* Send authentication continuation */ 17613498266Sopenharmony_ci oldap_cancel_auth, /* Send authentication cancellation */ 17713498266Sopenharmony_ci oldap_get_message, /* Get SASL response message */ 17813498266Sopenharmony_ci 0, /* Maximum initial response length (no max) */ 17913498266Sopenharmony_ci LDAP_SASL_BIND_IN_PROGRESS, /* Code received when continuation is expected */ 18013498266Sopenharmony_ci LDAP_SUCCESS, /* Code to receive upon authentication success */ 18113498266Sopenharmony_ci SASL_AUTH_NONE, /* Default mechanisms */ 18213498266Sopenharmony_ci 0 /* Configuration flags */ 18313498266Sopenharmony_ci}; 18413498266Sopenharmony_ci 18513498266Sopenharmony_cistruct ldapconninfo { 18613498266Sopenharmony_ci struct SASL sasl; /* SASL-related parameters */ 18713498266Sopenharmony_ci LDAP *ld; /* Openldap connection handle. */ 18813498266Sopenharmony_ci Curl_recv *recv; /* For stacking SSL handler */ 18913498266Sopenharmony_ci Curl_send *send; 19013498266Sopenharmony_ci struct berval *servercred; /* SASL data from server. */ 19113498266Sopenharmony_ci ldapstate state; /* Current machine state. */ 19213498266Sopenharmony_ci int proto; /* LDAP_PROTO_TCP/LDAP_PROTO_UDP/LDAP_PROTO_IPC */ 19313498266Sopenharmony_ci int msgid; /* Current message id. */ 19413498266Sopenharmony_ci}; 19513498266Sopenharmony_ci 19613498266Sopenharmony_cistruct ldapreqinfo { 19713498266Sopenharmony_ci int msgid; 19813498266Sopenharmony_ci int nument; 19913498266Sopenharmony_ci}; 20013498266Sopenharmony_ci 20113498266Sopenharmony_ci/* 20213498266Sopenharmony_ci * oldap_state() 20313498266Sopenharmony_ci * 20413498266Sopenharmony_ci * This is the ONLY way to change LDAP state! 20513498266Sopenharmony_ci */ 20613498266Sopenharmony_cistatic void oldap_state(struct Curl_easy *data, ldapstate newstate) 20713498266Sopenharmony_ci{ 20813498266Sopenharmony_ci struct ldapconninfo *ldapc = data->conn->proto.ldapc; 20913498266Sopenharmony_ci 21013498266Sopenharmony_ci#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) 21113498266Sopenharmony_ci /* for debug purposes */ 21213498266Sopenharmony_ci static const char * const names[] = { 21313498266Sopenharmony_ci "STOP", 21413498266Sopenharmony_ci "SSL", 21513498266Sopenharmony_ci "STARTTLS", 21613498266Sopenharmony_ci "TLS", 21713498266Sopenharmony_ci "MECHS", 21813498266Sopenharmony_ci "SASL", 21913498266Sopenharmony_ci "BIND", 22013498266Sopenharmony_ci "BINDV2", 22113498266Sopenharmony_ci /* LAST */ 22213498266Sopenharmony_ci }; 22313498266Sopenharmony_ci 22413498266Sopenharmony_ci if(ldapc->state != newstate) 22513498266Sopenharmony_ci infof(data, "LDAP %p state change from %s to %s", 22613498266Sopenharmony_ci (void *)ldapc, names[ldapc->state], names[newstate]); 22713498266Sopenharmony_ci#endif 22813498266Sopenharmony_ci 22913498266Sopenharmony_ci ldapc->state = newstate; 23013498266Sopenharmony_ci} 23113498266Sopenharmony_ci 23213498266Sopenharmony_ci/* Map some particular LDAP error codes to CURLcode values. */ 23313498266Sopenharmony_cistatic CURLcode oldap_map_error(int rc, CURLcode result) 23413498266Sopenharmony_ci{ 23513498266Sopenharmony_ci switch(rc) { 23613498266Sopenharmony_ci case LDAP_NO_MEMORY: 23713498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 23813498266Sopenharmony_ci break; 23913498266Sopenharmony_ci case LDAP_INVALID_CREDENTIALS: 24013498266Sopenharmony_ci result = CURLE_LOGIN_DENIED; 24113498266Sopenharmony_ci break; 24213498266Sopenharmony_ci case LDAP_PROTOCOL_ERROR: 24313498266Sopenharmony_ci result = CURLE_UNSUPPORTED_PROTOCOL; 24413498266Sopenharmony_ci break; 24513498266Sopenharmony_ci case LDAP_INSUFFICIENT_ACCESS: 24613498266Sopenharmony_ci result = CURLE_REMOTE_ACCESS_DENIED; 24713498266Sopenharmony_ci break; 24813498266Sopenharmony_ci } 24913498266Sopenharmony_ci return result; 25013498266Sopenharmony_ci} 25113498266Sopenharmony_ci 25213498266Sopenharmony_cistatic CURLcode oldap_url_parse(struct Curl_easy *data, LDAPURLDesc **ludp) 25313498266Sopenharmony_ci{ 25413498266Sopenharmony_ci CURLcode result = CURLE_OK; 25513498266Sopenharmony_ci int rc = LDAP_URL_ERR_BADURL; 25613498266Sopenharmony_ci static const char * const url_errs[] = { 25713498266Sopenharmony_ci "success", 25813498266Sopenharmony_ci "out of memory", 25913498266Sopenharmony_ci "bad parameter", 26013498266Sopenharmony_ci "unrecognized scheme", 26113498266Sopenharmony_ci "unbalanced delimiter", 26213498266Sopenharmony_ci "bad URL", 26313498266Sopenharmony_ci "bad host or port", 26413498266Sopenharmony_ci "bad or missing attributes", 26513498266Sopenharmony_ci "bad or missing scope", 26613498266Sopenharmony_ci "bad or missing filter", 26713498266Sopenharmony_ci "bad or missing extensions" 26813498266Sopenharmony_ci }; 26913498266Sopenharmony_ci 27013498266Sopenharmony_ci *ludp = NULL; 27113498266Sopenharmony_ci if(!data->state.up.user && !data->state.up.password && 27213498266Sopenharmony_ci !data->state.up.options) 27313498266Sopenharmony_ci rc = ldap_url_parse(data->state.url, ludp); 27413498266Sopenharmony_ci if(rc != LDAP_URL_SUCCESS) { 27513498266Sopenharmony_ci const char *msg = "url parsing problem"; 27613498266Sopenharmony_ci 27713498266Sopenharmony_ci result = rc == LDAP_URL_ERR_MEM? CURLE_OUT_OF_MEMORY: CURLE_URL_MALFORMAT; 27813498266Sopenharmony_ci rc -= LDAP_URL_SUCCESS; 27913498266Sopenharmony_ci if((size_t) rc < sizeof(url_errs) / sizeof(url_errs[0])) 28013498266Sopenharmony_ci msg = url_errs[rc]; 28113498266Sopenharmony_ci failf(data, "LDAP local: %s", msg); 28213498266Sopenharmony_ci } 28313498266Sopenharmony_ci return result; 28413498266Sopenharmony_ci} 28513498266Sopenharmony_ci 28613498266Sopenharmony_ci/* Parse the login options. */ 28713498266Sopenharmony_cistatic CURLcode oldap_parse_login_options(struct connectdata *conn) 28813498266Sopenharmony_ci{ 28913498266Sopenharmony_ci CURLcode result = CURLE_OK; 29013498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 29113498266Sopenharmony_ci const char *ptr = conn->options; 29213498266Sopenharmony_ci 29313498266Sopenharmony_ci while(!result && ptr && *ptr) { 29413498266Sopenharmony_ci const char *key = ptr; 29513498266Sopenharmony_ci const char *value; 29613498266Sopenharmony_ci 29713498266Sopenharmony_ci while(*ptr && *ptr != '=') 29813498266Sopenharmony_ci ptr++; 29913498266Sopenharmony_ci 30013498266Sopenharmony_ci value = ptr + 1; 30113498266Sopenharmony_ci 30213498266Sopenharmony_ci while(*ptr && *ptr != ';') 30313498266Sopenharmony_ci ptr++; 30413498266Sopenharmony_ci 30513498266Sopenharmony_ci if(checkprefix("AUTH=", key)) 30613498266Sopenharmony_ci result = Curl_sasl_parse_url_auth_option(&li->sasl, value, ptr - value); 30713498266Sopenharmony_ci else 30813498266Sopenharmony_ci result = CURLE_SETOPT_OPTION_SYNTAX; 30913498266Sopenharmony_ci 31013498266Sopenharmony_ci if(*ptr == ';') 31113498266Sopenharmony_ci ptr++; 31213498266Sopenharmony_ci } 31313498266Sopenharmony_ci 31413498266Sopenharmony_ci return result == CURLE_URL_MALFORMAT? CURLE_SETOPT_OPTION_SYNTAX: result; 31513498266Sopenharmony_ci} 31613498266Sopenharmony_ci 31713498266Sopenharmony_cistatic CURLcode oldap_setup_connection(struct Curl_easy *data, 31813498266Sopenharmony_ci struct connectdata *conn) 31913498266Sopenharmony_ci{ 32013498266Sopenharmony_ci CURLcode result; 32113498266Sopenharmony_ci LDAPURLDesc *lud; 32213498266Sopenharmony_ci (void)conn; 32313498266Sopenharmony_ci 32413498266Sopenharmony_ci /* Early URL syntax check. */ 32513498266Sopenharmony_ci result = oldap_url_parse(data, &lud); 32613498266Sopenharmony_ci ldap_free_urldesc(lud); 32713498266Sopenharmony_ci 32813498266Sopenharmony_ci return result; 32913498266Sopenharmony_ci} 33013498266Sopenharmony_ci 33113498266Sopenharmony_ci/* 33213498266Sopenharmony_ci * Get the SASL authentication challenge from the server credential buffer. 33313498266Sopenharmony_ci */ 33413498266Sopenharmony_cistatic CURLcode oldap_get_message(struct Curl_easy *data, struct bufref *out) 33513498266Sopenharmony_ci{ 33613498266Sopenharmony_ci struct berval *servercred = data->conn->proto.ldapc->servercred; 33713498266Sopenharmony_ci 33813498266Sopenharmony_ci if(!servercred || !servercred->bv_val) 33913498266Sopenharmony_ci return CURLE_WEIRD_SERVER_REPLY; 34013498266Sopenharmony_ci Curl_bufref_set(out, servercred->bv_val, servercred->bv_len, NULL); 34113498266Sopenharmony_ci return CURLE_OK; 34213498266Sopenharmony_ci} 34313498266Sopenharmony_ci 34413498266Sopenharmony_ci/* 34513498266Sopenharmony_ci * Sends an initial SASL bind request to the server. 34613498266Sopenharmony_ci */ 34713498266Sopenharmony_cistatic CURLcode oldap_perform_auth(struct Curl_easy *data, const char *mech, 34813498266Sopenharmony_ci const struct bufref *initresp) 34913498266Sopenharmony_ci{ 35013498266Sopenharmony_ci struct connectdata *conn = data->conn; 35113498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 35213498266Sopenharmony_ci CURLcode result = CURLE_OK; 35313498266Sopenharmony_ci struct berval cred; 35413498266Sopenharmony_ci struct berval *pcred = &cred; 35513498266Sopenharmony_ci int rc; 35613498266Sopenharmony_ci 35713498266Sopenharmony_ci cred.bv_val = (char *) Curl_bufref_ptr(initresp); 35813498266Sopenharmony_ci cred.bv_len = Curl_bufref_len(initresp); 35913498266Sopenharmony_ci if(!cred.bv_val) 36013498266Sopenharmony_ci pcred = NULL; 36113498266Sopenharmony_ci rc = ldap_sasl_bind(li->ld, NULL, mech, pcred, NULL, NULL, &li->msgid); 36213498266Sopenharmony_ci if(rc != LDAP_SUCCESS) 36313498266Sopenharmony_ci result = oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND); 36413498266Sopenharmony_ci return result; 36513498266Sopenharmony_ci} 36613498266Sopenharmony_ci 36713498266Sopenharmony_ci/* 36813498266Sopenharmony_ci * Sends SASL continuation. 36913498266Sopenharmony_ci */ 37013498266Sopenharmony_cistatic CURLcode oldap_continue_auth(struct Curl_easy *data, const char *mech, 37113498266Sopenharmony_ci const struct bufref *resp) 37213498266Sopenharmony_ci{ 37313498266Sopenharmony_ci struct connectdata *conn = data->conn; 37413498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 37513498266Sopenharmony_ci CURLcode result = CURLE_OK; 37613498266Sopenharmony_ci struct berval cred; 37713498266Sopenharmony_ci struct berval *pcred = &cred; 37813498266Sopenharmony_ci int rc; 37913498266Sopenharmony_ci 38013498266Sopenharmony_ci cred.bv_val = (char *) Curl_bufref_ptr(resp); 38113498266Sopenharmony_ci cred.bv_len = Curl_bufref_len(resp); 38213498266Sopenharmony_ci if(!cred.bv_val) 38313498266Sopenharmony_ci pcred = NULL; 38413498266Sopenharmony_ci rc = ldap_sasl_bind(li->ld, NULL, mech, pcred, NULL, NULL, &li->msgid); 38513498266Sopenharmony_ci if(rc != LDAP_SUCCESS) 38613498266Sopenharmony_ci result = oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND); 38713498266Sopenharmony_ci return result; 38813498266Sopenharmony_ci} 38913498266Sopenharmony_ci 39013498266Sopenharmony_ci/* 39113498266Sopenharmony_ci * Sends SASL bind cancellation. 39213498266Sopenharmony_ci */ 39313498266Sopenharmony_cistatic CURLcode oldap_cancel_auth(struct Curl_easy *data, const char *mech) 39413498266Sopenharmony_ci{ 39513498266Sopenharmony_ci struct ldapconninfo *li = data->conn->proto.ldapc; 39613498266Sopenharmony_ci CURLcode result = CURLE_OK; 39713498266Sopenharmony_ci int rc = ldap_sasl_bind(li->ld, NULL, LDAP_SASL_NULL, NULL, NULL, NULL, 39813498266Sopenharmony_ci &li->msgid); 39913498266Sopenharmony_ci 40013498266Sopenharmony_ci (void)mech; 40113498266Sopenharmony_ci if(rc != LDAP_SUCCESS) 40213498266Sopenharmony_ci result = oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND); 40313498266Sopenharmony_ci return result; 40413498266Sopenharmony_ci} 40513498266Sopenharmony_ci 40613498266Sopenharmony_ci/* Starts LDAP simple bind. */ 40713498266Sopenharmony_cistatic CURLcode oldap_perform_bind(struct Curl_easy *data, ldapstate newstate) 40813498266Sopenharmony_ci{ 40913498266Sopenharmony_ci CURLcode result = CURLE_OK; 41013498266Sopenharmony_ci struct connectdata *conn = data->conn; 41113498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 41213498266Sopenharmony_ci char *binddn = NULL; 41313498266Sopenharmony_ci struct berval passwd; 41413498266Sopenharmony_ci int rc; 41513498266Sopenharmony_ci 41613498266Sopenharmony_ci passwd.bv_val = NULL; 41713498266Sopenharmony_ci passwd.bv_len = 0; 41813498266Sopenharmony_ci 41913498266Sopenharmony_ci if(data->state.aptr.user) { 42013498266Sopenharmony_ci binddn = conn->user; 42113498266Sopenharmony_ci passwd.bv_val = conn->passwd; 42213498266Sopenharmony_ci passwd.bv_len = strlen(passwd.bv_val); 42313498266Sopenharmony_ci } 42413498266Sopenharmony_ci 42513498266Sopenharmony_ci rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd, 42613498266Sopenharmony_ci NULL, NULL, &li->msgid); 42713498266Sopenharmony_ci if(rc == LDAP_SUCCESS) 42813498266Sopenharmony_ci oldap_state(data, newstate); 42913498266Sopenharmony_ci else 43013498266Sopenharmony_ci result = oldap_map_error(rc, 43113498266Sopenharmony_ci data->state.aptr.user? 43213498266Sopenharmony_ci CURLE_LOGIN_DENIED: CURLE_LDAP_CANNOT_BIND); 43313498266Sopenharmony_ci return result; 43413498266Sopenharmony_ci} 43513498266Sopenharmony_ci 43613498266Sopenharmony_ci/* Query the supported SASL authentication mechanisms. */ 43713498266Sopenharmony_cistatic CURLcode oldap_perform_mechs(struct Curl_easy *data) 43813498266Sopenharmony_ci{ 43913498266Sopenharmony_ci CURLcode result = CURLE_OK; 44013498266Sopenharmony_ci struct ldapconninfo *li = data->conn->proto.ldapc; 44113498266Sopenharmony_ci int rc; 44213498266Sopenharmony_ci static const char * const supportedSASLMechanisms[] = { 44313498266Sopenharmony_ci "supportedSASLMechanisms", 44413498266Sopenharmony_ci NULL 44513498266Sopenharmony_ci }; 44613498266Sopenharmony_ci 44713498266Sopenharmony_ci rc = ldap_search_ext(li->ld, "", LDAP_SCOPE_BASE, "(objectclass=*)", 44813498266Sopenharmony_ci (char **) supportedSASLMechanisms, 0, 44913498266Sopenharmony_ci NULL, NULL, NULL, 0, &li->msgid); 45013498266Sopenharmony_ci if(rc == LDAP_SUCCESS) 45113498266Sopenharmony_ci oldap_state(data, OLDAP_MECHS); 45213498266Sopenharmony_ci else 45313498266Sopenharmony_ci result = oldap_map_error(rc, CURLE_LOGIN_DENIED); 45413498266Sopenharmony_ci return result; 45513498266Sopenharmony_ci} 45613498266Sopenharmony_ci 45713498266Sopenharmony_ci/* Starts SASL bind. */ 45813498266Sopenharmony_cistatic CURLcode oldap_perform_sasl(struct Curl_easy *data) 45913498266Sopenharmony_ci{ 46013498266Sopenharmony_ci saslprogress progress = SASL_IDLE; 46113498266Sopenharmony_ci struct ldapconninfo *li = data->conn->proto.ldapc; 46213498266Sopenharmony_ci CURLcode result = Curl_sasl_start(&li->sasl, data, TRUE, &progress); 46313498266Sopenharmony_ci 46413498266Sopenharmony_ci oldap_state(data, OLDAP_SASL); 46513498266Sopenharmony_ci if(!result && progress != SASL_INPROGRESS) 46613498266Sopenharmony_ci result = CURLE_LOGIN_DENIED; 46713498266Sopenharmony_ci return result; 46813498266Sopenharmony_ci} 46913498266Sopenharmony_ci 47013498266Sopenharmony_ci#ifdef USE_SSL 47113498266Sopenharmony_cistatic Sockbuf_IO ldapsb_tls; 47213498266Sopenharmony_ci 47313498266Sopenharmony_cistatic bool ssl_installed(struct connectdata *conn) 47413498266Sopenharmony_ci{ 47513498266Sopenharmony_ci return conn->proto.ldapc->recv != NULL; 47613498266Sopenharmony_ci} 47713498266Sopenharmony_ci 47813498266Sopenharmony_cistatic CURLcode oldap_ssl_connect(struct Curl_easy *data, ldapstate newstate) 47913498266Sopenharmony_ci{ 48013498266Sopenharmony_ci CURLcode result = CURLE_OK; 48113498266Sopenharmony_ci struct connectdata *conn = data->conn; 48213498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 48313498266Sopenharmony_ci bool ssldone = 0; 48413498266Sopenharmony_ci 48513498266Sopenharmony_ci result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone); 48613498266Sopenharmony_ci if(!result) { 48713498266Sopenharmony_ci oldap_state(data, newstate); 48813498266Sopenharmony_ci 48913498266Sopenharmony_ci if(ssldone) { 49013498266Sopenharmony_ci Sockbuf *sb; 49113498266Sopenharmony_ci 49213498266Sopenharmony_ci /* Install the libcurl SSL handlers into the sockbuf. */ 49313498266Sopenharmony_ci ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb); 49413498266Sopenharmony_ci ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data); 49513498266Sopenharmony_ci li->recv = conn->recv[FIRSTSOCKET]; 49613498266Sopenharmony_ci li->send = conn->send[FIRSTSOCKET]; 49713498266Sopenharmony_ci } 49813498266Sopenharmony_ci } 49913498266Sopenharmony_ci 50013498266Sopenharmony_ci return result; 50113498266Sopenharmony_ci} 50213498266Sopenharmony_ci 50313498266Sopenharmony_ci/* Send the STARTTLS request */ 50413498266Sopenharmony_cistatic CURLcode oldap_perform_starttls(struct Curl_easy *data) 50513498266Sopenharmony_ci{ 50613498266Sopenharmony_ci CURLcode result = CURLE_OK; 50713498266Sopenharmony_ci struct ldapconninfo *li = data->conn->proto.ldapc; 50813498266Sopenharmony_ci int rc = ldap_start_tls(li->ld, NULL, NULL, &li->msgid); 50913498266Sopenharmony_ci 51013498266Sopenharmony_ci if(rc == LDAP_SUCCESS) 51113498266Sopenharmony_ci oldap_state(data, OLDAP_STARTTLS); 51213498266Sopenharmony_ci else 51313498266Sopenharmony_ci result = oldap_map_error(rc, CURLE_USE_SSL_FAILED); 51413498266Sopenharmony_ci return result; 51513498266Sopenharmony_ci} 51613498266Sopenharmony_ci#endif 51713498266Sopenharmony_ci 51813498266Sopenharmony_cistatic CURLcode oldap_connect(struct Curl_easy *data, bool *done) 51913498266Sopenharmony_ci{ 52013498266Sopenharmony_ci struct connectdata *conn = data->conn; 52113498266Sopenharmony_ci struct ldapconninfo *li; 52213498266Sopenharmony_ci static const int version = LDAP_VERSION3; 52313498266Sopenharmony_ci int rc; 52413498266Sopenharmony_ci char *hosturl; 52513498266Sopenharmony_ci#ifdef CURL_OPENLDAP_DEBUG 52613498266Sopenharmony_ci static int do_trace = -1; 52713498266Sopenharmony_ci#endif 52813498266Sopenharmony_ci 52913498266Sopenharmony_ci (void)done; 53013498266Sopenharmony_ci 53113498266Sopenharmony_ci DEBUGASSERT(!conn->proto.ldapc); 53213498266Sopenharmony_ci li = calloc(1, sizeof(struct ldapconninfo)); 53313498266Sopenharmony_ci if(!li) 53413498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 53513498266Sopenharmony_ci else { 53613498266Sopenharmony_ci CURLcode result; 53713498266Sopenharmony_ci li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme); 53813498266Sopenharmony_ci conn->proto.ldapc = li; 53913498266Sopenharmony_ci 54013498266Sopenharmony_ci /* Initialize the SASL storage */ 54113498266Sopenharmony_ci Curl_sasl_init(&li->sasl, data, &saslldap); 54213498266Sopenharmony_ci 54313498266Sopenharmony_ci /* Clear the TLS upgraded flag */ 54413498266Sopenharmony_ci conn->bits.tls_upgraded = FALSE; 54513498266Sopenharmony_ci 54613498266Sopenharmony_ci result = oldap_parse_login_options(conn); 54713498266Sopenharmony_ci if(result) 54813498266Sopenharmony_ci return result; 54913498266Sopenharmony_ci } 55013498266Sopenharmony_ci 55113498266Sopenharmony_ci hosturl = aprintf("ldap%s://%s:%d", 55213498266Sopenharmony_ci conn->handler->flags & PROTOPT_SSL? "s": "", 55313498266Sopenharmony_ci conn->host.name, conn->remote_port); 55413498266Sopenharmony_ci if(!hosturl) 55513498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 55613498266Sopenharmony_ci 55713498266Sopenharmony_ci rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld); 55813498266Sopenharmony_ci if(rc) { 55913498266Sopenharmony_ci failf(data, "LDAP local: Cannot connect to %s, %s", 56013498266Sopenharmony_ci hosturl, ldap_err2string(rc)); 56113498266Sopenharmony_ci free(hosturl); 56213498266Sopenharmony_ci return CURLE_COULDNT_CONNECT; 56313498266Sopenharmony_ci } 56413498266Sopenharmony_ci 56513498266Sopenharmony_ci free(hosturl); 56613498266Sopenharmony_ci 56713498266Sopenharmony_ci#ifdef CURL_OPENLDAP_DEBUG 56813498266Sopenharmony_ci if(do_trace < 0) { 56913498266Sopenharmony_ci const char *env = getenv("CURL_OPENLDAP_TRACE"); 57013498266Sopenharmony_ci do_trace = (env && strtol(env, NULL, 10) > 0); 57113498266Sopenharmony_ci } 57213498266Sopenharmony_ci if(do_trace) 57313498266Sopenharmony_ci ldap_set_option(li->ld, LDAP_OPT_DEBUG_LEVEL, &do_trace); 57413498266Sopenharmony_ci#endif 57513498266Sopenharmony_ci 57613498266Sopenharmony_ci /* Try version 3 first. */ 57713498266Sopenharmony_ci ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &version); 57813498266Sopenharmony_ci 57913498266Sopenharmony_ci /* Do not chase referrals. */ 58013498266Sopenharmony_ci ldap_set_option(li->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 58113498266Sopenharmony_ci 58213498266Sopenharmony_ci#ifdef USE_SSL 58313498266Sopenharmony_ci if(conn->handler->flags & PROTOPT_SSL) 58413498266Sopenharmony_ci return oldap_ssl_connect(data, OLDAP_SSL); 58513498266Sopenharmony_ci 58613498266Sopenharmony_ci if(data->set.use_ssl) { 58713498266Sopenharmony_ci CURLcode result = oldap_perform_starttls(data); 58813498266Sopenharmony_ci 58913498266Sopenharmony_ci if(!result || data->set.use_ssl != CURLUSESSL_TRY) 59013498266Sopenharmony_ci return result; 59113498266Sopenharmony_ci } 59213498266Sopenharmony_ci#endif 59313498266Sopenharmony_ci 59413498266Sopenharmony_ci if(li->sasl.prefmech != SASL_AUTH_NONE) 59513498266Sopenharmony_ci return oldap_perform_mechs(data); 59613498266Sopenharmony_ci 59713498266Sopenharmony_ci /* Force bind even if anonymous bind is not needed in protocol version 3 59813498266Sopenharmony_ci to detect missing version 3 support. */ 59913498266Sopenharmony_ci return oldap_perform_bind(data, OLDAP_BIND); 60013498266Sopenharmony_ci} 60113498266Sopenharmony_ci 60213498266Sopenharmony_ci/* Handle the supported SASL mechanisms query response */ 60313498266Sopenharmony_cistatic CURLcode oldap_state_mechs_resp(struct Curl_easy *data, 60413498266Sopenharmony_ci LDAPMessage *msg, int code) 60513498266Sopenharmony_ci{ 60613498266Sopenharmony_ci struct connectdata *conn = data->conn; 60713498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 60813498266Sopenharmony_ci int rc; 60913498266Sopenharmony_ci BerElement *ber = NULL; 61013498266Sopenharmony_ci CURLcode result = CURLE_OK; 61113498266Sopenharmony_ci struct berval bv, *bvals; 61213498266Sopenharmony_ci 61313498266Sopenharmony_ci switch(ldap_msgtype(msg)) { 61413498266Sopenharmony_ci case LDAP_RES_SEARCH_ENTRY: 61513498266Sopenharmony_ci /* Got a list of supported SASL mechanisms. */ 61613498266Sopenharmony_ci if(code != LDAP_SUCCESS && code != LDAP_NO_RESULTS_RETURNED) 61713498266Sopenharmony_ci return CURLE_LOGIN_DENIED; 61813498266Sopenharmony_ci 61913498266Sopenharmony_ci rc = ldap_get_dn_ber(li->ld, msg, &ber, &bv); 62013498266Sopenharmony_ci if(rc < 0) 62113498266Sopenharmony_ci return oldap_map_error(rc, CURLE_BAD_CONTENT_ENCODING); 62213498266Sopenharmony_ci for(rc = ldap_get_attribute_ber(li->ld, msg, ber, &bv, &bvals); 62313498266Sopenharmony_ci rc == LDAP_SUCCESS; 62413498266Sopenharmony_ci rc = ldap_get_attribute_ber(li->ld, msg, ber, &bv, &bvals)) { 62513498266Sopenharmony_ci int i; 62613498266Sopenharmony_ci 62713498266Sopenharmony_ci if(!bv.bv_val) 62813498266Sopenharmony_ci break; 62913498266Sopenharmony_ci 63013498266Sopenharmony_ci if(bvals) { 63113498266Sopenharmony_ci for(i = 0; bvals[i].bv_val; i++) { 63213498266Sopenharmony_ci size_t llen; 63313498266Sopenharmony_ci unsigned short mech = Curl_sasl_decode_mech((char *) bvals[i].bv_val, 63413498266Sopenharmony_ci bvals[i].bv_len, &llen); 63513498266Sopenharmony_ci if(bvals[i].bv_len == llen) 63613498266Sopenharmony_ci li->sasl.authmechs |= mech; 63713498266Sopenharmony_ci } 63813498266Sopenharmony_ci ber_memfree(bvals); 63913498266Sopenharmony_ci } 64013498266Sopenharmony_ci } 64113498266Sopenharmony_ci ber_free(ber, 0); 64213498266Sopenharmony_ci break; 64313498266Sopenharmony_ci 64413498266Sopenharmony_ci case LDAP_RES_SEARCH_RESULT: 64513498266Sopenharmony_ci switch(code) { 64613498266Sopenharmony_ci case LDAP_SIZELIMIT_EXCEEDED: 64713498266Sopenharmony_ci infof(data, "Too many authentication mechanisms\n"); 64813498266Sopenharmony_ci FALLTHROUGH(); 64913498266Sopenharmony_ci case LDAP_SUCCESS: 65013498266Sopenharmony_ci case LDAP_NO_RESULTS_RETURNED: 65113498266Sopenharmony_ci if(Curl_sasl_can_authenticate(&li->sasl, data)) 65213498266Sopenharmony_ci result = oldap_perform_sasl(data); 65313498266Sopenharmony_ci else 65413498266Sopenharmony_ci result = CURLE_LOGIN_DENIED; 65513498266Sopenharmony_ci break; 65613498266Sopenharmony_ci default: 65713498266Sopenharmony_ci result = oldap_map_error(code, CURLE_LOGIN_DENIED); 65813498266Sopenharmony_ci break; 65913498266Sopenharmony_ci } 66013498266Sopenharmony_ci break; 66113498266Sopenharmony_ci default: 66213498266Sopenharmony_ci break; 66313498266Sopenharmony_ci } 66413498266Sopenharmony_ci return result; 66513498266Sopenharmony_ci} 66613498266Sopenharmony_ci 66713498266Sopenharmony_ci/* Handle a SASL bind response. */ 66813498266Sopenharmony_cistatic CURLcode oldap_state_sasl_resp(struct Curl_easy *data, 66913498266Sopenharmony_ci LDAPMessage *msg, int code) 67013498266Sopenharmony_ci{ 67113498266Sopenharmony_ci struct connectdata *conn = data->conn; 67213498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 67313498266Sopenharmony_ci CURLcode result = CURLE_OK; 67413498266Sopenharmony_ci saslprogress progress; 67513498266Sopenharmony_ci int rc; 67613498266Sopenharmony_ci 67713498266Sopenharmony_ci li->servercred = NULL; 67813498266Sopenharmony_ci rc = ldap_parse_sasl_bind_result(li->ld, msg, &li->servercred, 0); 67913498266Sopenharmony_ci if(rc != LDAP_SUCCESS) { 68013498266Sopenharmony_ci failf(data, "LDAP local: sasl ldap_parse_result %s", ldap_err2string(rc)); 68113498266Sopenharmony_ci result = oldap_map_error(rc, CURLE_LOGIN_DENIED); 68213498266Sopenharmony_ci } 68313498266Sopenharmony_ci else { 68413498266Sopenharmony_ci result = Curl_sasl_continue(&li->sasl, data, code, &progress); 68513498266Sopenharmony_ci if(!result && progress != SASL_INPROGRESS) 68613498266Sopenharmony_ci oldap_state(data, OLDAP_STOP); 68713498266Sopenharmony_ci } 68813498266Sopenharmony_ci 68913498266Sopenharmony_ci if(li->servercred) 69013498266Sopenharmony_ci ber_bvfree(li->servercred); 69113498266Sopenharmony_ci return result; 69213498266Sopenharmony_ci} 69313498266Sopenharmony_ci 69413498266Sopenharmony_ci/* Handle a simple bind response. */ 69513498266Sopenharmony_cistatic CURLcode oldap_state_bind_resp(struct Curl_easy *data, LDAPMessage *msg, 69613498266Sopenharmony_ci int code) 69713498266Sopenharmony_ci{ 69813498266Sopenharmony_ci struct connectdata *conn = data->conn; 69913498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 70013498266Sopenharmony_ci CURLcode result = CURLE_OK; 70113498266Sopenharmony_ci struct berval *bv = NULL; 70213498266Sopenharmony_ci int rc; 70313498266Sopenharmony_ci 70413498266Sopenharmony_ci if(code != LDAP_SUCCESS) 70513498266Sopenharmony_ci return oldap_map_error(code, CURLE_LDAP_CANNOT_BIND); 70613498266Sopenharmony_ci 70713498266Sopenharmony_ci rc = ldap_parse_sasl_bind_result(li->ld, msg, &bv, 0); 70813498266Sopenharmony_ci if(rc != LDAP_SUCCESS) { 70913498266Sopenharmony_ci failf(data, "LDAP local: bind ldap_parse_sasl_bind_result %s", 71013498266Sopenharmony_ci ldap_err2string(rc)); 71113498266Sopenharmony_ci result = oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND); 71213498266Sopenharmony_ci } 71313498266Sopenharmony_ci else 71413498266Sopenharmony_ci oldap_state(data, OLDAP_STOP); 71513498266Sopenharmony_ci 71613498266Sopenharmony_ci if(bv) 71713498266Sopenharmony_ci ber_bvfree(bv); 71813498266Sopenharmony_ci return result; 71913498266Sopenharmony_ci} 72013498266Sopenharmony_ci 72113498266Sopenharmony_cistatic CURLcode oldap_connecting(struct Curl_easy *data, bool *done) 72213498266Sopenharmony_ci{ 72313498266Sopenharmony_ci CURLcode result = CURLE_OK; 72413498266Sopenharmony_ci struct connectdata *conn = data->conn; 72513498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 72613498266Sopenharmony_ci LDAPMessage *msg = NULL; 72713498266Sopenharmony_ci struct timeval tv = {0, 0}; 72813498266Sopenharmony_ci int code = LDAP_SUCCESS; 72913498266Sopenharmony_ci int rc; 73013498266Sopenharmony_ci 73113498266Sopenharmony_ci if(li->state != OLDAP_SSL && li->state != OLDAP_TLS) { 73213498266Sopenharmony_ci /* Get response to last command. */ 73313498266Sopenharmony_ci rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, &tv, &msg); 73413498266Sopenharmony_ci switch(rc) { 73513498266Sopenharmony_ci case 0: /* Timed out. */ 73613498266Sopenharmony_ci return CURLE_OK; 73713498266Sopenharmony_ci case LDAP_RES_SEARCH_ENTRY: 73813498266Sopenharmony_ci case LDAP_RES_SEARCH_REFERENCE: 73913498266Sopenharmony_ci break; 74013498266Sopenharmony_ci default: 74113498266Sopenharmony_ci li->msgid = 0; /* Nothing to abandon upon error. */ 74213498266Sopenharmony_ci if(rc < 0) { 74313498266Sopenharmony_ci failf(data, "LDAP local: connecting ldap_result %s", 74413498266Sopenharmony_ci ldap_err2string(rc)); 74513498266Sopenharmony_ci return oldap_map_error(rc, CURLE_COULDNT_CONNECT); 74613498266Sopenharmony_ci } 74713498266Sopenharmony_ci break; 74813498266Sopenharmony_ci } 74913498266Sopenharmony_ci 75013498266Sopenharmony_ci /* Get error code from message. */ 75113498266Sopenharmony_ci rc = ldap_parse_result(li->ld, msg, &code, NULL, NULL, NULL, NULL, 0); 75213498266Sopenharmony_ci if(rc) 75313498266Sopenharmony_ci code = rc; 75413498266Sopenharmony_ci else { 75513498266Sopenharmony_ci /* store the latest code for later retrieval */ 75613498266Sopenharmony_ci data->info.httpcode = code; 75713498266Sopenharmony_ci } 75813498266Sopenharmony_ci 75913498266Sopenharmony_ci /* If protocol version 3 is not supported, fallback to version 2. */ 76013498266Sopenharmony_ci if(code == LDAP_PROTOCOL_ERROR && li->state != OLDAP_BINDV2 && 76113498266Sopenharmony_ci#ifdef USE_SSL 76213498266Sopenharmony_ci (ssl_installed(conn) || data->set.use_ssl <= CURLUSESSL_TRY) && 76313498266Sopenharmony_ci#endif 76413498266Sopenharmony_ci li->sasl.prefmech == SASL_AUTH_NONE) { 76513498266Sopenharmony_ci static const int version = LDAP_VERSION2; 76613498266Sopenharmony_ci 76713498266Sopenharmony_ci ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &version); 76813498266Sopenharmony_ci ldap_msgfree(msg); 76913498266Sopenharmony_ci return oldap_perform_bind(data, OLDAP_BINDV2); 77013498266Sopenharmony_ci } 77113498266Sopenharmony_ci } 77213498266Sopenharmony_ci 77313498266Sopenharmony_ci /* Handle response message according to current state. */ 77413498266Sopenharmony_ci switch(li->state) { 77513498266Sopenharmony_ci 77613498266Sopenharmony_ci#ifdef USE_SSL 77713498266Sopenharmony_ci case OLDAP_SSL: 77813498266Sopenharmony_ci result = oldap_ssl_connect(data, OLDAP_SSL); 77913498266Sopenharmony_ci if(!result && ssl_installed(conn)) { 78013498266Sopenharmony_ci if(li->sasl.prefmech != SASL_AUTH_NONE) 78113498266Sopenharmony_ci result = oldap_perform_mechs(data); 78213498266Sopenharmony_ci else 78313498266Sopenharmony_ci result = oldap_perform_bind(data, OLDAP_BIND); 78413498266Sopenharmony_ci } 78513498266Sopenharmony_ci break; 78613498266Sopenharmony_ci case OLDAP_STARTTLS: 78713498266Sopenharmony_ci if(code != LDAP_SUCCESS) { 78813498266Sopenharmony_ci if(data->set.use_ssl != CURLUSESSL_TRY) 78913498266Sopenharmony_ci result = oldap_map_error(code, CURLE_USE_SSL_FAILED); 79013498266Sopenharmony_ci else if(li->sasl.prefmech != SASL_AUTH_NONE) 79113498266Sopenharmony_ci result = oldap_perform_mechs(data); 79213498266Sopenharmony_ci else 79313498266Sopenharmony_ci result = oldap_perform_bind(data, OLDAP_BIND); 79413498266Sopenharmony_ci break; 79513498266Sopenharmony_ci } 79613498266Sopenharmony_ci result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET); 79713498266Sopenharmony_ci if(result) 79813498266Sopenharmony_ci break; 79913498266Sopenharmony_ci FALLTHROUGH(); 80013498266Sopenharmony_ci case OLDAP_TLS: 80113498266Sopenharmony_ci result = oldap_ssl_connect(data, OLDAP_TLS); 80213498266Sopenharmony_ci if(result) 80313498266Sopenharmony_ci result = oldap_map_error(code, CURLE_USE_SSL_FAILED); 80413498266Sopenharmony_ci else if(ssl_installed(conn)) { 80513498266Sopenharmony_ci conn->bits.tls_upgraded = TRUE; 80613498266Sopenharmony_ci if(li->sasl.prefmech != SASL_AUTH_NONE) 80713498266Sopenharmony_ci result = oldap_perform_mechs(data); 80813498266Sopenharmony_ci else if(data->state.aptr.user) 80913498266Sopenharmony_ci result = oldap_perform_bind(data, OLDAP_BIND); 81013498266Sopenharmony_ci else { 81113498266Sopenharmony_ci /* Version 3 supported: no bind required */ 81213498266Sopenharmony_ci oldap_state(data, OLDAP_STOP); 81313498266Sopenharmony_ci result = CURLE_OK; 81413498266Sopenharmony_ci } 81513498266Sopenharmony_ci } 81613498266Sopenharmony_ci break; 81713498266Sopenharmony_ci#endif 81813498266Sopenharmony_ci 81913498266Sopenharmony_ci case OLDAP_MECHS: 82013498266Sopenharmony_ci result = oldap_state_mechs_resp(data, msg, code); 82113498266Sopenharmony_ci break; 82213498266Sopenharmony_ci case OLDAP_SASL: 82313498266Sopenharmony_ci result = oldap_state_sasl_resp(data, msg, code); 82413498266Sopenharmony_ci break; 82513498266Sopenharmony_ci case OLDAP_BIND: 82613498266Sopenharmony_ci case OLDAP_BINDV2: 82713498266Sopenharmony_ci result = oldap_state_bind_resp(data, msg, code); 82813498266Sopenharmony_ci break; 82913498266Sopenharmony_ci default: 83013498266Sopenharmony_ci /* internal error */ 83113498266Sopenharmony_ci result = CURLE_COULDNT_CONNECT; 83213498266Sopenharmony_ci break; 83313498266Sopenharmony_ci } 83413498266Sopenharmony_ci 83513498266Sopenharmony_ci ldap_msgfree(msg); 83613498266Sopenharmony_ci 83713498266Sopenharmony_ci *done = li->state == OLDAP_STOP; 83813498266Sopenharmony_ci if(*done) 83913498266Sopenharmony_ci conn->recv[FIRSTSOCKET] = oldap_recv; 84013498266Sopenharmony_ci 84113498266Sopenharmony_ci if(result && li->msgid) { 84213498266Sopenharmony_ci ldap_abandon_ext(li->ld, li->msgid, NULL, NULL); 84313498266Sopenharmony_ci li->msgid = 0; 84413498266Sopenharmony_ci } 84513498266Sopenharmony_ci return result; 84613498266Sopenharmony_ci} 84713498266Sopenharmony_ci 84813498266Sopenharmony_cistatic CURLcode oldap_disconnect(struct Curl_easy *data, 84913498266Sopenharmony_ci struct connectdata *conn, 85013498266Sopenharmony_ci bool dead_connection) 85113498266Sopenharmony_ci{ 85213498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 85313498266Sopenharmony_ci (void) dead_connection; 85413498266Sopenharmony_ci#ifndef USE_SSL 85513498266Sopenharmony_ci (void)data; 85613498266Sopenharmony_ci#endif 85713498266Sopenharmony_ci 85813498266Sopenharmony_ci if(li) { 85913498266Sopenharmony_ci if(li->ld) { 86013498266Sopenharmony_ci#ifdef USE_SSL 86113498266Sopenharmony_ci if(ssl_installed(conn)) { 86213498266Sopenharmony_ci Sockbuf *sb; 86313498266Sopenharmony_ci ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb); 86413498266Sopenharmony_ci ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data); 86513498266Sopenharmony_ci } 86613498266Sopenharmony_ci#endif 86713498266Sopenharmony_ci ldap_unbind_ext(li->ld, NULL, NULL); 86813498266Sopenharmony_ci li->ld = NULL; 86913498266Sopenharmony_ci } 87013498266Sopenharmony_ci Curl_sasl_cleanup(conn, li->sasl.authused); 87113498266Sopenharmony_ci conn->proto.ldapc = NULL; 87213498266Sopenharmony_ci free(li); 87313498266Sopenharmony_ci } 87413498266Sopenharmony_ci return CURLE_OK; 87513498266Sopenharmony_ci} 87613498266Sopenharmony_ci 87713498266Sopenharmony_cistatic CURLcode oldap_do(struct Curl_easy *data, bool *done) 87813498266Sopenharmony_ci{ 87913498266Sopenharmony_ci struct connectdata *conn = data->conn; 88013498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 88113498266Sopenharmony_ci struct ldapreqinfo *lr; 88213498266Sopenharmony_ci CURLcode result; 88313498266Sopenharmony_ci int rc; 88413498266Sopenharmony_ci LDAPURLDesc *lud; 88513498266Sopenharmony_ci int msgid; 88613498266Sopenharmony_ci 88713498266Sopenharmony_ci connkeep(conn, "OpenLDAP do"); 88813498266Sopenharmony_ci 88913498266Sopenharmony_ci infof(data, "LDAP local: %s", data->state.url); 89013498266Sopenharmony_ci 89113498266Sopenharmony_ci result = oldap_url_parse(data, &lud); 89213498266Sopenharmony_ci if(!result) { 89313498266Sopenharmony_ci#ifdef USE_SSL 89413498266Sopenharmony_ci if(ssl_installed(conn)) { 89513498266Sopenharmony_ci Sockbuf *sb; 89613498266Sopenharmony_ci /* re-install the libcurl SSL handlers into the sockbuf. */ 89713498266Sopenharmony_ci ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb); 89813498266Sopenharmony_ci ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data); 89913498266Sopenharmony_ci } 90013498266Sopenharmony_ci#endif 90113498266Sopenharmony_ci 90213498266Sopenharmony_ci rc = ldap_search_ext(li->ld, lud->lud_dn, lud->lud_scope, 90313498266Sopenharmony_ci lud->lud_filter, lud->lud_attrs, 0, 90413498266Sopenharmony_ci NULL, NULL, NULL, 0, &msgid); 90513498266Sopenharmony_ci ldap_free_urldesc(lud); 90613498266Sopenharmony_ci if(rc != LDAP_SUCCESS) { 90713498266Sopenharmony_ci failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc)); 90813498266Sopenharmony_ci result = CURLE_LDAP_SEARCH_FAILED; 90913498266Sopenharmony_ci } 91013498266Sopenharmony_ci else { 91113498266Sopenharmony_ci lr = calloc(1, sizeof(struct ldapreqinfo)); 91213498266Sopenharmony_ci if(!lr) { 91313498266Sopenharmony_ci ldap_abandon_ext(li->ld, msgid, NULL, NULL); 91413498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 91513498266Sopenharmony_ci } 91613498266Sopenharmony_ci else { 91713498266Sopenharmony_ci lr->msgid = msgid; 91813498266Sopenharmony_ci data->req.p.ldap = lr; 91913498266Sopenharmony_ci Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); 92013498266Sopenharmony_ci *done = TRUE; 92113498266Sopenharmony_ci } 92213498266Sopenharmony_ci } 92313498266Sopenharmony_ci } 92413498266Sopenharmony_ci return result; 92513498266Sopenharmony_ci} 92613498266Sopenharmony_ci 92713498266Sopenharmony_cistatic CURLcode oldap_done(struct Curl_easy *data, CURLcode res, 92813498266Sopenharmony_ci bool premature) 92913498266Sopenharmony_ci{ 93013498266Sopenharmony_ci struct connectdata *conn = data->conn; 93113498266Sopenharmony_ci struct ldapreqinfo *lr = data->req.p.ldap; 93213498266Sopenharmony_ci 93313498266Sopenharmony_ci (void)res; 93413498266Sopenharmony_ci (void)premature; 93513498266Sopenharmony_ci 93613498266Sopenharmony_ci if(lr) { 93713498266Sopenharmony_ci /* if there was a search in progress, abandon it */ 93813498266Sopenharmony_ci if(lr->msgid) { 93913498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 94013498266Sopenharmony_ci ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL); 94113498266Sopenharmony_ci lr->msgid = 0; 94213498266Sopenharmony_ci } 94313498266Sopenharmony_ci data->req.p.ldap = NULL; 94413498266Sopenharmony_ci free(lr); 94513498266Sopenharmony_ci } 94613498266Sopenharmony_ci 94713498266Sopenharmony_ci return CURLE_OK; 94813498266Sopenharmony_ci} 94913498266Sopenharmony_ci 95013498266Sopenharmony_cistatic CURLcode client_write(struct Curl_easy *data, 95113498266Sopenharmony_ci const char *prefix, size_t plen, 95213498266Sopenharmony_ci const char *value, size_t len, 95313498266Sopenharmony_ci const char *suffix, size_t slen) 95413498266Sopenharmony_ci{ 95513498266Sopenharmony_ci CURLcode result = CURLE_OK; 95613498266Sopenharmony_ci 95713498266Sopenharmony_ci if(prefix) { 95813498266Sopenharmony_ci /* If we have a zero-length value and the prefix ends with a space 95913498266Sopenharmony_ci separator, drop the latter. */ 96013498266Sopenharmony_ci if(!len && plen && prefix[plen - 1] == ' ') 96113498266Sopenharmony_ci plen--; 96213498266Sopenharmony_ci result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) prefix, plen); 96313498266Sopenharmony_ci } 96413498266Sopenharmony_ci if(!result && value) { 96513498266Sopenharmony_ci result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) value, len); 96613498266Sopenharmony_ci } 96713498266Sopenharmony_ci if(!result && suffix) { 96813498266Sopenharmony_ci result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) suffix, slen); 96913498266Sopenharmony_ci } 97013498266Sopenharmony_ci return result; 97113498266Sopenharmony_ci} 97213498266Sopenharmony_ci 97313498266Sopenharmony_cistatic ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf, 97413498266Sopenharmony_ci size_t len, CURLcode *err) 97513498266Sopenharmony_ci{ 97613498266Sopenharmony_ci struct connectdata *conn = data->conn; 97713498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 97813498266Sopenharmony_ci struct ldapreqinfo *lr = data->req.p.ldap; 97913498266Sopenharmony_ci int rc; 98013498266Sopenharmony_ci LDAPMessage *msg = NULL; 98113498266Sopenharmony_ci BerElement *ber = NULL; 98213498266Sopenharmony_ci struct timeval tv = {0, 0}; 98313498266Sopenharmony_ci struct berval bv, *bvals; 98413498266Sopenharmony_ci int binary = 0; 98513498266Sopenharmony_ci CURLcode result = CURLE_AGAIN; 98613498266Sopenharmony_ci int code; 98713498266Sopenharmony_ci char *info = NULL; 98813498266Sopenharmony_ci 98913498266Sopenharmony_ci (void)len; 99013498266Sopenharmony_ci (void)buf; 99113498266Sopenharmony_ci (void)sockindex; 99213498266Sopenharmony_ci 99313498266Sopenharmony_ci rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_ONE, &tv, &msg); 99413498266Sopenharmony_ci if(rc < 0) { 99513498266Sopenharmony_ci failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc)); 99613498266Sopenharmony_ci result = CURLE_RECV_ERROR; 99713498266Sopenharmony_ci } 99813498266Sopenharmony_ci 99913498266Sopenharmony_ci *err = result; 100013498266Sopenharmony_ci 100113498266Sopenharmony_ci /* error or timed out */ 100213498266Sopenharmony_ci if(!msg) 100313498266Sopenharmony_ci return -1; 100413498266Sopenharmony_ci 100513498266Sopenharmony_ci result = CURLE_OK; 100613498266Sopenharmony_ci 100713498266Sopenharmony_ci switch(ldap_msgtype(msg)) { 100813498266Sopenharmony_ci case LDAP_RES_SEARCH_RESULT: 100913498266Sopenharmony_ci lr->msgid = 0; 101013498266Sopenharmony_ci rc = ldap_parse_result(li->ld, msg, &code, NULL, &info, NULL, NULL, 0); 101113498266Sopenharmony_ci if(rc) { 101213498266Sopenharmony_ci failf(data, "LDAP local: search ldap_parse_result %s", 101313498266Sopenharmony_ci ldap_err2string(rc)); 101413498266Sopenharmony_ci result = CURLE_LDAP_SEARCH_FAILED; 101513498266Sopenharmony_ci break; 101613498266Sopenharmony_ci } 101713498266Sopenharmony_ci 101813498266Sopenharmony_ci /* store the latest code for later retrieval */ 101913498266Sopenharmony_ci data->info.httpcode = code; 102013498266Sopenharmony_ci 102113498266Sopenharmony_ci switch(code) { 102213498266Sopenharmony_ci case LDAP_SIZELIMIT_EXCEEDED: 102313498266Sopenharmony_ci infof(data, "There are more than %d entries", lr->nument); 102413498266Sopenharmony_ci FALLTHROUGH(); 102513498266Sopenharmony_ci case LDAP_SUCCESS: 102613498266Sopenharmony_ci data->req.size = data->req.bytecount; 102713498266Sopenharmony_ci break; 102813498266Sopenharmony_ci default: 102913498266Sopenharmony_ci failf(data, "LDAP remote: search failed %s %s", ldap_err2string(code), 103013498266Sopenharmony_ci info ? info : ""); 103113498266Sopenharmony_ci result = CURLE_LDAP_SEARCH_FAILED; 103213498266Sopenharmony_ci break; 103313498266Sopenharmony_ci } 103413498266Sopenharmony_ci if(info) 103513498266Sopenharmony_ci ldap_memfree(info); 103613498266Sopenharmony_ci break; 103713498266Sopenharmony_ci case LDAP_RES_SEARCH_ENTRY: 103813498266Sopenharmony_ci lr->nument++; 103913498266Sopenharmony_ci rc = ldap_get_dn_ber(li->ld, msg, &ber, &bv); 104013498266Sopenharmony_ci if(rc < 0) { 104113498266Sopenharmony_ci result = CURLE_RECV_ERROR; 104213498266Sopenharmony_ci break; 104313498266Sopenharmony_ci } 104413498266Sopenharmony_ci 104513498266Sopenharmony_ci result = client_write(data, STRCONST("DN: "), bv.bv_val, bv.bv_len, 104613498266Sopenharmony_ci STRCONST("\n")); 104713498266Sopenharmony_ci if(result) 104813498266Sopenharmony_ci break; 104913498266Sopenharmony_ci 105013498266Sopenharmony_ci for(rc = ldap_get_attribute_ber(li->ld, msg, ber, &bv, &bvals); 105113498266Sopenharmony_ci rc == LDAP_SUCCESS; 105213498266Sopenharmony_ci rc = ldap_get_attribute_ber(li->ld, msg, ber, &bv, &bvals)) { 105313498266Sopenharmony_ci int i; 105413498266Sopenharmony_ci 105513498266Sopenharmony_ci if(!bv.bv_val) 105613498266Sopenharmony_ci break; 105713498266Sopenharmony_ci 105813498266Sopenharmony_ci if(!bvals) { 105913498266Sopenharmony_ci result = client_write(data, STRCONST("\t"), bv.bv_val, bv.bv_len, 106013498266Sopenharmony_ci STRCONST(":\n")); 106113498266Sopenharmony_ci if(result) 106213498266Sopenharmony_ci break; 106313498266Sopenharmony_ci continue; 106413498266Sopenharmony_ci } 106513498266Sopenharmony_ci 106613498266Sopenharmony_ci binary = bv.bv_len > 7 && 106713498266Sopenharmony_ci !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7); 106813498266Sopenharmony_ci 106913498266Sopenharmony_ci for(i = 0; bvals[i].bv_val != NULL; i++) { 107013498266Sopenharmony_ci int binval = 0; 107113498266Sopenharmony_ci 107213498266Sopenharmony_ci result = client_write(data, STRCONST("\t"), bv.bv_val, bv.bv_len, 107313498266Sopenharmony_ci STRCONST(":")); 107413498266Sopenharmony_ci if(result) 107513498266Sopenharmony_ci break; 107613498266Sopenharmony_ci 107713498266Sopenharmony_ci if(!binary) { 107813498266Sopenharmony_ci /* check for leading or trailing whitespace */ 107913498266Sopenharmony_ci if(ISBLANK(bvals[i].bv_val[0]) || 108013498266Sopenharmony_ci ISBLANK(bvals[i].bv_val[bvals[i].bv_len - 1])) 108113498266Sopenharmony_ci binval = 1; 108213498266Sopenharmony_ci else { 108313498266Sopenharmony_ci /* check for unprintable characters */ 108413498266Sopenharmony_ci unsigned int j; 108513498266Sopenharmony_ci for(j = 0; j < bvals[i].bv_len; j++) 108613498266Sopenharmony_ci if(!ISPRINT(bvals[i].bv_val[j])) { 108713498266Sopenharmony_ci binval = 1; 108813498266Sopenharmony_ci break; 108913498266Sopenharmony_ci } 109013498266Sopenharmony_ci } 109113498266Sopenharmony_ci } 109213498266Sopenharmony_ci if(binary || binval) { 109313498266Sopenharmony_ci char *val_b64 = NULL; 109413498266Sopenharmony_ci size_t val_b64_sz = 0; 109513498266Sopenharmony_ci 109613498266Sopenharmony_ci /* Binary value, encode to base64. */ 109713498266Sopenharmony_ci if(bvals[i].bv_len) 109813498266Sopenharmony_ci result = Curl_base64_encode(bvals[i].bv_val, bvals[i].bv_len, 109913498266Sopenharmony_ci &val_b64, &val_b64_sz); 110013498266Sopenharmony_ci if(!result) 110113498266Sopenharmony_ci result = client_write(data, STRCONST(": "), val_b64, val_b64_sz, 110213498266Sopenharmony_ci STRCONST("\n")); 110313498266Sopenharmony_ci free(val_b64); 110413498266Sopenharmony_ci } 110513498266Sopenharmony_ci else 110613498266Sopenharmony_ci result = client_write(data, STRCONST(" "), 110713498266Sopenharmony_ci bvals[i].bv_val, bvals[i].bv_len, 110813498266Sopenharmony_ci STRCONST("\n")); 110913498266Sopenharmony_ci if(result) 111013498266Sopenharmony_ci break; 111113498266Sopenharmony_ci } 111213498266Sopenharmony_ci 111313498266Sopenharmony_ci ber_memfree(bvals); 111413498266Sopenharmony_ci bvals = NULL; 111513498266Sopenharmony_ci if(!result) 111613498266Sopenharmony_ci result = client_write(data, STRCONST("\n"), NULL, 0, NULL, 0); 111713498266Sopenharmony_ci if(result) 111813498266Sopenharmony_ci break; 111913498266Sopenharmony_ci } 112013498266Sopenharmony_ci 112113498266Sopenharmony_ci ber_free(ber, 0); 112213498266Sopenharmony_ci 112313498266Sopenharmony_ci if(!result) 112413498266Sopenharmony_ci result = client_write(data, STRCONST("\n"), NULL, 0, NULL, 0); 112513498266Sopenharmony_ci if(!result) 112613498266Sopenharmony_ci result = CURLE_AGAIN; 112713498266Sopenharmony_ci break; 112813498266Sopenharmony_ci } 112913498266Sopenharmony_ci 113013498266Sopenharmony_ci ldap_msgfree(msg); 113113498266Sopenharmony_ci *err = result; 113213498266Sopenharmony_ci return result? -1: 0; 113313498266Sopenharmony_ci} 113413498266Sopenharmony_ci 113513498266Sopenharmony_ci#ifdef USE_SSL 113613498266Sopenharmony_cistatic int 113713498266Sopenharmony_cildapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg) 113813498266Sopenharmony_ci{ 113913498266Sopenharmony_ci sbiod->sbiod_pvt = arg; 114013498266Sopenharmony_ci return 0; 114113498266Sopenharmony_ci} 114213498266Sopenharmony_ci 114313498266Sopenharmony_cistatic int 114413498266Sopenharmony_cildapsb_tls_remove(Sockbuf_IO_Desc *sbiod) 114513498266Sopenharmony_ci{ 114613498266Sopenharmony_ci sbiod->sbiod_pvt = NULL; 114713498266Sopenharmony_ci return 0; 114813498266Sopenharmony_ci} 114913498266Sopenharmony_ci 115013498266Sopenharmony_ci/* We don't need to do anything because libcurl does it already */ 115113498266Sopenharmony_cistatic int 115213498266Sopenharmony_cildapsb_tls_close(Sockbuf_IO_Desc *sbiod) 115313498266Sopenharmony_ci{ 115413498266Sopenharmony_ci (void)sbiod; 115513498266Sopenharmony_ci return 0; 115613498266Sopenharmony_ci} 115713498266Sopenharmony_ci 115813498266Sopenharmony_cistatic int 115913498266Sopenharmony_cildapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg) 116013498266Sopenharmony_ci{ 116113498266Sopenharmony_ci (void)arg; 116213498266Sopenharmony_ci if(opt == LBER_SB_OPT_DATA_READY) { 116313498266Sopenharmony_ci struct Curl_easy *data = sbiod->sbiod_pvt; 116413498266Sopenharmony_ci return Curl_conn_data_pending(data, FIRSTSOCKET); 116513498266Sopenharmony_ci } 116613498266Sopenharmony_ci return 0; 116713498266Sopenharmony_ci} 116813498266Sopenharmony_ci 116913498266Sopenharmony_cistatic ber_slen_t 117013498266Sopenharmony_cildapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) 117113498266Sopenharmony_ci{ 117213498266Sopenharmony_ci struct Curl_easy *data = sbiod->sbiod_pvt; 117313498266Sopenharmony_ci ber_slen_t ret = 0; 117413498266Sopenharmony_ci if(data) { 117513498266Sopenharmony_ci struct connectdata *conn = data->conn; 117613498266Sopenharmony_ci if(conn) { 117713498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 117813498266Sopenharmony_ci CURLcode err = CURLE_RECV_ERROR; 117913498266Sopenharmony_ci 118013498266Sopenharmony_ci ret = (li->recv)(data, FIRSTSOCKET, buf, len, &err); 118113498266Sopenharmony_ci if(ret < 0 && err == CURLE_AGAIN) { 118213498266Sopenharmony_ci SET_SOCKERRNO(EWOULDBLOCK); 118313498266Sopenharmony_ci } 118413498266Sopenharmony_ci } 118513498266Sopenharmony_ci } 118613498266Sopenharmony_ci return ret; 118713498266Sopenharmony_ci} 118813498266Sopenharmony_ci 118913498266Sopenharmony_cistatic ber_slen_t 119013498266Sopenharmony_cildapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) 119113498266Sopenharmony_ci{ 119213498266Sopenharmony_ci struct Curl_easy *data = sbiod->sbiod_pvt; 119313498266Sopenharmony_ci ber_slen_t ret = 0; 119413498266Sopenharmony_ci if(data) { 119513498266Sopenharmony_ci struct connectdata *conn = data->conn; 119613498266Sopenharmony_ci if(conn) { 119713498266Sopenharmony_ci struct ldapconninfo *li = conn->proto.ldapc; 119813498266Sopenharmony_ci CURLcode err = CURLE_SEND_ERROR; 119913498266Sopenharmony_ci ret = (li->send)(data, FIRSTSOCKET, buf, len, &err); 120013498266Sopenharmony_ci if(ret < 0 && err == CURLE_AGAIN) { 120113498266Sopenharmony_ci SET_SOCKERRNO(EWOULDBLOCK); 120213498266Sopenharmony_ci } 120313498266Sopenharmony_ci } 120413498266Sopenharmony_ci } 120513498266Sopenharmony_ci return ret; 120613498266Sopenharmony_ci} 120713498266Sopenharmony_ci 120813498266Sopenharmony_cistatic Sockbuf_IO ldapsb_tls = 120913498266Sopenharmony_ci{ 121013498266Sopenharmony_ci ldapsb_tls_setup, 121113498266Sopenharmony_ci ldapsb_tls_remove, 121213498266Sopenharmony_ci ldapsb_tls_ctrl, 121313498266Sopenharmony_ci ldapsb_tls_read, 121413498266Sopenharmony_ci ldapsb_tls_write, 121513498266Sopenharmony_ci ldapsb_tls_close 121613498266Sopenharmony_ci}; 121713498266Sopenharmony_ci#endif /* USE_SSL */ 121813498266Sopenharmony_ci 121913498266Sopenharmony_ci#endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */ 1220