Skip to content

Conversation

@eehakkin
Copy link

@eehakkin eehakkin commented Jan 22, 2026

The OpenLDAP library has global options (which can be set by passing a NULL LDAP handle to ldap_set_setting()) and connection specific options (which can be set by passing a non-NULL LDAP handle to ldap_set_setting()). For TLS connection, the library uses either a default TLS context (which is based on global TLS options) or a connection specific TLS context (which can be create used the LDAP_OPT_X_TLS_NEWCTX option and which is based on connection specific TLS options).

The Dovecot LDAP libraries set and use the options and TLS contexts inconsistently and therefore it is not possible to set Dovecot LDAP TLS options as documented. Additionally, the ssl_min_protocol setting in handled wrongly.

Problems:

  1. Inconsistent use of LDAP TLS contexts:

    • LDAP connections are create by by the db_ldap_init_ld() in src/auth/db-ldap.c and by the ldap_connection_setup() in src/lib-ldap/ldap-connection.c (using ldap_initialize()). Both of these call the ldap_set_tls_options() to set connection specific TLS options (except for LDAP_OPT_X_TLS_REQUIRE_CERT also the global one).
    • The ldap_connection_setup() in src/lib-ldap/ldap-connection.c also sets the LDAP_OPT_X_TLS_NEWCTX option and thus creates a new connection specific TLS context based on the connection specific TLS options which were set by the ldap_set_tls_options().
    • But the db_ldap_init_ld() in src/auth/db-ldap.c does not set the LDAP_OPT_X_TLS_NEWCTX option and thus uses the default TLS context based on the global TLS options which were not set by the ldap_set_tls_options().

    To fix this disparity, the ldap_set_tls_options() should set the LDAP_OPT_X_TLS_NEWCTX option.

  2. Once the TLS context issue is fixed and only connection specific TLS options are used, it is not longer necessary to set the global LDAP_OPT_X_TLS_REQUIRE_CERT option in the ldap_set_tls_options().

  3. The ldap_set_tls_options() uses the ssl_min_protocol setting string as-is as a LDAP_OPT_X_TLS_PROTOCOL_MIN option but the option is an int option. Typically the string is something like "TLSv1.3" or "\x54\x4C\x53\x76\x31\x2E\x33" which with typical 4 byte little endian ints means TLSv7754572.84 (0x76534C, 0x54) which LDAP servers do not provide.
    To fix this, the ldap_set_tls_options() should convert the ssl_min_protocol setting to LDAP_OPT_X_TLS_PROTOCOL_TLSx_y constants.

  4. The ldap_connection_setup() in src/lib-ldap/ldap-connection.c calls the ldap_set_tls_options() to set TLS options but overrides the LDAP_OPT_X_TLS_PROTOCOL_MIN option with the LDAP_OPT_X_TLS_PROTOCOL_SSL3 value.

Partial work-a-round for the current Dovecot 2.4.x is to configure at least LDAP TLS certificates also using import_environment as in

import_environment {
	LDAPTLS_CACERT    = /path/to/ca.pem
	LDAPTLS_CACERTDIR = /path/to/ca.dir/
	LDAPTLS_CERT      = /path/to/cert.pem
	LDAPTLS_KEY       = /path/to/key.pem
}

/* refuse to connect to SSLv2 as it's completely insecure */
opt = LDAP_OPT_X_TLS_PROTOCOL_SSL3;
ldap_set_option(conn->conn, LDAP_OPT_X_TLS_PROTOCOL_MIN, &opt);
#endif
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be done in ldap_set_tls_options().

opt = 0;
ldap_set_option(conn->conn, LDAP_OPT_X_TLS_NEWCTX, &opt);
#endif

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be done in ldap_set_tls_options().

int opt = requires ? LDAP_OPT_X_TLS_HARD : LDAP_OPT_X_TLS_ALLOW;

/* required for Bookworm */
if (ldap_set_opt(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &opt,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's required for Bookworm and others to either set the global TLS options (by passing a NULL LDAP handle for ldap_set_option) and not to create a connection specific TLS context (by setting the LDAP_OPT_X_TLS_NEWCTX option) or to set the connection specific TLS options (by passing a non-NULL LDAP handle for ldap_set_option like on RHEL9) and to create a connection specific TLS context (by setting the LDAP_OPT_X_TLS_NEWCTX option).

It's better to set set the connection specific TLS options and to create a connection specific TLS context.

else if (strcasecmp(ssl_set->ssl_min_protocol, "ANY") == 0 ||
*ssl_set->ssl_min_protocol == '\0')
/* refuse to connect to SSLv2 as it's completely insecure */
opt = LDAP_OPT_X_TLS_PROTOCOL_SSL3;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this minimum be increased to LDAP_OPT_X_TLS_PROTOCOL_TLS1_0?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants