Re: updated patch for Start TLS for LDAP clients (RFC 2830)
Seth Grover <[email protected]> Tue, 10 Dec 2019 15:09:00 -0700
| Newsgroups | gmane.network.stunnel.user |
|---|---|
| Message-ID | <CAD13zvT9EF9Ohp0Kniw2+wBKkFuEOQBGuiyHQ3A+VD66ARS1PA@mail.gmail.com> |
--===============8754002518155526001== Content-Type: multipart/alternative; boundary="0000000000000c583e059960c38a" --0000000000000c583e059960c38a Content-Type: text/plain; charset="UTF-8" On Tue, Dec 3, 2019 at 2:29 PM Seth Grover <[email protected]> wrote: > ... > Back in 2013 Bart Dopheide submitted a patch to the mailing list to add LDAP > StartTLS (elevate connection to TLS after initial connection is initiated) > support to the list of supported protocols in protocol.c ( > https://www.stunnel.org/pipermail/stunnel-users/2013-November/004437.html). > It doesn't look like this patch was ever accepted into stunnel. > > I've run into a similar requirement and have updated the patch to work > against stunnel 5.56. In addition, there are a few other minor changes, the > most significant being as follows. It would appear that Windows Active > Directory servers do not implement the ldap extended response PDU in the > same way as OpenLDAP (see this thread: > https://www.openldap.org/lists/openldap-software/200401/msg00800.html). > With this patch you can specify either "protocol = winldap" or "protocol = > openldap" and have it work either way. I haven't modified the logic of > Bart's original patch as far as OpenLDAP goes, but I have split the code > path where applicable to handle the Windows case. > ... > The patch is at the end of this message. > ... > I apologize, but I had a stupid bug in the OpenLDAP portion of my patch which I hadn't been able to test as I didn't have an OpenLDAP server instance set up. On line 108 of my patch, this code: resp_len = buffer_8; > should be changed to: resp_len = buffer_8[0]; > I set up an openldap instance in docker ( https://github.com/osixia/docker-openldap) and am now getting correct results against both Active Directory and OpenLDAP. For completeness' sake, I am including the full (corrected) patch again here: diff -Nurp a/src/protocol.c b/src/protocol.c --- a/src/protocol.c 2019-05-15 13:35:16.000000000 -0600 +++ b/src/protocol.c 2019-12-03 13:54:47.536940900 -0700 @@ -64,6 +64,8 @@ NOEXPORT char *pop3_server(CLI *, SERVIC NOEXPORT char *imap_client(CLI *, SERVICE_OPTIONS *, const PHASE); NOEXPORT char *imap_server(CLI *, SERVICE_OPTIONS *, const PHASE); NOEXPORT char *nntp_client(CLI *, SERVICE_OPTIONS *, const PHASE); +NOEXPORT char *openldap_client(CLI *, SERVICE_OPTIONS *, const PHASE); +NOEXPORT char *winldap_client(CLI *, SERVICE_OPTIONS *, const PHASE); NOEXPORT char *connect_server(CLI *, SERVICE_OPTIONS *, const PHASE); NOEXPORT char *connect_client(CLI *, SERVICE_OPTIONS *, const PHASE); #ifndef OPENSSL_NO_MD4 @@ -113,6 +115,14 @@ char *protocol(CLI *c, SERVICE_OPTIONS * return opt->option.client ? nntp_client(c, opt, phase) : "The 'nntp' protocol is not supported in the server mode"; + if(!strcasecmp(opt->protocol, "openldap")) + return opt->option.client ? + openldap_client(c, opt, phase) : + "The 'openldap' protocol is not supported in the server mode"; + if(!strcasecmp(opt->protocol, "winldap")) + return opt->option.client ? + winldap_client(c, opt, phase) : + "The 'winldap' protocol is not supported in the server mode"; if(!strcasecmp(opt->protocol, "connect")) return opt->option.client ? connect_client(c, opt, phase) : @@ -1119,6 +1129,182 @@ NOEXPORT char *nntp_client(CLI *c, SERVI return NULL; } +/**************************************** LDAP, RFC 2830 */ +uint8_t 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") */ +}; + +typedef enum { + LDAP_OPENLDAP, + LDAP_WINLDAP +} LDAP_MODE; + +#define LDAP_UNIVERSAL_SEQUENCE 0x30 +#define LDAP_WINLDAP_FOUR_BYTE_LEN_FLAG 0x84 +#define LDAP_RESPONSE_MSG_ID_TYPE_INT 0x02 +#define LDAP_RESPONSE_EXPECTED_MSG_ID_LEN 0x01 +#define LDAP_RESPONSE_EXPECTED_MSG_ID 0x01 +#define LDAP_RESPONSE_EXT_RESP 0x0a +#define LDAP_RESPONSE_EXT_RESP_APPLICATION 0x78 +#define LDAP_RESPONSE_EXPECTED_ERR_LEN 0x01 +#define LDAP_RESPONSE_SUCCESS 0x00 + +NOEXPORT char *ldap_client(CLI *c, SERVICE_OPTIONS *opt, const PHASE phase, const LDAP_MODE ldap_mode) { + + /* thanks to these threads for help with these PDUs + https://www.stunnel.org/pipermail/stunnel-users/2013-November/004437.html + https://www.openldap.org/lists/openldap-software/200401/msg00800.html */ + + uint8_t buffer_8[1]; + uint32_t buffer_32[1]; + uint32_t resp_len; + uint8_t ldap_response[256]; + uint8_t *resp_ptr; + + (void)opt; /* squash the unused parameter warning */ + + if(phase!=PROTOCOL_MIDDLE) + return NULL; + + /* send "Start TLS" request to AD server */ + s_log(LOG_DEBUG, "Requesting LDAP Start TLS"); + s_write(c, c->remote_fd.fd, ldap_startssl_message, (size_t)ldap_startssl_message[1] + 2); + + /* LDAP_UNIVERSAL_SEQUENCE (1 byte) */ + s_read(c, c->remote_fd.fd, buffer_8, 1); + if(buffer_8[0] != LDAP_UNIVERSAL_SEQUENCE) { + s_log(LOG_ERR, "start tag is not UNIVERSAL SEQUENCE"); + throw_exception(c, 1); + } + + if(ldap_mode == LDAP_OPENLDAP) { + /* OpenLDAP - response length (1 byte) */ + s_log(LOG_DEBUG, "Reading OpenLDAP message size (1 byte)"); + s_read(c, c->remote_fd.fd, buffer_8, 1); + resp_len = buffer_8[0]; + + } else if(ldap_mode == LDAP_WINLDAP) { + + /* WinLDAP - "response length is 4 bytes" flag - LDAP_WINLDAP_FOUR_BYTE_LEN_FLAG (1-byte) */ + s_read(c, c->remote_fd.fd, buffer_8, 1); + if(buffer_8[0] != LDAP_WINLDAP_FOUR_BYTE_LEN_FLAG) { + s_log(LOG_ERR, "LDAP message length flag is an unexpected value"); + throw_exception(c, 1); + } + + /* WinLDAP - response length (4 bytes, network byte order) */ + s_log(LOG_DEBUG, "Reading WinLDAP message size (4 bytes)"); + s_read(c, c->remote_fd.fd, buffer_32, 4); + resp_len = ntohl(buffer_32[0]); + + } else { + s_log(LOG_ERR, "Unsupported LDAP mode"); + throw_exception(c, 1); + } + + /* LDAP response message */ + s_log(LOG_DEBUG, "Reading LDAP message (%u byte(s))", resp_len); + s_read(c, c->remote_fd.fd, ldap_response, resp_len); + + resp_ptr = &ldap_response[0]; + + /* LDAP_RESPONSE_MSG_ID_TYPE_INT - 1 byte */ + if(*resp_ptr != LDAP_RESPONSE_MSG_ID_TYPE_INT) { + s_log(LOG_ERR, "LDAP response has an incorrect message ID type"); + throw_exception(c, 1); + } + resp_ptr++; + + /* LDAP_RESPONSE_EXPECTED_MSG_ID_LEN - 1 byte */ + if(*resp_ptr != LDAP_RESPONSE_EXPECTED_MSG_ID_LEN) { + s_log(LOG_ERR, "LDAP response has an unexpected message ID length"); + throw_exception(c, 1); + } + resp_ptr++; + + /* LDAP_RESPONSE_EXPECTED_MSG_ID - 1 byte */ + if(*resp_ptr != LDAP_RESPONSE_EXPECTED_MSG_ID) { + s_log(LOG_ERR, "LDAP response has an unexpected message ID"); + throw_exception(c, 1); + } + resp_ptr++; + + /* LDAP_RESPONSE_EXT_RESP_APPLICATION - 1 byte */ + if(*resp_ptr != LDAP_RESPONSE_EXT_RESP_APPLICATION) { + s_log(LOG_ERR, "LDAP response protocolOp is not APPLICATION"); + throw_exception(c, 1); + } + resp_ptr++; + + if(ldap_mode == LDAP_WINLDAP) { + /* WinLDAP - "response length is 4 bytes" flag - LDAP_WINLDAP_FOUR_BYTE_LEN_FLAG (1-byte) */ + if(*resp_ptr != LDAP_WINLDAP_FOUR_BYTE_LEN_FLAG) { + s_log(LOG_ERR, "LDAP extendedResp length flag is an unexpected value"); + throw_exception(c, 1); + } + /* WinLDAP - extended response message length (4-bytes) */ + resp_ptr += 5; + + } else { + /* OpenLDAP - extended response message length (1-byte) */ + resp_ptr++; + } + + /* LDAP_RESPONSE_EXT_RESP - 1 byte */ + if(*resp_ptr != LDAP_RESPONSE_EXT_RESP) { + s_log(LOG_ERR, "LDAP response type is not EXT_RESP"); + throw_exception(c, 1); + } + resp_ptr++; + + /* LDAP_RESPONSE_EXT_RESP - 1 byte */ + if(*resp_ptr != LDAP_RESPONSE_EXPECTED_ERR_LEN) { + s_log(LOG_ERR, "LDAP response has an unexpected error code length"); + throw_exception(c, 1); + } + resp_ptr++; + + if(*resp_ptr != LDAP_RESPONSE_SUCCESS) { + s_log(LOG_ERR, "LDAP response has indicated an error (%u)", *resp_ptr); + throw_exception(c, 1); + } + + return NULL; +} + + +NOEXPORT char *openldap_client(CLI *c, SERVICE_OPTIONS *opt, const PHASE phase) { + return ldap_client(c, opt, phase, LDAP_OPENLDAP); +} + +NOEXPORT char *winldap_client(CLI *c, SERVICE_OPTIONS *opt, const PHASE phase) { + return ldap_client(c, opt, phase, LDAP_WINLDAP); +} + /**************************************** connect */ NOEXPORT char *connect_server(CLI *c, SERVICE_OPTIONS *opt, const PHASE phase) { --0000000000000c583e059960c38a Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div class=3D"gmail_quote"><div dir=3D"ltr" class=3D"gmail= _attr">On Tue, Dec 3, 2019 at 2:29 PM Seth Grover <<a href=3D"mailto:Set= [email protected]">[email protected]</a>> wrote:<br></div><bloc= kquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:= 1px solid rgb(204,204,204);padding-left:1ex"><div>...</div></blockquote><bl= ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-lef= t:1px solid rgb(204,204,204);padding-left:1ex"><div>Back in 2013 Bart Dophe= ide submitted a patch to the mailing list to add <span class=3D"gmail-il">L= DAP</span> StartTLS (elevate connection to TLS after initial connection is=20 initiated) support to the list of supported protocols in protocol.c (<a hre= f=3D"https://www.stunnel.org/pipermail/stunnel-users/2013-November/004437.h= tml" target=3D"_blank">https://www.stunnel.org/pipermail/stunnel-users/2013= -November/004437.html</a>). It doesn't look like this patch was ever ac= cepted into stunnel.<br><br>I've run into a similar requirement and have updated the patch to work=20 against stunnel 5.56. In addition, there are a few other minor changes,=20 the most significant being as follows. It would appear that Windows=20 Active Directory servers do not implement the <span class=3D"gmail-il">ldap= </span> extended response PDU in the same way as OpenLDAP (see this thread:= <a href=3D"https://www.openldap.org/lists/openldap-software/200401/msg0080= 0.html" target=3D"_blank">https://www.openldap.org/lists/openldap-software/= 200401/msg00800.html</a>). With this patch you can specify either "protocol =3D winldap" or= =20 "protocol =3D openldap" and have it work either way. I haven'= t modified=20 the logic of Bart's original patch as far as OpenLDAP goes, but I have= =20 split the code path where applicable to handle the Windows case.<br>... <br= ></div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin:0px 0= px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div = dir=3D"ltr">The patch is at the end of this message.<br>...<br></div></bloc= kquote><div><br></div><div>I apologize, but I had a stupid bug in the OpenL= DAP portion of my patch which I hadn't been able to test as I didn'= t have an OpenLDAP server instance set up. On line 108 of my patch, this co= de:</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0= px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><= div>resp_len =3D buffer_8;</div></blockquote><div><br></div><div>should be = changed to:<br></div><div><br></div><blockquote class=3D"gmail_quote" style= =3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding= -left:1ex"><div>resp_len =3D buffer_8[0];</div></blockquote><div><br></div>= <div>I set up an openldap instance in docker (<a href=3D"https://github.com= /osixia/docker-openldap">https://github.com/osixia/docker-openldap</a>) and= am now getting correct results against both Active Directory and OpenLDAP.= For completeness' sake, I am including the full (corrected) patch agai= n here:</div><div><br></div><div>diff -Nurp a/src/protocol.c b/src/protocol= .c<br>--- a/src/protocol.c 2019-05-15 13:35:16.000000000 -0600<br>+++ b/src= /protocol.c 2019-12-03 13:54:47.536940900 -0700<br>@@ -64,6 +64,8 @@ NOEXPO= RT char *pop3_server(CLI *, SERVIC<br>=C2=A0NOEXPORT char *imap_client(CLI = *, SERVICE_OPTIONS *, const PHASE);<br>=C2=A0NOEXPORT char *imap_server(CLI= *, SERVICE_OPTIONS *, const PHASE);<br>=C2=A0NOEXPORT char *nntp_client(CL= I *, SERVICE_OPTIONS *, const PHASE);<br>+NOEXPORT char *openldap_client(CL= I *, SERVICE_OPTIONS *, const PHASE);<br>+NOEXPORT char *winldap_client(CLI= *, SERVICE_OPTIONS *, const PHASE);<br>=C2=A0NOEXPORT char *connect_server= (CLI *, SERVICE_OPTIONS *, const PHASE);<br>=C2=A0NOEXPORT char *connect_cl= ient(CLI *, SERVICE_OPTIONS *, const PHASE);<br>=C2=A0#ifndef OPENSSL_NO_MD= 4<br>@@ -113,6 +115,14 @@ char *protocol(CLI *c, SERVICE_OPTIONS *<br>=C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return opt->option.client ?<br>=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0nntp_client(c, opt, phase) :<br>=C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"The 'nntp' proto= col is not supported in the server mode";<br>+ =C2=A0 =C2=A0if(!strcas= ecmp(opt->protocol, "openldap"))<br>+ =C2=A0 =C2=A0 =C2=A0 =C2= =A0return opt->option.client ?<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0openldap_client(c, opt, phase) :<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0"The 'openldap' protocol is not supported in the ser= ver mode";<br>+ =C2=A0 =C2=A0if(!strcasecmp(opt->protocol, "wi= nldap"))<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0return opt->option.client = ?<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0winldap_client(c, opt, phas= e) :<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"The 'winldap&#= 39; protocol is not supported in the server mode";<br>=C2=A0 =C2=A0 = =C2=A0if(!strcasecmp(opt->protocol, "connect"))<br>=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0return opt->option.client ?<br>=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0connect_client(c, opt, phase) :<br>@@ -1119,= 6 +1129,182 @@ NOEXPORT char *nntp_client(CLI *c, SERVI<br>=C2=A0 =C2=A0 = =C2=A0return NULL;<br>=C2=A0}<br><br>+/************************************= **** LDAP, RFC 2830 */<br>+uint8_t ldap_startssl_message[0x1d + 2] =3D<br>+= {<br>+ =C2=A00x30, =C2=A0 =C2=A0 =C2=A0 =C2=A0/* tag =3D UNIVERSAL SEQUENCE= */<br>+ =C2=A00x1d, =C2=A0 =C2=A0 =C2=A0 =C2=A0/* len =3D 29 (the remainin= g number of bytes in this message) */<br>+ =C2=A00x02, =C2=A0 =C2=A0 =C2=A0= =C2=A0/* =C2=A0 messageID */<br>+ =C2=A00x01, =C2=A0 =C2=A0 =C2=A0 =C2=A0/= * =C2=A0 len =3D 1 */<br>+ =C2=A00x01, =C2=A0 =C2=A0 =C2=A0 =C2=A0/* =C2=A0= value =3D 1 (this is messageID 1) */<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 /* =C2=A0 --- */<br>+ =C2=A00x77, =C2=A0 =C2=A0 =C2=A0 = =C2=A0/* =C2=A0 protocolOp =3D APPLICATION (23) (=3DExtendedRequest)<br>+ = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 * =C2=A0 =C2=A0 0b0= 1xxxxxx =3D> APPLICATION<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 * =C2=A0 =C2=A0 0bxx1xxxxx =3D> ?<br>+ =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 * =C2=A0 =C2=A0 0xxxx10111 =3D> 2= 3<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 */<br>+ =C2=A00x18,= =C2=A0 =C2=A0 =C2=A0 =C2=A0/* =C2=A0 len =3D 24 */<br>+ =C2=A00x80, =C2=A0= =C2=A0 =C2=A0 =C2=A0/* =C2=A0 type =3D requstName? */<br>+ =C2=A00x16, =C2= =A0 =C2=A0 =C2=A0 =C2=A0/* =C2=A0 len =3D 22 */<br>+ =C2=A0/* OID: 1.3.6.1.= 4.1.1466.20037 (=3DLDAP_START_TLS_OID)*/<br>+ =C2=A0'1', '.'= ;,<br>+ =C2=A0'3', '.',<br>+ =C2=A0'6', '.'= ,<br>+ =C2=A0'1', '.',<br>+ =C2=A0'4', '.',= <br>+ =C2=A0'1', '.',<br>+ =C2=A0'1', '4', = '6', '6', '.',<br>+ =C2=A0'2', '0',= '0', '3', '7'<br>+ =C2=A0/* No requestValue, as pe= r RFC2830 (in 2.1: "The requestValue field is absent") */<br>+};<= br>+<br>+typedef enum {<br>+ =C2=A0 =C2=A0LDAP_OPENLDAP,<br>+ =C2=A0 =C2=A0= LDAP_WINLDAP<br>+} LDAP_MODE;<br>+<br>+#define LDAP_UNIVERSAL_SEQUENCE =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x30<br>+#define LDAP_W= INLDAP_FOUR_BYTE_LEN_FLAG =C2=A0 =C2=A0 =C2=A0 =C2=A00x84<br>+#define LDAP_= RESPONSE_MSG_ID_TYPE_INT =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x02<br>+#define= LDAP_RESPONSE_EXPECTED_MSG_ID_LEN =C2=A0 =C2=A0 =C2=A00x01<br>+#define LDA= P_RESPONSE_EXPECTED_MSG_ID =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x01<br>+#defi= ne LDAP_RESPONSE_EXT_RESP =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 0x0a<br>+#define LDAP_RESPONSE_EXT_RESP_APPLICATION =C2=A0 =C2=A0 0x= 78<br>+#define LDAP_RESPONSE_EXPECTED_ERR_LEN =C2=A0 =C2=A0 =C2=A0 =C2=A0 0= x01<br>+#define LDAP_RESPONSE_SUCCESS =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A00x00<br>+<br>+NOEXPORT char *ldap_client(CLI *c,= SERVICE_OPTIONS *opt, const PHASE phase, const LDAP_MODE ldap_mode) {<br>+= <br>+ =C2=A0 =C2=A0/* thanks to these threads for help with these PDUs<br>+= =C2=A0 =C2=A0 =C2=A0 =C2=A0 <a href=3D"https://www.stunnel.org/pipermail/s= tunnel-users/2013-November/004437.html">https://www.stunnel.org/pipermail/s= tunnel-users/2013-November/004437.html</a><br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0= <a href=3D"https://www.openldap.org/lists/openldap-software/200401/msg0080= 0.html">https://www.openldap.org/lists/openldap-software/200401/msg00800.ht= ml</a> */<br>+<br>+ =C2=A0 =C2=A0uint8_t buffer_8[1];<br>+ =C2=A0 =C2=A0uin= t32_t buffer_32[1];<br>+ =C2=A0 =C2=A0uint32_t resp_len;<br>+ =C2=A0 =C2=A0= uint8_t ldap_response[256];<br>+ =C2=A0 =C2=A0uint8_t *resp_ptr;<br>+<br>+ = =C2=A0 =C2=A0(void)opt; /* squash the unused parameter warning */<br>+<br>+= =C2=A0 =C2=A0if(phase!=3DPROTOCOL_MIDDLE)<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0= return NULL;<br>+<br>+ =C2=A0 =C2=A0/* send "Start TLS" request t= o AD server */<br>+ =C2=A0 =C2=A0s_log(LOG_DEBUG, "Requesting LDAP Sta= rt TLS");<br>+ =C2=A0 =C2=A0s_write(c, c->remote_fd.fd, ldap_starts= sl_message, (size_t)ldap_startssl_message[1] + 2);<br>+<br>+ =C2=A0 =C2=A0/= * LDAP_UNIVERSAL_SEQUENCE (1 byte) */<br>+ =C2=A0 =C2=A0s_read(c, c->rem= ote_fd.fd, buffer_8, 1);<br>+ =C2=A0 =C2=A0if(buffer_8[0] !=3D LDAP_UNIVERS= AL_SEQUENCE) {<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0s_log(LOG_ERR, "start t= ag is not UNIVERSAL SEQUENCE");<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0throw_= exception(c, 1);<br>+ =C2=A0 =C2=A0}<br>+<br>+ =C2=A0 =C2=A0if(ldap_mode = =3D=3D LDAP_OPENLDAP) {<br>+ =C2=A0 =C2=A0 =C2=A0/* OpenLDAP - response len= gth (1 byte) */<br>+ =C2=A0 =C2=A0 =C2=A0s_log(LOG_DEBUG, "Reading Ope= nLDAP message size (1 byte)");<br>+ =C2=A0 =C2=A0 =C2=A0s_read(c, c-&g= t;remote_fd.fd, buffer_8, 1);<br>+ =C2=A0 =C2=A0 =C2=A0resp_len =3D buffer_= 8[0];<br>+<br>+ =C2=A0 =C2=A0} else if(ldap_mode =3D=3D LDAP_WINLDAP) {<br>= +<br>+ =C2=A0 =C2=A0 =C2=A0/* WinLDAP - "response length is 4 bytes&qu= ot; flag - LDAP_WINLDAP_FOUR_BYTE_LEN_FLAG (1-byte) */<br>+ =C2=A0 =C2=A0 = =C2=A0s_read(c, c->remote_fd.fd, buffer_8, 1);<br>+ =C2=A0 =C2=A0 =C2=A0= if(buffer_8[0] !=3D LDAP_WINLDAP_FOUR_BYTE_LEN_FLAG) {<br>+ =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0s_log(LOG_ERR, "LDAP message length flag is an une= xpected value");<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0throw_exceptio= n(c, 1);<br>+ =C2=A0 =C2=A0 =C2=A0}<br>+<br>+ =C2=A0 =C2=A0 =C2=A0/* WinLDA= P - response length (4 bytes, network byte order) */<br>+ =C2=A0 =C2=A0 =C2= =A0s_log(LOG_DEBUG, "Reading WinLDAP message size (4 bytes)");<br= >+ =C2=A0 =C2=A0 =C2=A0s_read(c, c->remote_fd.fd, buffer_32, 4);<br>+ = =C2=A0 =C2=A0 =C2=A0resp_len =3D ntohl(buffer_32[0]);<br>+<br>+ =C2=A0 =C2= =A0} else {<br>+ =C2=A0 =C2=A0 =C2=A0s_log(LOG_ERR, "Unsupported LDAP = mode");<br>+ =C2=A0 =C2=A0 =C2=A0throw_exception(c, 1);<br>+ =C2=A0 = =C2=A0}<br>+<br>+ =C2=A0 =C2=A0/* LDAP response message */<br>+ =C2=A0 =C2= =A0s_log(LOG_DEBUG, "Reading LDAP message (%u byte(s))", resp_len= );<br>+ =C2=A0 =C2=A0s_read(c, c->remote_fd.fd, ldap_response, resp_len)= ;<br>+<br>+ =C2=A0 =C2=A0resp_ptr =3D &ldap_response[0];<br>+<br>+ =C2= =A0 =C2=A0/* LDAP_RESPONSE_MSG_ID_TYPE_INT - 1 byte */<br>+ =C2=A0 =C2=A0if= (*resp_ptr !=3D LDAP_RESPONSE_MSG_ID_TYPE_INT) {<br>+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0s_log(LOG_ERR, "LDAP response has an incorrect message ID type&q= uot;);<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0throw_exception(c, 1);<br>+ =C2=A0 = =C2=A0}<br>+ =C2=A0 =C2=A0resp_ptr++;<br>+<br>+ =C2=A0 =C2=A0/* LDAP_RESPON= SE_EXPECTED_MSG_ID_LEN - 1 byte */<br>+ =C2=A0 =C2=A0if(*resp_ptr !=3D LDAP= _RESPONSE_EXPECTED_MSG_ID_LEN) {<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0s_log(LOG_= ERR, "LDAP response has an unexpected message ID length");<br>+ = =C2=A0 =C2=A0 =C2=A0 =C2=A0throw_exception(c, 1);<br>+ =C2=A0 =C2=A0}<br>+ = =C2=A0 =C2=A0resp_ptr++;<br>+<br>+ =C2=A0 =C2=A0/* LDAP_RESPONSE_EXPECTED_M= SG_ID - 1 byte */<br>+ =C2=A0 =C2=A0if(*resp_ptr !=3D LDAP_RESPONSE_EXPECTE= D_MSG_ID) {<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0s_log(LOG_ERR, "LDAP respo= nse has an unexpected message ID");<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0th= row_exception(c, 1);<br>+ =C2=A0 =C2=A0}<br>+ =C2=A0 =C2=A0resp_ptr++;<br>+= <br>+ =C2=A0 =C2=A0/* LDAP_RESPONSE_EXT_RESP_APPLICATION - 1 byte */<br>+ = =C2=A0 =C2=A0if(*resp_ptr !=3D LDAP_RESPONSE_EXT_RESP_APPLICATION) {<br>+ = =C2=A0 =C2=A0 =C2=A0 =C2=A0s_log(LOG_ERR, "LDAP response protocolOp is= not APPLICATION");<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0throw_exception(c,= 1);<br>+ =C2=A0 =C2=A0}<br>+ =C2=A0 =C2=A0resp_ptr++;<br>+<br>+ =C2=A0 =C2= =A0if(ldap_mode =3D=3D LDAP_WINLDAP) {<br>+ =C2=A0 =C2=A0 =C2=A0/* WinLDAP = - "response length is 4 bytes" flag - LDAP_WINLDAP_FOUR_BYTE_LEN_= FLAG (1-byte) */<br>+ =C2=A0 =C2=A0 =C2=A0if(*resp_ptr !=3D LDAP_WINLDAP_FO= UR_BYTE_LEN_FLAG) {<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0s_log(LOG_ERR, &= quot;LDAP extendedResp length flag is an unexpected value");<br>+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0throw_exception(c, 1);<br>+ =C2=A0 =C2=A0 = =C2=A0}<br>+ =C2=A0 =C2=A0 =C2=A0/* WinLDAP - extended response message len= gth (4-bytes) */<br>+ =C2=A0 =C2=A0 =C2=A0resp_ptr +=3D 5;<br>+<br>+ =C2=A0= =C2=A0} else {<br>+ =C2=A0 =C2=A0 =C2=A0/* OpenLDAP - extended response me= ssage length (1-byte) */<br>+ =C2=A0 =C2=A0 =C2=A0resp_ptr++;<br>+ =C2=A0 = =C2=A0}<br>+<br>+ =C2=A0 =C2=A0/* LDAP_RESPONSE_EXT_RESP - 1 byte */<br>+ = =C2=A0 =C2=A0if(*resp_ptr !=3D LDAP_RESPONSE_EXT_RESP) {<br>+ =C2=A0 =C2=A0= =C2=A0 =C2=A0s_log(LOG_ERR, "LDAP response type is not EXT_RESP"= );<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0throw_exception(c, 1);<br>+ =C2=A0 =C2= =A0}<br>+ =C2=A0 =C2=A0resp_ptr++;<br>+<br>+ =C2=A0 =C2=A0/* LDAP_RESPONSE_= EXT_RESP - 1 byte */<br>+ =C2=A0 =C2=A0if(*resp_ptr !=3D LDAP_RESPONSE_EXPE= CTED_ERR_LEN) {<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0s_log(LOG_ERR, "LDAP r= esponse has an unexpected error code length");<br>+ =C2=A0 =C2=A0 =C2= =A0 =C2=A0throw_exception(c, 1);<br>+ =C2=A0 =C2=A0}<br>+ =C2=A0 =C2=A0resp= _ptr++;<br>+<br>+ =C2=A0 =C2=A0if(*resp_ptr !=3D LDAP_RESPONSE_SUCCESS) {<b= r>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0s_log(LOG_ERR, "LDAP response has indic= ated an error (%u)", *resp_ptr);<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0throw= _exception(c, 1);<br>+ =C2=A0 =C2=A0}<br>+<br>+ =C2=A0 =C2=A0return NULL;<b= r>+}<br>+<br>+<br>+NOEXPORT char *openldap_client(CLI *c, SERVICE_OPTIONS *= opt, const PHASE phase) {<br>+ =C2=A0return ldap_client(c, opt, phase, LDAP= _OPENLDAP);<br>+}<br>+<br>+NOEXPORT char *winldap_client(CLI *c, SERVICE_OP= TIONS *opt, const PHASE phase) {<br>+ =C2=A0return ldap_client(c, opt, phas= e, LDAP_WINLDAP);<br>+}<br>+<br>=C2=A0/************************************= **** connect */<br><br>=C2=A0NOEXPORT char *connect_server(CLI *c, SERVICE_= OPTIONS *opt, const PHASE phase) {<br></div><div><br></div></div></div> --0000000000000c583e059960c38a-- --===============8754002518155526001== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ stunnel-users mailing list [email protected] https://www.stunnel.org/cgi-bin/mailman/listinfo/stunnel-users --===============8754002518155526001==--