openldap: implement STARTTLS
As this introduces use of CURLOPT_USE_SSL option for LDAP, also check this option in ldap.c as it is not supported by this backend. Closes #8065
This commit is contained in:
parent
a6e2643433
commit
a40160aee8
@ -1,6 +1,6 @@
|
|||||||
Long: ssl-reqd
|
Long: ssl-reqd
|
||||||
Help: Require SSL/TLS
|
Help: Require SSL/TLS
|
||||||
Protocols: FTP IMAP POP3 SMTP
|
Protocols: FTP IMAP POP3 SMTP LDAP
|
||||||
Added: 7.20.0
|
Added: 7.20.0
|
||||||
Category: tls
|
Category: tls
|
||||||
Example: --ssl-reqd ftp://example.com
|
Example: --ssl-reqd ftp://example.com
|
||||||
@ -9,4 +9,8 @@ See-also: ssl insecure
|
|||||||
Require SSL/TLS for the connection. Terminates the connection if the server
|
Require SSL/TLS for the connection. Terminates the connection if the server
|
||||||
does not support SSL/TLS.
|
does not support SSL/TLS.
|
||||||
|
|
||||||
|
This option is handled in LDAP since version 7.81.0. It is fully supported
|
||||||
|
by the openldap backend and rejected by the generic ldap backend if explicit
|
||||||
|
TLS is required.
|
||||||
|
|
||||||
This option was formerly known as --ftp-ssl-reqd.
|
This option was formerly known as --ftp-ssl-reqd.
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
Long: ssl
|
Long: ssl
|
||||||
Help: Try SSL/TLS
|
Help: Try SSL/TLS
|
||||||
Protocols: FTP IMAP POP3 SMTP
|
Protocols: FTP IMAP POP3 SMTP LDAP
|
||||||
Added: 7.20.0
|
Added: 7.20.0
|
||||||
Category: tls
|
Category: tls
|
||||||
Example: --ssl pop3://example.com/
|
Example: --ssl pop3://example.com/
|
||||||
@ -10,5 +10,11 @@ Try to use SSL/TLS for the connection. Reverts to a non-secure connection if
|
|||||||
the server does not support SSL/TLS. See also --ftp-ssl-control and --ssl-reqd
|
the server does not support SSL/TLS. See also --ftp-ssl-control and --ssl-reqd
|
||||||
for different levels of encryption required.
|
for different levels of encryption required.
|
||||||
|
|
||||||
|
This option is handled in LDAP since version 7.81.0. It is fully supported
|
||||||
|
by the openldap backend and ignored by the generic ldap backend.
|
||||||
|
|
||||||
|
Please note that a server may close the connection if the negotiation does
|
||||||
|
not succeed.
|
||||||
|
|
||||||
This option was formerly known as --ftp-ssl (Added in 7.11.0). That option
|
This option was formerly known as --ftp-ssl (Added in 7.11.0). That option
|
||||||
name can still be used but will be removed in a future version.
|
name can still be used but will be removed in a future version.
|
||||||
|
|||||||
@ -40,7 +40,8 @@ This is for enabling SSL/TLS when you use FTP, SMTP, POP3, IMAP etc.
|
|||||||
.IP CURLUSESSL_NONE
|
.IP CURLUSESSL_NONE
|
||||||
do not attempt to use SSL.
|
do not attempt to use SSL.
|
||||||
.IP CURLUSESSL_TRY
|
.IP CURLUSESSL_TRY
|
||||||
Try using SSL, proceed as normal otherwise.
|
Try using SSL, proceed as normal otherwise. Note that server may close the
|
||||||
|
connection if the negotiation does not succeed.
|
||||||
.IP CURLUSESSL_CONTROL
|
.IP CURLUSESSL_CONTROL
|
||||||
Require SSL for the control connection or fail with \fICURLE_USE_SSL_FAILED\fP.
|
Require SSL for the control connection or fail with \fICURLE_USE_SSL_FAILED\fP.
|
||||||
.IP CURLUSESSL_ALL
|
.IP CURLUSESSL_ALL
|
||||||
@ -48,7 +49,7 @@ Require SSL for all communication or fail with \fICURLE_USE_SSL_FAILED\fP.
|
|||||||
.SH DEFAULT
|
.SH DEFAULT
|
||||||
CURLUSESSL_NONE
|
CURLUSESSL_NONE
|
||||||
.SH PROTOCOLS
|
.SH PROTOCOLS
|
||||||
FTP, SMTP, POP3, IMAP
|
FTP, SMTP, POP3, IMAP, LDAP
|
||||||
.SH EXAMPLE
|
.SH EXAMPLE
|
||||||
.nf
|
.nf
|
||||||
CURL *curl = curl_easy_init();
|
CURL *curl = curl_easy_init();
|
||||||
@ -65,6 +66,7 @@ if(curl) {
|
|||||||
.SH AVAILABILITY
|
.SH AVAILABILITY
|
||||||
Added in 7.11.0. This option was known as CURLOPT_FTP_SSL up to 7.16.4, and
|
Added in 7.11.0. This option was known as CURLOPT_FTP_SSL up to 7.16.4, and
|
||||||
the constants were known as CURLFTPSSL_*
|
the constants were known as CURLFTPSSL_*
|
||||||
|
Handled by LDAP since 7.81.0. Fully supported by the openldap backend only.
|
||||||
.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"
|
||||||
|
|||||||
@ -464,6 +464,11 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
|
|||||||
#endif
|
#endif
|
||||||
#endif /* CURL_LDAP_USE_SSL */
|
#endif /* CURL_LDAP_USE_SSL */
|
||||||
}
|
}
|
||||||
|
else if(data->set.use_ssl > CURLUSESSL_TRY) {
|
||||||
|
failf(data, "LDAP local: explicit TLS not supported");
|
||||||
|
result = CURLE_NOT_BUILT_IN;
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
server = ldap_init(host, (int)conn->port);
|
server = ldap_init(host, (int)conn->port);
|
||||||
if(!server) {
|
if(!server) {
|
||||||
|
|||||||
@ -74,6 +74,8 @@
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
OLDAP_STOP, /* Do nothing state, stops the state machine */
|
OLDAP_STOP, /* Do nothing state, stops the state machine */
|
||||||
OLDAP_SSL, /* Performing SSL handshake. */
|
OLDAP_SSL, /* Performing SSL handshake. */
|
||||||
|
OLDAP_STARTTLS, /* STARTTLS request sent. */
|
||||||
|
OLDAP_TLS, /* Performing TLS handshake. */
|
||||||
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 */
|
||||||
@ -194,6 +196,8 @@ static void state(struct Curl_easy *data, ldapstate newstate)
|
|||||||
static const char * const names[] = {
|
static const char * const names[] = {
|
||||||
"STOP",
|
"STOP",
|
||||||
"SSL",
|
"SSL",
|
||||||
|
"STARTTLS",
|
||||||
|
"TLS",
|
||||||
"BIND",
|
"BIND",
|
||||||
"BINDV2",
|
"BINDV2",
|
||||||
/* LAST */
|
/* LAST */
|
||||||
@ -256,6 +260,10 @@ static CURLcode oldap_setup_connection(struct Curl_easy *data,
|
|||||||
li->proto = proto;
|
li->proto = proto;
|
||||||
conn->proto.ldapc = li;
|
conn->proto.ldapc = li;
|
||||||
connkeep(conn, "OpenLDAP default");
|
connkeep(conn, "OpenLDAP default");
|
||||||
|
|
||||||
|
/* Clear the TLS upgraded flag */
|
||||||
|
conn->bits.tls_upgraded = FALSE;
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,7 +305,7 @@ static bool ssl_installed(struct connectdata *conn)
|
|||||||
return conn->proto.ldapc->recv != NULL;
|
return conn->proto.ldapc->recv != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode oldap_ssl_connect(struct Curl_easy *data)
|
static CURLcode oldap_ssl_connect(struct Curl_easy *data, ldapstate newstate)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
struct connectdata *conn = data->conn;
|
struct connectdata *conn = data->conn;
|
||||||
@ -307,7 +315,7 @@ static CURLcode oldap_ssl_connect(struct Curl_easy *data)
|
|||||||
result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
|
result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
|
||||||
FIRSTSOCKET, &ssldone);
|
FIRSTSOCKET, &ssldone);
|
||||||
if(!result) {
|
if(!result) {
|
||||||
state(data, OLDAP_SSL);
|
state(data, newstate);
|
||||||
|
|
||||||
if(ssldone) {
|
if(ssldone) {
|
||||||
Sockbuf *sb;
|
Sockbuf *sb;
|
||||||
@ -322,6 +330,20 @@ static CURLcode oldap_ssl_connect(struct Curl_easy *data)
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Send the STARTTLS request */
|
||||||
|
static CURLcode oldap_perform_starttls(struct Curl_easy *data)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct ldapconninfo *li = data->conn->proto.ldapc;
|
||||||
|
int rc = ldap_start_tls(li->ld, NULL, NULL, &li->msgid);
|
||||||
|
|
||||||
|
if(rc == LDAP_SUCCESS)
|
||||||
|
state(data, OLDAP_STARTTLS);
|
||||||
|
else
|
||||||
|
result = oldap_map_error(rc, CURLE_USE_SSL_FAILED);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
|
static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
|
||||||
@ -364,7 +386,14 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
|
|||||||
|
|
||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
if(conn->handler->flags & PROTOPT_SSL)
|
if(conn->handler->flags & PROTOPT_SSL)
|
||||||
return oldap_ssl_connect(data);
|
return oldap_ssl_connect(data, OLDAP_SSL);
|
||||||
|
|
||||||
|
if(data->set.use_ssl) {
|
||||||
|
CURLcode result = oldap_perform_starttls(data);
|
||||||
|
|
||||||
|
if(!result || data->set.use_ssl != CURLUSESSL_TRY)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* 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
|
||||||
@ -409,7 +438,7 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
|
|||||||
int code = LDAP_SUCCESS;
|
int code = LDAP_SUCCESS;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if(li->state != OLDAP_SSL) {
|
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)
|
if(!rc)
|
||||||
@ -426,7 +455,11 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
|
|||||||
code = rc;
|
code = rc;
|
||||||
|
|
||||||
/* 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
|
||||||
|
&& (ssl_installed(conn) || data->set.use_ssl <= CURLUSESSL_TRY)
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
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);
|
||||||
@ -440,10 +473,33 @@ 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);
|
result = oldap_ssl_connect(data, OLDAP_SSL);
|
||||||
if(!result && ssl_installed(conn))
|
if(!result && ssl_installed(conn))
|
||||||
result = oldap_perform_bind(data, OLDAP_BIND);
|
result = oldap_perform_bind(data, OLDAP_BIND);
|
||||||
break;
|
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
|
||||||
|
result = oldap_perform_bind(data, OLDAP_BIND);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case OLDAP_TLS:
|
||||||
|
result = oldap_ssl_connect(data, OLDAP_TLS);
|
||||||
|
if(result && data->set.use_ssl != CURLUSESSL_TRY)
|
||||||
|
result = oldap_map_error(code, CURLE_USE_SSL_FAILED);
|
||||||
|
else if(ssl_installed(conn)) {
|
||||||
|
conn->bits.tls_upgraded = TRUE;
|
||||||
|
if(conn->bits.user_passwd)
|
||||||
|
result = oldap_perform_bind(data, OLDAP_BIND);
|
||||||
|
else {
|
||||||
|
state(data, OLDAP_STOP); /* Version 3 supported: no bind required */
|
||||||
|
result = CURLE_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case OLDAP_BIND:
|
case OLDAP_BIND:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user