sendhex "300C020101 61 070A01 01 04000400"
} -start
+server s4 {
+ recv 14
+ sendhex "308400000010020101 61 84000000070A01"
+ delay 0.1
+ sendhex "00 04000400"
+} -start
+
syslog S1 -level notice {
recv
expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv succeeded, reason: Layer7 check passed.+info: \"Success\".+check duration: [[:digit:]]+ms, status: 1/1 UP."
expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be3/srv failed, reason: Layer7 wrong status.+code: 1.+info: \"See RFC: http://tools.ietf.org/html/rfc4511#section-4.1.9\".+check duration: [[:digit:]]+ms, status: 0/1 DOWN."
} -start
+syslog S4 -level notice {
+ recv
+ expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be4/srv succeeded, reason: Layer7 check passed.+info: \"Success\".+check duration: [[:digit:]]+ms, status: 1/1 UP."
+} -start
+
haproxy h1 -conf {
defaults
mode tcp
option ldap-check
server srv ${s3_addr}:${s3_port} check inter 1s rise 1 fall 1
+ backend be4
+ log ${S4_addr}:${S4_port} daemon
+ option log-health-checks
+ option ldap-check
+ server srv ${s4_addr}:${s4_port} check inter 1s rise 1 fall 1
+
listen ldap1
bind "fd@${ldap1}"
tcp-request inspect-delay 100ms
syslog S1 -wait
syslog S2 -wait
syslog S3 -wait
+syslog S4 -wait
#include <haproxy/istbuf.h>
#include <haproxy/list.h>
#include <haproxy/log.h>
+#include <haproxy/net_helper.h>
#include <haproxy/protocol.h>
#include <haproxy/proxy-t.h>
#include <haproxy/regex.h>
enum healthcheck_status status;
struct buffer *msg = NULL;
struct ist desc = IST_NULL;
- unsigned short msglen = 0;
+ char *ptr;
+ unsigned short nbytes = 0;
+ size_t msglen = 0;
TRACE_ENTER(CHK_EV_TCPCHK_EXP, check);
* http://en.wikipedia.org/wiki/Basic_Encoding_Rules
* http://tools.ietf.org/html/rfc4511
*/
+ ptr = b_head(&check->bi) + 1;
+
/* size of LDAPMessage */
- msglen = (*(b_head(&check->bi) + 1) & 0x80) ? (*(b_head(&check->bi) + 1) & 0x7f) : 0;
+ if (*ptr & 0x80) {
+ /* For message size encoded on several bytes, we only handle
+ * size encoded on 2 or 4 bytes. There is no reason to make this
+ * part to complex because only Active Directory is known to
+ * encode BindReponse length on 4 bytes.
+ */
+ nbytes = (*ptr & 0x7f);
+ if (b_data(&check->bi) < 1 + nbytes)
+ goto too_short;
+ switch (nbytes) {
+ case 4: msglen = read_n32(ptr+1); break;
+ case 2: msglen = read_n16(ptr+1); break;
+ default:
+ status = HCHK_STATUS_L7RSP;
+ desc = ist("Not LDAPv3 protocol");
+ goto error;
+ }
+ }
+ else
+ msglen = *ptr;
+ ptr += 1 + nbytes;
+
+ if (b_data(&check->bi) < 2 + nbytes + msglen)
+ goto too_short;
/* http://tools.ietf.org/html/rfc4511#section-4.2.2
* messageID: 0x02 0x01 0x01: INTEGER 1
* protocolOp: 0x61: bindResponse
*/
- if ((msglen > 2) || (memcmp(b_head(&check->bi) + 2 + msglen, "\x02\x01\x01\x61", 4) != 0)) {
+ if (memcmp(ptr, "\x02\x01\x01\x61", 4) != 0) {
status = HCHK_STATUS_L7RSP;
desc = ist("Not LDAPv3 protocol");
goto error;
}
+ ptr += 4;
- /* size of bindResponse */
- msglen += (*(b_head(&check->bi) + msglen + 6) & 0x80) ? (*(b_head(&check->bi) + msglen + 6) & 0x7f) : 0;
+ /* skip size of bindResponse */
+ nbytes = 0;
+ if (*ptr & 0x80)
+ nbytes = (*ptr & 0x7f);
+ ptr += 1 + nbytes;
/* http://tools.ietf.org/html/rfc4511#section-4.1.9
* ldapResult: 0x0a 0x01: ENUMERATION
*/
- if ((msglen > 4) || (memcmp(b_head(&check->bi) + 7 + msglen, "\x0a\x01", 2) != 0)) {
+ if (memcmp(ptr, "\x0a\x01", 2) != 0) {
status = HCHK_STATUS_L7RSP;
desc = ist("Not LDAPv3 protocol");
goto error;
}
+ ptr += 2;
/* http://tools.ietf.org/html/rfc4511#section-4.1.9
* resultCode
*/
- check->code = *(b_head(&check->bi) + msglen + 9);
+ check->code = *ptr;
if (check->code) {
status = HCHK_STATUS_L7STS;
desc = ist("See RFC: http://tools.ietf.org/html/rfc4511#section-4.1.9");
tcpcheck_expect_onerror_message(msg, check, rule, 0, desc);
set_server_check_status(check, status, (msg ? b_head(msg) : NULL));
goto out;
+
+ too_short:
+ if (!last_read)
+ goto wait_more_data;
+ /* invalid length or truncated response */
+ status = HCHK_STATUS_L7RSP;
+ goto error;
+
+ wait_more_data:
+ TRACE_DEVEL("waiting for more data", CHK_EV_TCPCHK_EXP, check);
+ ret = TCPCHK_EVAL_WAIT;
+ goto out;
}
/* Custom tcp-check expect function to parse and validate the SPOP hello agent