updated patch for Start TLS for LDAP clients (RFC 2830)
Seth Grover <[email protected]> Tue, 3 Dec 2019 14:29:51 -0700
| Newsgroups | gmane.network.stunnel.user |
|---|---|
| Message-ID | <CAD13zvR25tCkBwv0AfHLqhvR4paLX1vhJ+2E00c+9g0OggSVqw@mail.gmail.com> |
--===============3938563711249280035== Content-Type: multipart/alternative; boundary="0000000000002507ff0598d366b5" --0000000000002507ff0598d366b5 Content-Type: text/plain; charset="UTF-8" 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. I am testing this against a virtual Windows Server 2016 Active Directory instance with self-signed certificates with the following config: [stunnel.winldap] client = yes accept = localhost:3268 connect =mymachine.example.com:3268 protocol = winldap And the following ldapsearch command: LDAPTLS_REQCERT=never ldapsearch -Z -h localhost -p 3268 -D "[email protected]" -W -b "dc=localdomain,dc=lan" -s sub "objectClass=person" The ldapsearch output returns as expected and I can see in wireshark that the LDAP_START_TLS_OID request/response happens as it should. The patch is at the end of this message. -SG 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; + + } 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) { --0000000000002507ff0598d366b5 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">Back in 2013 Bart Dopheide submitted a patch to the mailin= g list to add LDAP StartTLS (elevate connection to TLS after initial connec= tion is initiated) support to the list of supported protocols in protocol.c= (<a href=3D"https://www.stunnel.org/pipermail/stunnel-users/2013-November/= 004437.html">https://www.stunnel.org/pipermail/stunnel-users/2013-November/= 004437.html</a>). It doesn't look like this patch was ever accepted int= o stunnel.<br><br>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 respons= e PDU in the same way as OpenLDAP (see this thread: <a href=3D"https://www.= openldap.org/lists/openldap-software/200401/msg00800.html">https://www.open= ldap.org/lists/openldap-software/200401/msg00800.html</a>). With this patch= you can specify either "protocol =3D winldap" or "protocol = =3D 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 spli= t the code path where applicable to handle the Windows case.<br><br>I am te= sting this against a virtual Windows Server 2016 Active Directory instance = with self-signed certificates with the following config:<br><br>[stunnel.wi= nldap]<br>client =3D yes<br>accept =3D localhost:3268<br>connect =3D<a href= =3D"http://mymachine.example.com:3268">mymachine.example.com:3268</a><br>pr= otocol =3D winldap<br><br>And the following ldapsearch command:<br><br>LDAP= TLS_REQCERT=3Dnever ldapsearch -Z -h localhost -p 3268 -D "nginx_bind_= [email protected]" -W -b "dc=3Dlocaldomain,dc=3Dlan" -s sub= "objectClass=3Dperson"<br><br>The ldapsearch output returns as e= xpected and I can see in wireshark that the LDAP_START_TLS_OID request/resp= onse happens as it should.<br><br>The patch is at the end of this message.<= br><br>-SG<br><br>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 201= 9-12-03 13:54:47.536940900 -0700<br>@@ -64,6 +64,8 @@ NOEXPORT char *pop3_s= erver(CLI *, SERVIC<br>=C2=A0NOEXPORT char *imap_client(CLI *, SERVICE_OPTI= ONS *, const PHASE);<br>=C2=A0NOEXPORT char *imap_server(CLI *, SERVICE_OPT= IONS *, const PHASE);<br>=C2=A0NOEXPORT char *nntp_client(CLI *, SERVICE_OP= TIONS *, const PHASE);<br>+NOEXPORT char *openldap_client(CLI *, SERVICE_OP= TIONS *, const PHASE);<br>+NOEXPORT char *winldap_client(CLI *, SERVICE_OPT= IONS *, const PHASE);<br>=C2=A0NOEXPORT char *connect_server(CLI *, SERVICE= _OPTIONS *, const PHASE);<br>=C2=A0NOEXPORT char *connect_client(CLI *, SER= VICE_OPTIONS *, const PHASE);<br>=C2=A0#ifndef OPENSSL_NO_MD4<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' protocol is not support= ed in the server mode";<br>+ =C2=A0 =C2=A0if(!strcasecmp(opt->proto= col, "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_clie= nt(c, opt, phase) :<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"The= 'openldap' protocol is not supported in the server mode";<br>= + =C2=A0 =C2=A0if(!strcasecmp(opt->protocol, "winldap"))<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, phase) :<br>+ =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"The 'winldap' protocol is n= ot supported in the server mode";<br>=C2=A0 =C2=A0 =C2=A0if(!strcasecm= p(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 @@ NOE= XPORT char *nntp_client(CLI *c, SERVI<br>=C2=A0 =C2=A0 =C2=A0return NULL;<b= r>=C2=A0}<br>=C2=A0<br>+/**************************************** LDAP, RFC= 2830 */<br>+uint8_t ldap_startssl_message[0x1d + 2] =3D<br>+{<br>+ =C2=A00= x30, =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 remaining 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 l= en =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 0b01xxxxxx =3D&g= t; 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> 23<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&= #39;1', '.',<br>+ =C2=A0'4', '.',<br>+ =C2=A0&#= 39;1', '.',<br>+ =C2=A0'1', '4', '6', &= #39;6', '.',<br>+ =C2=A0'2', '0', '0', = '3', '7'<br>+ =C2=A0/* No requestValue, as per RFC2830 (in = 2.1: "The requestValue field is absent") */<br>+};<br>+<br>+typed= ef enum {<br>+ =C2=A0 =C2=A0LDAP_OPENLDAP,<br>+ =C2=A0 =C2=A0LDAP_WINLDAP<b= r>+} 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_WINLDAP_FOUR_BY= TE_LEN_FLAG =C2=A0 =C2=A0 =C2=A0 =C2=A00x84<br>+#define LDAP_RESPONSE_MSG_I= D_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 LDAP_RESPONSE_EXP= ECTED_MSG_ID =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x01<br>+#define LDAP_RESPON= SE_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 0x78<br>+#define= LDAP_RESPONSE_EXPECTED_ERR_LEN =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x01<br>+#defin= e 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_OPTIO= NS *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/stunnel-user= s/2013-November/004437.html">https://www.stunnel.org/pipermail/stunnel-user= s/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/msg00800.html">htt= ps://www.openldap.org/lists/openldap-software/200401/msg00800.html</a> */<b= r>+<br>+ =C2=A0 =C2=A0uint8_t buffer_8[1];<br>+ =C2=A0 =C2=A0uint32_t buffe= r_32[1];<br>+ =C2=A0 =C2=A0uint32_t resp_len;<br>+ =C2=A0 =C2=A0uint8_t lda= p_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=A0return N= ULL;<br>+<br>+ =C2=A0 =C2=A0/* send "Start TLS" request to AD ser= ver */<br>+ =C2=A0 =C2=A0s_log(LOG_DEBUG, "Requesting LDAP Start TLS&q= uot;);<br>+ =C2=A0 =C2=A0s_write(c, c->remote_fd.fd, ldap_startssl_messa= ge, (size_t)ldap_startssl_message[1] + 2);<br>+<br>+ =C2=A0 =C2=A0/* LDAP_U= NIVERSAL_SEQUENCE (1 byte) */<br>+ =C2=A0 =C2=A0s_read(c, c->remote_fd.f= d, buffer_8, 1);<br>+ =C2=A0 =C2=A0if(buffer_8[0] !=3D LDAP_UNIVERSAL_SEQUE= NCE) {<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0s_log(LOG_ERR, "start tag is no= t UNIVERSAL SEQUENCE");<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0throw_exceptio= n(c, 1);<br>+ =C2=A0 =C2=A0}<br>+<br>+ =C2=A0 =C2=A0if(ldap_mode =3D=3D LDA= P_OPENLDAP) {<br>+ =C2=A0 =C2=A0 =C2=A0/* OpenLDAP - response length (1 byt= e) */<br>+ =C2=A0 =C2=A0 =C2=A0s_log(LOG_DEBUG, "Reading OpenLDAP mess= age size (1 byte)");<br>+ =C2=A0 =C2=A0 =C2=A0s_read(c, c->remote_f= d.fd, buffer_8, 1);<br>+ =C2=A0 =C2=A0 =C2=A0resp_len =3D buffer_8;<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" flag - LD= AP_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=A0if(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 unexpected value&= quot;);<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0throw_exception(c, 1);<br>+ = =C2=A0 =C2=A0 =C2=A0}<br>+<br>+ =C2=A0 =C2=A0 =C2=A0/* WinLDAP - response l= ength (4 bytes, network byte order) */<br>+ =C2=A0 =C2=A0 =C2=A0s_log(LOG_D= EBUG, "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_R= ESPONSE_MSG_ID_TYPE_INT - 1 byte */<br>+ =C2=A0 =C2=A0if(*resp_ptr !=3D LDA= P_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");<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_MSG_ID_L= EN - 1 byte */<br>+ =C2=A0 =C2=A0if(*resp_ptr !=3D LDAP_RESPONSE_EXPECTED_M= SG_ID_LEN) {<br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0s_log(LOG_ERR, "LDAP resp= onse 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_MSG_ID - 1 byte */<br>= + =C2=A0 =C2=A0if(*resp_ptr !=3D LDAP_RESPONSE_EXPECTED_MSG_ID) {<br>+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0s_log(LOG_ERR, "LDAP response has an unexpecte= d message ID");<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_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 le= ngth is 4 bytes" flag - LDAP_WINLDAP_FOUR_BYTE_LEN_FLAG (1-byte) */<br= >+ =C2=A0 =C2=A0 =C2=A0if(*resp_ptr !=3D LDAP_WINLDAP_FOUR_BYTE_LEN_FLAG) {= <br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0s_log(LOG_ERR, "LDAP extendedR= esp 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 length (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 message 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(LO= G_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=A0r= esp_ptr++;<br>+<br>+ =C2=A0 =C2=A0/* LDAP_RESPONSE_EXT_RESP - 1 byte */<br>= + =C2=A0 =C2=A0if(*resp_ptr !=3D LDAP_RESPONSE_EXPECTED_ERR_LEN) {<br>+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0s_log(LOG_ERR, "LDAP response has an unexpecte= d 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) {<br>+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0s_log(LOG_ERR, "LDAP response has indicated 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;<br>+}<br>+<br>+<br>+NOEX= PORT 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_OPTIONS *opt, const PHASE= phase) {<br>+ =C2=A0return ldap_client(c, opt, phase, LDAP_WINLDAP);<br>+}= <br>+<br>=C2=A0/**************************************** connect */<br>=C2= =A0<br>=C2=A0NOEXPORT char *connect_server(CLI *c, SERVICE_OPTIONS *opt, co= nst PHASE phase) {</div> --0000000000002507ff0598d366b5-- --===============3938563711249280035== 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 --===============3938563711249280035==--