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$