mirror of
https://github.com/curl/curl.git
synced 2025-01-18 14:04:30 +08:00
openldap: implement SASL authentication
As credentials can be quite different depending on the mechanism used, there are no default mechanisms for LDAP and simple bind with a DN is then used. The caller has to provide mechanism(s) using CURLOPT_LOGIN_OPTIONS to enable SASL authentication and disable simple bind. Closes #8152
This commit is contained in:
parent
ce5463e60c
commit
eeca818b1e
@ -1,6 +1,6 @@
|
||||
Long: login-options
|
||||
Arg: <options>
|
||||
Protocols: IMAP POP3 SMTP
|
||||
Protocols: IMAP LDAP POP3 SMTP
|
||||
Help: Server login options
|
||||
Added: 7.34.0
|
||||
Category: imap pop3 smtp auth
|
||||
|
@ -1,7 +1,7 @@
|
||||
Long: oauth2-bearer
|
||||
Help: OAuth 2 Bearer Token
|
||||
Arg: <token>
|
||||
Protocols: IMAP POP3 SMTP HTTP
|
||||
Protocols: IMAP LDAP POP3 SMTP HTTP
|
||||
Category: auth
|
||||
Example: --oauth2-bearer "mF_9.B5f-4.1JqM" $URL
|
||||
Added: 7.33.0
|
||||
|
@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@ -172,8 +172,8 @@ supports IPv6
|
||||
.IP CURL_VERSION_KERBEROS4
|
||||
supports Kerberos V4 (when using FTP). Legacy bit. Deprecated since 7.33.0.
|
||||
.IP CURL_VERSION_KERBEROS5
|
||||
supports Kerberos V5 authentication for FTP, IMAP, POP3, SMTP and SOCKSv5 proxy
|
||||
(Added in 7.40.0)
|
||||
supports Kerberos V5 authentication for FTP, IMAP, LDAP, POP3, SMTP and
|
||||
SOCKSv5 proxy. (Added in 7.40.0)
|
||||
.IP CURL_VERSION_LARGEFILE
|
||||
libcurl was built with support for large files. (Added in 7.11.1)
|
||||
.IP CURL_VERSION_UNICODE
|
||||
|
@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@ -46,7 +46,7 @@ option.
|
||||
.SH DEFAULT
|
||||
NULL
|
||||
.SH PROTOCOLS
|
||||
Only IMAP, POP3 and SMTP support login options.
|
||||
Only IMAP, LDAP, POP3 and SMTP support login options.
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
CURL *curl = curl_easy_init();
|
||||
@ -58,7 +58,7 @@ if(curl) {
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in 7.34.0
|
||||
Added in 7.34.0. Support for OpenLDAP added in 7.82.0.
|
||||
.SH RETURN VALUE
|
||||
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
|
||||
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
|
||||
|
@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@ -45,7 +45,7 @@ or a shared mailbox for example.
|
||||
.SH DEFAULT
|
||||
blank
|
||||
.SH PROTOCOLS
|
||||
IMAP, POP3 and SMTP
|
||||
IMAP, LDAP, POP3 and SMTP
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
CURL *curl = curl_easy_init();
|
||||
@ -59,7 +59,7 @@ if(curl) {
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in 7.66.0
|
||||
Added in 7.66.0. Support for OpenLDAP added in 7.82.0.
|
||||
.SH RETURN VALUE
|
||||
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
|
||||
.SH "SEE ALSO"
|
||||
|
@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@ -32,15 +32,15 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SERVICE_NAME, char *name);
|
||||
.SH DESCRIPTION
|
||||
Pass a char * as parameter to a string holding the \fIname\fP of the service
|
||||
for DIGEST-MD5, SPNEGO and Kerberos 5 authentication mechanisms. The default
|
||||
service names are "ftp", "HTTP", "imap", "pop" and "smtp". This option allows
|
||||
you to change them.
|
||||
service names are "ftp", "HTTP", "imap", "ldap", "pop" and "smtp". This option
|
||||
allows you to change them.
|
||||
|
||||
The application does not have to keep the string around after setting this
|
||||
option.
|
||||
.SH DEFAULT
|
||||
See above
|
||||
.SH PROTOCOLS
|
||||
HTTP, FTP, IMAP, POP and SMTP
|
||||
HTTP, FTP, IMAP, LDAP, POP3 and SMTP
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
CURL *curl = curl_easy_init();
|
||||
@ -52,7 +52,8 @@ if(curl) {
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in 7.43.0 for HTTP, 7.49.0 for FTP, IMAP, POP3 and SMTP.
|
||||
Added in 7.43.0 for HTTP, 7.49.0 for FTP, IMAP, POP3 and SMTP,
|
||||
7.82.0 for OpenLDAP.
|
||||
.SH RETURN VALUE
|
||||
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
|
||||
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
|
||||
|
@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@ -31,18 +31,18 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_XOAUTH2_BEARER, char *token);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a char * as parameter, which should point to the null-terminated OAuth
|
||||
2.0 Bearer Access Token for use with HTTP, IMAP, POP3 and SMTP servers
|
||||
2.0 Bearer Access Token for use with HTTP, IMAP, LDAP, POP3 and SMTP servers
|
||||
that support the OAuth 2.0 Authorization Framework.
|
||||
|
||||
Note: For IMAP, POP3 and SMTP, the user name used to generate the Bearer Token
|
||||
should be supplied via the \fICURLOPT_USERNAME(3)\fP option.
|
||||
Note: For IMAP, LDAP, POP3 and SMTP, the user name used to generate the
|
||||
Bearer Token should be supplied via the \fICURLOPT_USERNAME(3)\fP option.
|
||||
|
||||
The application does not have to keep the string around after setting this
|
||||
option.
|
||||
.SH DEFAULT
|
||||
NULL
|
||||
.SH PROTOCOLS
|
||||
IMAP, POP3 and SMTP
|
||||
HTTP, IMAP, LDAP, POP3 and SMTP
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
CURL *curl = curl_easy_init();
|
||||
@ -54,7 +54,7 @@ if(curl) {
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in 7.33.0
|
||||
Added in 7.33.0. Support for OpenLAP added in 7.82.0.
|
||||
.SH RETURN VALUE
|
||||
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
|
||||
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
|
||||
|
322
lib/openldap.c
322
lib/openldap.c
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2011 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2011 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
@ -46,6 +46,8 @@
|
||||
#include "curl_ldap.h"
|
||||
#include "curl_base64.h"
|
||||
#include "connect.h"
|
||||
#include "curl_sasl.h"
|
||||
#include "strcase.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
@ -76,6 +78,8 @@ typedef enum {
|
||||
OLDAP_SSL, /* Performing SSL handshake. */
|
||||
OLDAP_STARTTLS, /* STARTTLS request sent. */
|
||||
OLDAP_TLS, /* Performing TLS handshake. */
|
||||
OLDAP_MECHS, /* Get SASL authentication mechanisms. */
|
||||
OLDAP_SASL, /* SASL binding reply. */
|
||||
OLDAP_BIND, /* Simple bind reply. */
|
||||
OLDAP_BINDV2, /* Simple bind reply in protocol version 2. */
|
||||
OLDAP_LAST /* Never used */
|
||||
@ -96,6 +100,13 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done);
|
||||
static CURLcode oldap_disconnect(struct Curl_easy *data,
|
||||
struct connectdata *conn, bool dead);
|
||||
|
||||
static CURLcode oldap_perform_auth(struct Curl_easy *data, const char *mech,
|
||||
const struct bufref *initresp);
|
||||
static CURLcode oldap_continue_auth(struct Curl_easy *data, const char *mech,
|
||||
const struct bufref *resp);
|
||||
static CURLcode oldap_cancel_auth(struct Curl_easy *data, const char *mech);
|
||||
static CURLcode oldap_get_message(struct Curl_easy *data, struct bufref *out);
|
||||
|
||||
static Curl_recv oldap_recv;
|
||||
|
||||
/*
|
||||
@ -154,10 +165,26 @@ const struct Curl_handler Curl_handler_ldaps = {
|
||||
};
|
||||
#endif
|
||||
|
||||
/* SASL parameters for the ldap protocol */
|
||||
static const struct SASLproto saslldap = {
|
||||
"ldap", /* The service name */
|
||||
oldap_perform_auth, /* Send authentication command */
|
||||
oldap_continue_auth, /* Send authentication continuation */
|
||||
oldap_cancel_auth, /* Send authentication cancellation */
|
||||
oldap_get_message, /* Get SASL response message */
|
||||
0, /* Maximum initial response length (no max) */
|
||||
LDAP_SASL_BIND_IN_PROGRESS, /* Code received when continuation is expected */
|
||||
LDAP_SUCCESS, /* Code to receive upon authentication success */
|
||||
SASL_AUTH_NONE, /* Default mechanisms */
|
||||
0 /* Configuration flags */
|
||||
};
|
||||
|
||||
struct ldapconninfo {
|
||||
struct SASL sasl; /* SASL-related parameters */
|
||||
LDAP *ld; /* Openldap connection handle. */
|
||||
Curl_recv *recv; /* For stacking SSL handler */
|
||||
Curl_send *send;
|
||||
struct berval *servercred; /* SASL data from server. */
|
||||
ldapstate state; /* Current machine state. */
|
||||
int proto; /* LDAP_PROTO_TCP/LDAP_PROTO_UDP/LDAP_PROTO_IPC */
|
||||
int msgid; /* Current message id. */
|
||||
@ -184,6 +211,8 @@ static void state(struct Curl_easy *data, ldapstate newstate)
|
||||
"SSL",
|
||||
"STARTTLS",
|
||||
"TLS",
|
||||
"MECHS",
|
||||
"SASL",
|
||||
"BIND",
|
||||
"BINDV2",
|
||||
/* LAST */
|
||||
@ -251,6 +280,37 @@ static CURLcode oldap_url_parse(struct Curl_easy *data, LDAPURLDesc **ludp)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Parse the login options. */
|
||||
static CURLcode oldap_parse_login_options(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
const char *ptr = conn->options;
|
||||
|
||||
while(!result && ptr && *ptr) {
|
||||
const char *key = ptr;
|
||||
const char *value;
|
||||
|
||||
while(*ptr && *ptr != '=')
|
||||
ptr++;
|
||||
|
||||
value = ptr + 1;
|
||||
|
||||
while(*ptr && *ptr != ';')
|
||||
ptr++;
|
||||
|
||||
if(checkprefix("AUTH=", key))
|
||||
result = Curl_sasl_parse_url_auth_option(&li->sasl, value, ptr - value);
|
||||
else
|
||||
result = CURLE_SETOPT_OPTION_SYNTAX;
|
||||
|
||||
if(*ptr == ';')
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return result == CURLE_URL_MALFORMAT? CURLE_SETOPT_OPTION_SYNTAX: result;
|
||||
}
|
||||
|
||||
static CURLcode oldap_setup_connection(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
@ -271,14 +331,94 @@ static CURLcode oldap_setup_connection(struct Curl_easy *data,
|
||||
conn->proto.ldapc = li;
|
||||
connkeep(conn, "OpenLDAP default");
|
||||
|
||||
/* Initialize the SASL storage */
|
||||
Curl_sasl_init(&li->sasl, data, &saslldap);
|
||||
|
||||
/* Clear the TLS upgraded flag */
|
||||
conn->bits.tls_upgraded = FALSE;
|
||||
|
||||
result = oldap_parse_login_options(conn);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the SASL authentication challenge from the server credential buffer.
|
||||
*/
|
||||
static CURLcode oldap_get_message(struct Curl_easy *data, struct bufref *out)
|
||||
{
|
||||
struct berval *servercred = data->conn->proto.ldapc->servercred;
|
||||
|
||||
if(!servercred || !servercred->bv_val)
|
||||
return CURLE_WEIRD_SERVER_REPLY;
|
||||
Curl_bufref_set(out, servercred->bv_val, servercred->bv_len, NULL);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sends an initial SASL bind request to the server.
|
||||
*/
|
||||
static CURLcode oldap_perform_auth(struct Curl_easy *data, const char *mech,
|
||||
const struct bufref *initresp)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
CURLcode result = CURLE_OK;
|
||||
struct berval cred;
|
||||
struct berval *pcred = &cred;
|
||||
int rc;
|
||||
|
||||
cred.bv_val = (char *) Curl_bufref_ptr(initresp);
|
||||
cred.bv_len = Curl_bufref_len(initresp);
|
||||
if(!cred.bv_val)
|
||||
pcred = NULL;
|
||||
rc = ldap_sasl_bind(li->ld, NULL, mech, pcred, NULL, NULL, &li->msgid);
|
||||
if(rc != LDAP_SUCCESS)
|
||||
result = oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sends SASL continuation.
|
||||
*/
|
||||
static CURLcode oldap_continue_auth(struct Curl_easy *data, const char *mech,
|
||||
const struct bufref *resp)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
CURLcode result = CURLE_OK;
|
||||
struct berval cred;
|
||||
struct berval *pcred = &cred;
|
||||
int rc;
|
||||
|
||||
cred.bv_val = (char *) Curl_bufref_ptr(resp);
|
||||
cred.bv_len = Curl_bufref_len(resp);
|
||||
if(!cred.bv_val)
|
||||
pcred = NULL;
|
||||
rc = ldap_sasl_bind(li->ld, NULL, mech, pcred, NULL, NULL, &li->msgid);
|
||||
if(rc != LDAP_SUCCESS)
|
||||
result = oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sends SASL bind cancellation.
|
||||
*/
|
||||
static CURLcode oldap_cancel_auth(struct Curl_easy *data, const char *mech)
|
||||
{
|
||||
struct ldapconninfo *li = data->conn->proto.ldapc;
|
||||
CURLcode result = CURLE_OK;
|
||||
int rc = ldap_sasl_bind(li->ld, NULL, LDAP_SASL_NULL, NULL, NULL, NULL,
|
||||
&li->msgid);
|
||||
|
||||
(void)mech;
|
||||
if(rc != LDAP_SUCCESS)
|
||||
result = oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Starts LDAP simple bind. */
|
||||
static CURLcode oldap_perform_bind(struct Curl_easy *data, ldapstate newstate)
|
||||
{
|
||||
@ -309,6 +449,40 @@ static CURLcode oldap_perform_bind(struct Curl_easy *data, ldapstate newstate)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Query the supported SASL authentication mechanisms. */
|
||||
static CURLcode oldap_perform_mechs(struct Curl_easy *data)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct ldapconninfo *li = data->conn->proto.ldapc;
|
||||
int rc;
|
||||
static const char * const supportedSASLMechanisms[] = {
|
||||
"supportedSASLMechanisms",
|
||||
NULL
|
||||
};
|
||||
|
||||
rc = ldap_search_ext(li->ld, "", LDAP_SCOPE_BASE, "(objectclass=*)",
|
||||
(char **) supportedSASLMechanisms, 0,
|
||||
NULL, NULL, NULL, 0, &li->msgid);
|
||||
if(rc == LDAP_SUCCESS)
|
||||
state(data, OLDAP_MECHS);
|
||||
else
|
||||
result = oldap_map_error(rc, CURLE_LOGIN_DENIED);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Starts SASL bind. */
|
||||
static CURLcode oldap_perform_sasl(struct Curl_easy *data)
|
||||
{
|
||||
saslprogress progress = SASL_IDLE;
|
||||
struct ldapconninfo *li = data->conn->proto.ldapc;
|
||||
CURLcode result = Curl_sasl_start(&li->sasl, data, TRUE, &progress);
|
||||
|
||||
state(data, OLDAP_SASL);
|
||||
if(!result && progress != SASL_INPROGRESS)
|
||||
result = CURLE_LOGIN_DENIED;
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef USE_SSL
|
||||
static Sockbuf_IO ldapsb_tls;
|
||||
|
||||
@ -414,11 +588,106 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
|
||||
}
|
||||
#endif
|
||||
|
||||
if(li->sasl.prefmech != SASL_AUTH_NONE)
|
||||
return oldap_perform_mechs(data);
|
||||
|
||||
/* Force bind even if anonymous bind is not needed in protocol version 3
|
||||
to detect missing version 3 support. */
|
||||
return oldap_perform_bind(data, OLDAP_BIND);
|
||||
}
|
||||
|
||||
/* Handle the supported SASL mechanisms query response */
|
||||
static CURLcode oldap_state_mechs_resp(struct Curl_easy *data,
|
||||
LDAPMessage *msg, int code)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
int rc;
|
||||
BerElement *ber = NULL;
|
||||
CURLcode result = CURLE_OK;
|
||||
struct berval bv, *bvals;
|
||||
|
||||
switch(ldap_msgtype(msg)) {
|
||||
case LDAP_RES_SEARCH_ENTRY:
|
||||
/* Got a list of supported SASL mechanisms. */
|
||||
if(code != LDAP_SUCCESS && code != LDAP_NO_RESULTS_RETURNED)
|
||||
return CURLE_LOGIN_DENIED;
|
||||
|
||||
rc = ldap_get_dn_ber(li->ld, msg, &ber, &bv);
|
||||
if(rc < 0)
|
||||
return oldap_map_error(rc, CURLE_BAD_CONTENT_ENCODING);
|
||||
for(rc = ldap_get_attribute_ber(li->ld, msg, ber, &bv, &bvals);
|
||||
rc == LDAP_SUCCESS;
|
||||
rc = ldap_get_attribute_ber(li->ld, msg, ber, &bv, &bvals)) {
|
||||
int i;
|
||||
|
||||
if(!bv.bv_val)
|
||||
break;
|
||||
|
||||
if(bvals) {
|
||||
for(i = 0; bvals[i].bv_val; i++) {
|
||||
size_t llen;
|
||||
unsigned short mech = Curl_sasl_decode_mech((char *) bvals[i].bv_val,
|
||||
bvals[i].bv_len, &llen);
|
||||
if(bvals[i].bv_len == llen)
|
||||
li->sasl.authmechs |= mech;
|
||||
}
|
||||
ber_memfree(bvals);
|
||||
}
|
||||
}
|
||||
ber_free(ber, 0);
|
||||
break;
|
||||
|
||||
case LDAP_RES_SEARCH_RESULT:
|
||||
switch(code) {
|
||||
case LDAP_SIZELIMIT_EXCEEDED:
|
||||
infof(data, "Too many authentication mechanisms\n");
|
||||
/* FALLTHROUGH */
|
||||
case LDAP_SUCCESS:
|
||||
case LDAP_NO_RESULTS_RETURNED:
|
||||
if(Curl_sasl_can_authenticate(&li->sasl, conn))
|
||||
result = oldap_perform_sasl(data);
|
||||
else
|
||||
result = CURLE_LOGIN_DENIED;
|
||||
break;
|
||||
default:
|
||||
result = oldap_map_error(code, CURLE_LOGIN_DENIED);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Handle a SASL bind response. */
|
||||
static CURLcode oldap_state_sasl_resp(struct Curl_easy *data,
|
||||
LDAPMessage *msg, int code)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
CURLcode result = CURLE_OK;
|
||||
saslprogress progress;
|
||||
int rc;
|
||||
|
||||
li->servercred = NULL;
|
||||
rc = ldap_parse_sasl_bind_result(li->ld, msg, &li->servercred, 0);
|
||||
if(rc != LDAP_SUCCESS) {
|
||||
failf(data, "LDAP local: sasl ldap_parse_result %s", ldap_err2string(rc));
|
||||
result = oldap_map_error(rc, CURLE_LOGIN_DENIED);
|
||||
}
|
||||
else {
|
||||
result = Curl_sasl_continue(&li->sasl, data, code, &progress);
|
||||
if(!result && progress != SASL_INPROGRESS)
|
||||
state(data, OLDAP_STOP);
|
||||
}
|
||||
|
||||
if(li->servercred)
|
||||
ber_bvfree(li->servercred);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Handle a simple bind response. */
|
||||
static CURLcode oldap_state_bind_resp(struct Curl_easy *data, LDAPMessage *msg,
|
||||
int code)
|
||||
@ -459,12 +728,20 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
|
||||
if(li->state != OLDAP_SSL && li->state != OLDAP_TLS) {
|
||||
/* Get response to last command. */
|
||||
rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, &tv, &msg);
|
||||
if(!rc)
|
||||
return CURLE_OK; /* Timed out. */
|
||||
if(rc < 0) {
|
||||
failf(data, "LDAP local: connecting ldap_result %s",
|
||||
ldap_err2string(rc));
|
||||
return oldap_map_error(rc, CURLE_COULDNT_CONNECT);
|
||||
switch(rc) {
|
||||
case 0: /* Timed out. */
|
||||
return CURLE_OK;
|
||||
case LDAP_RES_SEARCH_ENTRY:
|
||||
case LDAP_RES_SEARCH_REFERENCE:
|
||||
break;
|
||||
default:
|
||||
li->msgid = 0; /* Nothing to abandon upon error. */
|
||||
if(rc < 0) {
|
||||
failf(data, "LDAP local: connecting ldap_result %s",
|
||||
ldap_err2string(rc));
|
||||
return oldap_map_error(rc, CURLE_COULDNT_CONNECT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get error code from message. */
|
||||
@ -477,11 +754,11 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
|
||||
}
|
||||
|
||||
/* If protocol version 3 is not supported, fallback to version 2. */
|
||||
if(code == LDAP_PROTOCOL_ERROR && li->state != OLDAP_BINDV2
|
||||
if(code == LDAP_PROTOCOL_ERROR && li->state != OLDAP_BINDV2 &&
|
||||
#ifdef USE_SSL
|
||||
&& (ssl_installed(conn) || data->set.use_ssl <= CURLUSESSL_TRY)
|
||||
(ssl_installed(conn) || data->set.use_ssl <= CURLUSESSL_TRY) &&
|
||||
#endif
|
||||
) {
|
||||
li->sasl.prefmech == SASL_AUTH_NONE) {
|
||||
static const int version = LDAP_VERSION2;
|
||||
|
||||
ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
|
||||
@ -496,13 +773,19 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
|
||||
#ifdef USE_SSL
|
||||
case OLDAP_SSL:
|
||||
result = oldap_ssl_connect(data, OLDAP_SSL);
|
||||
if(!result && ssl_installed(conn))
|
||||
result = oldap_perform_bind(data, OLDAP_BIND);
|
||||
if(!result && ssl_installed(conn)) {
|
||||
if(li->sasl.prefmech != SASL_AUTH_NONE)
|
||||
result = oldap_perform_mechs(data);
|
||||
else
|
||||
result = oldap_perform_bind(data, OLDAP_BIND);
|
||||
}
|
||||
break;
|
||||
case OLDAP_STARTTLS:
|
||||
if(code != LDAP_SUCCESS) {
|
||||
if(data->set.use_ssl != CURLUSESSL_TRY)
|
||||
result = oldap_map_error(code, CURLE_USE_SSL_FAILED);
|
||||
else if(li->sasl.prefmech != SASL_AUTH_NONE)
|
||||
result = oldap_perform_mechs(data);
|
||||
else
|
||||
result = oldap_perform_bind(data, OLDAP_BIND);
|
||||
break;
|
||||
@ -514,7 +797,9 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
|
||||
result = oldap_map_error(code, CURLE_USE_SSL_FAILED);
|
||||
else if(ssl_installed(conn)) {
|
||||
conn->bits.tls_upgraded = TRUE;
|
||||
if(conn->bits.user_passwd)
|
||||
if(li->sasl.prefmech != SASL_AUTH_NONE)
|
||||
result = oldap_perform_mechs(data);
|
||||
else if(conn->bits.user_passwd)
|
||||
result = oldap_perform_bind(data, OLDAP_BIND);
|
||||
else {
|
||||
state(data, OLDAP_STOP); /* Version 3 supported: no bind required */
|
||||
@ -524,6 +809,12 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
|
||||
break;
|
||||
#endif
|
||||
|
||||
case OLDAP_MECHS:
|
||||
result = oldap_state_mechs_resp(data, msg, code);
|
||||
break;
|
||||
case OLDAP_SASL:
|
||||
result = oldap_state_sasl_resp(data, msg, code);
|
||||
break;
|
||||
case OLDAP_BIND:
|
||||
case OLDAP_BINDV2:
|
||||
result = oldap_state_bind_resp(data, msg, code);
|
||||
@ -540,6 +831,10 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
|
||||
if(*done)
|
||||
conn->recv[FIRSTSOCKET] = oldap_recv;
|
||||
|
||||
if(result && li->msgid) {
|
||||
ldap_abandon_ext(li->ld, li->msgid, NULL, NULL);
|
||||
li->msgid = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -562,6 +857,7 @@ static CURLcode oldap_disconnect(struct Curl_easy *data,
|
||||
ldap_unbind_ext(li->ld, NULL, NULL);
|
||||
li->ld = NULL;
|
||||
}
|
||||
Curl_sasl_cleanup(conn, li->sasl.authused);
|
||||
conn->proto.ldapc = NULL;
|
||||
free(li);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user