Hi,
I noticed that latest/greatest stunnel does not support the Start TLS operation for LDAP (RFC2830). Yet, I need it in my organisation as a quick workaround.
After fiddling with OpenLDAP, tracing, and reading RFC 2830 a bit, I patched stunnel 4.56 and the patch has not failed me yet. But I must remark that I am no LDAP expert, nor an certified stunnel hacker. So, I will submit this patch as a first suggestion.
Will you consider the feature request of implementing the Start TLS feature as described in RFC 2830?
Cheers, Bart Dopheide
My patch suggestion is: dopheideb@anguish:/tmp$ diff -aur stunnel-4.56 stunnel-4.56-ldap-starttls-patch diff -aur stunnel-4.56/src/protocol.c stunnel-4.56-ldap-starttls-patch/src/protocol.c --- stunnel-4.56/src/protocol.c 2013-03-13 14:41:16.000000000 +0100 +++ stunnel-4.56-ldap-starttls-patch/src/protocol.c 2013-11-05 11:19:10.388365359 +0100 @@ -53,6 +53,7 @@ static void imap_client(CLI *); static void imap_server(CLI *); static void nntp_client(CLI *); +static void openldap_client(CLI *); static void connect_server(CLI *); static void connect_client(CLI *);
@@ -82,6 +83,7 @@ {"pop3", {{PROTOCOL_PRE_SSL, pop3_server}, {PROTOCOL_PRE_SSL, pop3_client}}}, {"imap", {{PROTOCOL_PRE_SSL, imap_server}, {PROTOCOL_PRE_SSL, imap_client}}}, {"nntp", {{PROTOCOL_NONE, NULL}, {PROTOCOL_PRE_SSL, nntp_client}}}, + {"openldap",{{PROTOCOL_NONE, NULL}, {PROTOCOL_PRE_SSL, openldap_client}}}, {"connect", {{PROTOCOL_PRE_CONNECT, connect_server}, {PROTOCOL_PRE_SSL, connect_client}}}, {NULL, {{PROTOCOL_NONE, NULL}, {PROTOCOL_NONE, NULL}}} }; @@ -513,6 +515,88 @@ str_free(line); }
+/**************************************** LDAP, RFC 2830 */ + +u8 ldap_startssl_message[0x1d + 2] = +{ + 0x30, /* tag = UNIVERSAL SEQUENCE */ + 0x1d, /* len = 29 (the remaining number of bytes in this message) */ + 0x02, /* messageID */ + 0x01, /* len = 1 */ + 0x01, /* value = 1 (this is messageID 1) */ + /* --- */ + 0x77, /* protocolOp = APPLICATION (23) (=ExtendedRequest) + * 0b01xxxxxx => APPLICATION + * 0bxx1xxxxx => ? + * 0xxxx10111 => 23 + */ + 0x18, /* len = 24 */ + 0x80, /* type = requstName? */ + 0x16, /* len = 22 */ + /* OID: 1.3.6.1.4.1.1466.20037 (=LDAP_START_TLS_OID)*/ + '1', '.', + '3', '.', + '6', '.', + '1', '.', + '4', '.', + '1', '.', + '1', '4', '6', '6', '.', + '2', '0', '0', '3', '7' + /* No requestValue, as per RFC2830 (in 2.1: "The requestValue field is absent") */ +}; +static void openldap_client(CLI *c) { + u8 buffer[1]; + u8 ldap_response[256]; + + s_log(LOG_DEBUG, "Requesting LDAP Start TLS"); + write_blocking(c, c->remote_fd.fd, ldap_startssl_message, ldap_startssl_message[1] + 2); + + read_blocking(c, c->remote_fd.fd, buffer, 1); + if(buffer[0] != 0x30) { + s_log(LOG_ERR, "start tag is not UNIVERSAL SEQUENCE"); + longjmp(c->err, 1); + } + + s_log(LOG_DEBUG, "Reading LDAP message size (1 byte)."); + read_blocking(c, c->remote_fd.fd, buffer, 1); + + s_log(LOG_DEBUG, "Reading LDAP message (%u byte(s))", buffer[0]); + read_blocking(c, c->remote_fd.fd, ldap_response, buffer[0]); + + if(ldap_response[0] != 0x02) { + s_log(LOG_ERR, "LDAP response does not start with type messageID"); + longjmp(c->err, 1); + } + if(ldap_response[1] != 0x01) { + s_log(LOG_ERR, "This is not an extendedResp(1)"); + longjmp(c->err, 1); + } + if(ldap_response[2] != 0x01) { + s_log(LOG_ERR, "Non-matching messageID"); + longjmp(c->err, 1); + } + if(ldap_response[3] != 0x78) { + s_log(LOG_ERR, "This is not a protocolOp for APPLICATION ExtendedResponse"); + longjmp(c->err, 1); + } + if(ldap_response[4] != 0x07) { + s_log(LOG_ERR, "Expected 0x07 indicating extendedResp is 7 bytes long"); + longjmp(c->err, 1); + } + if(ldap_response[5] != 0x0a) { + s_log(LOG_ERR, "This is not an extendedResp"); + longjmp(c->err, 1); + } + if(ldap_response[6] != 0x01) { + s_log(LOG_ERR, "This is not an extendedResp"); + longjmp(c->err, 1); + } + if(ldap_response[7] != 0x00) { + s_log(LOG_ERR, "This is not resultCode success"); + longjmp(c->err, 1); + } +} + /**************************************** connect */
static void connect_server(CLI *c) { dopheideb@anguish:/tmp$