mirror of
https://github.com/curl/curl.git
synced 2026-08-05 09:06:18 +03: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
8 changed files with 332 additions and 35 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
Long: login-options
|
Long: login-options
|
||||||
Arg: <options>
|
Arg: <options>
|
||||||
Protocols: IMAP POP3 SMTP
|
Protocols: IMAP LDAP POP3 SMTP
|
||||||
Help: Server login options
|
Help: Server login options
|
||||||
Added: 7.34.0
|
Added: 7.34.0
|
||||||
Category: imap pop3 smtp auth
|
Category: imap pop3 smtp auth
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Long: oauth2-bearer
|
Long: oauth2-bearer
|
||||||
Help: OAuth 2 Bearer Token
|
Help: OAuth 2 Bearer Token
|
||||||
Arg: <token>
|
Arg: <token>
|
||||||
Protocols: IMAP POP3 SMTP HTTP
|
Protocols: IMAP LDAP POP3 SMTP HTTP
|
||||||
Category: auth
|
Category: auth
|
||||||
Example: --oauth2-bearer "mF_9.B5f-4.1JqM" $URL
|
Example: --oauth2-bearer "mF_9.B5f-4.1JqM" $URL
|
||||||
Added: 7.33.0
|
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
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * you should have received as part of this distribution. The terms
|
||||||
|
|
@ -172,8 +172,8 @@ supports IPv6
|
||||||
.IP CURL_VERSION_KERBEROS4
|
.IP CURL_VERSION_KERBEROS4
|
||||||
supports Kerberos V4 (when using FTP). Legacy bit. Deprecated since 7.33.0.
|
supports Kerberos V4 (when using FTP). Legacy bit. Deprecated since 7.33.0.
|
||||||
.IP CURL_VERSION_KERBEROS5
|
.IP CURL_VERSION_KERBEROS5
|
||||||
supports Kerberos V5 authentication for FTP, IMAP, POP3, SMTP and SOCKSv5 proxy
|
supports Kerberos V5 authentication for FTP, IMAP, LDAP, POP3, SMTP and
|
||||||
(Added in 7.40.0)
|
SOCKSv5 proxy. (Added in 7.40.0)
|
||||||
.IP CURL_VERSION_LARGEFILE
|
.IP CURL_VERSION_LARGEFILE
|
||||||
libcurl was built with support for large files. (Added in 7.11.1)
|
libcurl was built with support for large files. (Added in 7.11.1)
|
||||||
.IP CURL_VERSION_UNICODE
|
.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
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * you should have received as part of this distribution. The terms
|
||||||
|
|
@ -46,7 +46,7 @@ option.
|
||||||
.SH DEFAULT
|
.SH DEFAULT
|
||||||
NULL
|
NULL
|
||||||
.SH PROTOCOLS
|
.SH PROTOCOLS
|
||||||
Only IMAP, POP3 and SMTP support login options.
|
Only IMAP, LDAP, POP3 and SMTP support login options.
|
||||||
.SH EXAMPLE
|
.SH EXAMPLE
|
||||||
.nf
|
.nf
|
||||||
CURL *curl = curl_easy_init();
|
CURL *curl = curl_easy_init();
|
||||||
|
|
@ -58,7 +58,7 @@ if(curl) {
|
||||||
}
|
}
|
||||||
.fi
|
.fi
|
||||||
.SH AVAILABILITY
|
.SH AVAILABILITY
|
||||||
Added in 7.34.0
|
Added in 7.34.0. Support for OpenLDAP added in 7.82.0.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
|
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
|
||||||
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
|
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
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * you should have received as part of this distribution. The terms
|
||||||
|
|
@ -45,7 +45,7 @@ or a shared mailbox for example.
|
||||||
.SH DEFAULT
|
.SH DEFAULT
|
||||||
blank
|
blank
|
||||||
.SH PROTOCOLS
|
.SH PROTOCOLS
|
||||||
IMAP, POP3 and SMTP
|
IMAP, LDAP, POP3 and SMTP
|
||||||
.SH EXAMPLE
|
.SH EXAMPLE
|
||||||
.nf
|
.nf
|
||||||
CURL *curl = curl_easy_init();
|
CURL *curl = curl_easy_init();
|
||||||
|
|
@ -59,7 +59,7 @@ if(curl) {
|
||||||
}
|
}
|
||||||
.fi
|
.fi
|
||||||
.SH AVAILABILITY
|
.SH AVAILABILITY
|
||||||
Added in 7.66.0
|
Added in 7.66.0. Support for OpenLDAP added in 7.82.0.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
|
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
|
||||||
.SH "SEE ALSO"
|
.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
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * 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
|
.SH DESCRIPTION
|
||||||
Pass a char * as parameter to a string holding the \fIname\fP of the service
|
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
|
for DIGEST-MD5, SPNEGO and Kerberos 5 authentication mechanisms. The default
|
||||||
service names are "ftp", "HTTP", "imap", "pop" and "smtp". This option allows
|
service names are "ftp", "HTTP", "imap", "ldap", "pop" and "smtp". This option
|
||||||
you to change them.
|
allows you to change them.
|
||||||
|
|
||||||
The application does not have to keep the string around after setting this
|
The application does not have to keep the string around after setting this
|
||||||
option.
|
option.
|
||||||
.SH DEFAULT
|
.SH DEFAULT
|
||||||
See above
|
See above
|
||||||
.SH PROTOCOLS
|
.SH PROTOCOLS
|
||||||
HTTP, FTP, IMAP, POP and SMTP
|
HTTP, FTP, IMAP, LDAP, POP3 and SMTP
|
||||||
.SH EXAMPLE
|
.SH EXAMPLE
|
||||||
.nf
|
.nf
|
||||||
CURL *curl = curl_easy_init();
|
CURL *curl = curl_easy_init();
|
||||||
|
|
@ -52,7 +52,8 @@ if(curl) {
|
||||||
}
|
}
|
||||||
.fi
|
.fi
|
||||||
.SH AVAILABILITY
|
.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
|
.SH RETURN VALUE
|
||||||
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
|
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
|
||||||
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
|
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
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * 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
|
.fi
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
Pass a char * as parameter, which should point to the null-terminated OAuth
|
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.
|
that support the OAuth 2.0 Authorization Framework.
|
||||||
|
|
||||||
Note: For IMAP, POP3 and SMTP, the user name used to generate the Bearer Token
|
Note: For IMAP, LDAP, POP3 and SMTP, the user name used to generate the
|
||||||
should be supplied via the \fICURLOPT_USERNAME(3)\fP option.
|
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
|
The application does not have to keep the string around after setting this
|
||||||
option.
|
option.
|
||||||
.SH DEFAULT
|
.SH DEFAULT
|
||||||
NULL
|
NULL
|
||||||
.SH PROTOCOLS
|
.SH PROTOCOLS
|
||||||
IMAP, POP3 and SMTP
|
HTTP, IMAP, LDAP, POP3 and SMTP
|
||||||
.SH EXAMPLE
|
.SH EXAMPLE
|
||||||
.nf
|
.nf
|
||||||
CURL *curl = curl_easy_init();
|
CURL *curl = curl_easy_init();
|
||||||
|
|
@ -54,7 +54,7 @@ if(curl) {
|
||||||
}
|
}
|
||||||
.fi
|
.fi
|
||||||
.SH AVAILABILITY
|
.SH AVAILABILITY
|
||||||
Added in 7.33.0
|
Added in 7.33.0. Support for OpenLAP added in 7.82.0.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
|
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
|
||||||
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
|
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>
|
* Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
|
@ -46,6 +46,8 @@
|
||||||
#include "curl_ldap.h"
|
#include "curl_ldap.h"
|
||||||
#include "curl_base64.h"
|
#include "curl_base64.h"
|
||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
|
#include "curl_sasl.h"
|
||||||
|
#include "strcase.h"
|
||||||
/* The last 3 #include files should be in this order */
|
/* The last 3 #include files should be in this order */
|
||||||
#include "curl_printf.h"
|
#include "curl_printf.h"
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
|
|
@ -76,6 +78,8 @@ typedef enum {
|
||||||
OLDAP_SSL, /* Performing SSL handshake. */
|
OLDAP_SSL, /* Performing SSL handshake. */
|
||||||
OLDAP_STARTTLS, /* STARTTLS request sent. */
|
OLDAP_STARTTLS, /* STARTTLS request sent. */
|
||||||
OLDAP_TLS, /* Performing TLS handshake. */
|
OLDAP_TLS, /* Performing TLS handshake. */
|
||||||
|
OLDAP_MECHS, /* Get SASL authentication mechanisms. */
|
||||||
|
OLDAP_SASL, /* SASL binding reply. */
|
||||||
OLDAP_BIND, /* Simple bind reply. */
|
OLDAP_BIND, /* Simple bind reply. */
|
||||||
OLDAP_BINDV2, /* Simple bind reply in protocol version 2. */
|
OLDAP_BINDV2, /* Simple bind reply in protocol version 2. */
|
||||||
OLDAP_LAST /* Never used */
|
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,
|
static CURLcode oldap_disconnect(struct Curl_easy *data,
|
||||||
struct connectdata *conn, bool dead);
|
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;
|
static Curl_recv oldap_recv;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -154,10 +165,26 @@ const struct Curl_handler Curl_handler_ldaps = {
|
||||||
};
|
};
|
||||||
#endif
|
#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 ldapconninfo {
|
||||||
|
struct SASL sasl; /* SASL-related parameters */
|
||||||
LDAP *ld; /* Openldap connection handle. */
|
LDAP *ld; /* Openldap connection handle. */
|
||||||
Curl_recv *recv; /* For stacking SSL handler */
|
Curl_recv *recv; /* For stacking SSL handler */
|
||||||
Curl_send *send;
|
Curl_send *send;
|
||||||
|
struct berval *servercred; /* SASL data from server. */
|
||||||
ldapstate state; /* Current machine state. */
|
ldapstate state; /* Current machine state. */
|
||||||
int proto; /* LDAP_PROTO_TCP/LDAP_PROTO_UDP/LDAP_PROTO_IPC */
|
int proto; /* LDAP_PROTO_TCP/LDAP_PROTO_UDP/LDAP_PROTO_IPC */
|
||||||
int msgid; /* Current message id. */
|
int msgid; /* Current message id. */
|
||||||
|
|
@ -184,6 +211,8 @@ static void state(struct Curl_easy *data, ldapstate newstate)
|
||||||
"SSL",
|
"SSL",
|
||||||
"STARTTLS",
|
"STARTTLS",
|
||||||
"TLS",
|
"TLS",
|
||||||
|
"MECHS",
|
||||||
|
"SASL",
|
||||||
"BIND",
|
"BIND",
|
||||||
"BINDV2",
|
"BINDV2",
|
||||||
/* LAST */
|
/* LAST */
|
||||||
|
|
@ -251,6 +280,37 @@ static CURLcode oldap_url_parse(struct Curl_easy *data, LDAPURLDesc **ludp)
|
||||||
return result;
|
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,
|
static CURLcode oldap_setup_connection(struct Curl_easy *data,
|
||||||
struct connectdata *conn)
|
struct connectdata *conn)
|
||||||
{
|
{
|
||||||
|
|
@ -271,14 +331,94 @@ static CURLcode oldap_setup_connection(struct Curl_easy *data,
|
||||||
conn->proto.ldapc = li;
|
conn->proto.ldapc = li;
|
||||||
connkeep(conn, "OpenLDAP default");
|
connkeep(conn, "OpenLDAP default");
|
||||||
|
|
||||||
|
/* Initialize the SASL storage */
|
||||||
|
Curl_sasl_init(&li->sasl, data, &saslldap);
|
||||||
|
|
||||||
/* Clear the TLS upgraded flag */
|
/* Clear the TLS upgraded flag */
|
||||||
conn->bits.tls_upgraded = FALSE;
|
conn->bits.tls_upgraded = FALSE;
|
||||||
|
|
||||||
|
result = oldap_parse_login_options(conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
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. */
|
/* Starts LDAP simple bind. */
|
||||||
static CURLcode oldap_perform_bind(struct Curl_easy *data, ldapstate newstate)
|
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;
|
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
|
#ifdef USE_SSL
|
||||||
static Sockbuf_IO ldapsb_tls;
|
static Sockbuf_IO ldapsb_tls;
|
||||||
|
|
||||||
|
|
@ -414,11 +588,106 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
/* Force bind even if anonymous bind is not needed in protocol version 3
|
||||||
to detect missing version 3 support. */
|
to detect missing version 3 support. */
|
||||||
return oldap_perform_bind(data, OLDAP_BIND);
|
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. */
|
/* Handle a simple bind response. */
|
||||||
static CURLcode oldap_state_bind_resp(struct Curl_easy *data, LDAPMessage *msg,
|
static CURLcode oldap_state_bind_resp(struct Curl_easy *data, LDAPMessage *msg,
|
||||||
int code)
|
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) {
|
if(li->state != OLDAP_SSL && li->state != OLDAP_TLS) {
|
||||||
/* Get response to last command. */
|
/* Get response to last command. */
|
||||||
rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, &tv, &msg);
|
rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, &tv, &msg);
|
||||||
if(!rc)
|
switch(rc) {
|
||||||
return CURLE_OK; /* Timed out. */
|
case 0: /* Timed out. */
|
||||||
if(rc < 0) {
|
return CURLE_OK;
|
||||||
failf(data, "LDAP local: connecting ldap_result %s",
|
case LDAP_RES_SEARCH_ENTRY:
|
||||||
ldap_err2string(rc));
|
case LDAP_RES_SEARCH_REFERENCE:
|
||||||
return oldap_map_error(rc, CURLE_COULDNT_CONNECT);
|
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. */
|
/* 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 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
|
#ifdef USE_SSL
|
||||||
&& (ssl_installed(conn) || data->set.use_ssl <= CURLUSESSL_TRY)
|
(ssl_installed(conn) || data->set.use_ssl <= CURLUSESSL_TRY) &&
|
||||||
#endif
|
#endif
|
||||||
) {
|
li->sasl.prefmech == SASL_AUTH_NONE) {
|
||||||
static const int version = LDAP_VERSION2;
|
static const int version = LDAP_VERSION2;
|
||||||
|
|
||||||
ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
|
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
|
#ifdef USE_SSL
|
||||||
case OLDAP_SSL:
|
case OLDAP_SSL:
|
||||||
result = oldap_ssl_connect(data, OLDAP_SSL);
|
result = oldap_ssl_connect(data, OLDAP_SSL);
|
||||||
if(!result && ssl_installed(conn))
|
if(!result && ssl_installed(conn)) {
|
||||||
result = oldap_perform_bind(data, OLDAP_BIND);
|
if(li->sasl.prefmech != SASL_AUTH_NONE)
|
||||||
|
result = oldap_perform_mechs(data);
|
||||||
|
else
|
||||||
|
result = oldap_perform_bind(data, OLDAP_BIND);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case OLDAP_STARTTLS:
|
case OLDAP_STARTTLS:
|
||||||
if(code != LDAP_SUCCESS) {
|
if(code != LDAP_SUCCESS) {
|
||||||
if(data->set.use_ssl != CURLUSESSL_TRY)
|
if(data->set.use_ssl != CURLUSESSL_TRY)
|
||||||
result = oldap_map_error(code, CURLE_USE_SSL_FAILED);
|
result = oldap_map_error(code, CURLE_USE_SSL_FAILED);
|
||||||
|
else if(li->sasl.prefmech != SASL_AUTH_NONE)
|
||||||
|
result = oldap_perform_mechs(data);
|
||||||
else
|
else
|
||||||
result = oldap_perform_bind(data, OLDAP_BIND);
|
result = oldap_perform_bind(data, OLDAP_BIND);
|
||||||
break;
|
break;
|
||||||
|
|
@ -514,7 +797,9 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
|
||||||
result = oldap_map_error(code, CURLE_USE_SSL_FAILED);
|
result = oldap_map_error(code, CURLE_USE_SSL_FAILED);
|
||||||
else if(ssl_installed(conn)) {
|
else if(ssl_installed(conn)) {
|
||||||
conn->bits.tls_upgraded = TRUE;
|
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);
|
result = oldap_perform_bind(data, OLDAP_BIND);
|
||||||
else {
|
else {
|
||||||
state(data, OLDAP_STOP); /* Version 3 supported: no bind required */
|
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;
|
break;
|
||||||
#endif
|
#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_BIND:
|
||||||
case OLDAP_BINDV2:
|
case OLDAP_BINDV2:
|
||||||
result = oldap_state_bind_resp(data, msg, code);
|
result = oldap_state_bind_resp(data, msg, code);
|
||||||
|
|
@ -540,6 +831,10 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
|
||||||
if(*done)
|
if(*done)
|
||||||
conn->recv[FIRSTSOCKET] = oldap_recv;
|
conn->recv[FIRSTSOCKET] = oldap_recv;
|
||||||
|
|
||||||
|
if(result && li->msgid) {
|
||||||
|
ldap_abandon_ext(li->ld, li->msgid, NULL, NULL);
|
||||||
|
li->msgid = 0;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -562,6 +857,7 @@ static CURLcode oldap_disconnect(struct Curl_easy *data,
|
||||||
ldap_unbind_ext(li->ld, NULL, NULL);
|
ldap_unbind_ext(li->ld, NULL, NULL);
|
||||||
li->ld = NULL;
|
li->ld = NULL;
|
||||||
}
|
}
|
||||||
|
Curl_sasl_cleanup(conn, li->sasl.authused);
|
||||||
conn->proto.ldapc = NULL;
|
conn->proto.ldapc = NULL;
|
||||||
free(li);
|
free(li);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue