[stunnel-users] Patch for Start TLS for LDAP clients (RFC 2830)

Bart Dopheide dopheide at fmf.nl
Tue Nov 5 15:00:50 CET 2013


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 at 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 at anguish:/tmp$ 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://www.stunnel.org/pipermail/stunnel-users/attachments/20131105/7f17d88a/attachment-0001.sig>


More information about the stunnel-users mailing list