diff --git a/lib/socks_mosq.c b/lib/socks_mosq.c index 9bc9094e..b50c2d51 100644 --- a/lib/socks_mosq.c +++ b/lib/socks_mosq.c @@ -114,6 +114,16 @@ int mosquitto_socks5_set(struct mosquitto *mosq, const char *host, int port, con } #ifdef WITH_SOCKS +static void socks5__packet_alloc(struct mosquitto__packet **packet, uint32_t packet_length) +{ + *packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet) + packet_length + WS_PACKET_OFFSET); + if(!(*packet)) return; + (*packet)->pos = WS_PACKET_OFFSET; + (*packet)->packet_length = packet_length + WS_PACKET_OFFSET; + (*packet)->to_process = packet_length; +} + + int socks5__send(struct mosquitto *mosq) { struct mosquitto__packet *packet; @@ -136,17 +146,17 @@ int socks5__send(struct mosquitto *mosq) packet_length = 3; } - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet) + packet_length); + socks5__packet_alloc(&packet, packet_length); if(!packet) return MOSQ_ERR_NOMEM; - packet->payload[0] = 0x05; + packet->payload[0 + WS_PACKET_OFFSET] = 0x05; if(mosq->socks5_username){ - packet->payload[1] = 2; - packet->payload[2] = SOCKS_AUTH_NONE; - packet->payload[3] = SOCKS_AUTH_USERPASS; + packet->payload[1 + WS_PACKET_OFFSET] = 2; + packet->payload[2 + WS_PACKET_OFFSET] = SOCKS_AUTH_NONE; + packet->payload[3 + WS_PACKET_OFFSET] = SOCKS_AUTH_USERPASS; }else{ - packet->payload[1] = 1; - packet->payload[2] = SOCKS_AUTH_NONE; + packet->payload[1 + WS_PACKET_OFFSET] = 1; + packet->payload[2 + WS_PACKET_OFFSET] = SOCKS_AUTH_NONE; } mosquitto__set_state(mosq, mosq_cs_socks5_start); @@ -168,25 +178,23 @@ int socks5__send(struct mosquitto *mosq) if(ipv4_pton_result == 1){ packet_length = 10; - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet) + packet_length); + socks5__packet_alloc(&packet, packet_length); if(!packet) return MOSQ_ERR_NOMEM; - packet->payload[3] = SOCKS_ATYPE_IP_V4; - memcpy(&(packet->payload[4]), (const void*)&addr_ipv4, 4); - packet->payload[4+4] = MOSQ_MSB(mosq->port); - packet->payload[4+4+1] = MOSQ_LSB(mosq->port); - + packet->payload[3 + WS_PACKET_OFFSET] = SOCKS_ATYPE_IP_V4; + memcpy(&(packet->payload[4 + WS_PACKET_OFFSET]), (const void*)&addr_ipv4, 4); + packet->payload[4+4 + WS_PACKET_OFFSET] = MOSQ_MSB(mosq->port); + packet->payload[4+4+1 + WS_PACKET_OFFSET] = MOSQ_LSB(mosq->port); }else if(ipv6_pton_result == 1){ packet_length = 22; - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet) + packet_length); + socks5__packet_alloc(&packet, packet_length); if(!packet) return MOSQ_ERR_NOMEM; - packet->payload[3] = SOCKS_ATYPE_IP_V6; - memcpy(&(packet->payload[4]), (const void*)&addr_ipv6, 16); - packet->payload[4+16] = MOSQ_MSB(mosq->port); - packet->payload[4+16+1] = MOSQ_LSB(mosq->port); - + packet->payload[3 + WS_PACKET_OFFSET] = SOCKS_ATYPE_IP_V6; + memcpy(&(packet->payload[4 + WS_PACKET_OFFSET]), (const void*)&addr_ipv6, 16); + packet->payload[4+16 + WS_PACKET_OFFSET] = MOSQ_MSB(mosq->port); + packet->payload[4+16+1 + WS_PACKET_OFFSET] = MOSQ_LSB(mosq->port); }else{ slen = strlen(mosq->host); if(slen > UCHAR_MAX){ @@ -194,18 +202,18 @@ int socks5__send(struct mosquitto *mosq) } packet_length = 7U + (uint32_t)slen; - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet) + packet_length); + socks5__packet_alloc(&packet, packet_length); if(!packet) return MOSQ_ERR_NOMEM; - packet->payload[3] = SOCKS_ATYPE_DOMAINNAME; - packet->payload[4] = (uint8_t)slen; - memcpy(&(packet->payload[5]), mosq->host, slen); - packet->payload[5+slen] = MOSQ_MSB(mosq->port); - packet->payload[6+slen] = MOSQ_LSB(mosq->port); + packet->payload[3 + WS_PACKET_OFFSET] = SOCKS_ATYPE_DOMAINNAME; + packet->payload[4 + WS_PACKET_OFFSET] = (uint8_t)slen; + memcpy(&(packet->payload[5 + WS_PACKET_OFFSET]), mosq->host, slen); + packet->payload[5+slen + WS_PACKET_OFFSET] = MOSQ_MSB(mosq->port); + packet->payload[6+slen + WS_PACKET_OFFSET] = MOSQ_LSB(mosq->port); } - packet->payload[0] = 0x05; - packet->payload[1] = 0x01; - packet->payload[2] = 0x00; + packet->payload[0 + WS_PACKET_OFFSET] = 0x05; + packet->payload[1 + WS_PACKET_OFFSET] = 0x01; + packet->payload[2 + WS_PACKET_OFFSET] = 0x00; mosquitto__set_state(mosq, mosq_cs_socks5_request); @@ -224,14 +232,14 @@ int socks5__send(struct mosquitto *mosq) plen = (uint8_t)strlen(mosq->socks5_password); packet_length = 3U + ulen + plen; - packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet) + packet_length); + socks5__packet_alloc(&packet, packet_length); if(!packet) return MOSQ_ERR_NOMEM; - packet->payload[0] = 0x01; - packet->payload[1] = ulen; - memcpy(&(packet->payload[2]), mosq->socks5_username, ulen); - packet->payload[2+ulen] = plen; - memcpy(&(packet->payload[3+ulen]), mosq->socks5_password, plen); + packet->payload[0 + WS_PACKET_OFFSET] = 0x01; + packet->payload[1 + WS_PACKET_OFFSET] = ulen; + memcpy(&(packet->payload[2 + WS_PACKET_OFFSET]), mosq->socks5_username, ulen); + packet->payload[2+ulen + WS_PACKET_OFFSET] = plen; + memcpy(&(packet->payload[3+ulen + WS_PACKET_OFFSET]), mosq->socks5_password, plen); mosquitto__set_state(mosq, mosq_cs_socks5_userpass_reply); diff --git a/test/client/03-publish-socks.py b/test/client/03-publish-socks.py new file mode 100755 index 00000000..7ce2d593 --- /dev/null +++ b/test/client/03-publish-socks.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 + +# + +from mosq_test_helper import * + +def do_test(proto_ver): + rc = 1 + + (port1, port2) = mosq_test.get_port(2) + + cmd = ['microsocks', '-1', '-b', '-i', '127.0.0.1', '-u', 'user', '-P', 'password', '-p', str(port1)] + try: + proxy = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except FileNotFoundError: + print("microsocks not found, skipping test") + sys.exit(0) + + if proto_ver == 5: + V = 'mqttv5' + elif proto_ver == 4: + V = 'mqttv311' + else: + V = 'mqttv31' + + env = { + 'LD_LIBRARY_PATH':'../../lib', + 'XDG_CONFIG_HOME':'/tmp/missing' + } + cmd = [ + '/snap/bin/valgrind', '--log-file=vglog', + '../../client/mosquitto_pub', + '-h', '127.0.0.1', + '-p', str(port2), + '-q', '1', + '-t', '03/pub/proxy/test', + '-m', 'message', + '-V', V, + '--proxy', f'socks5h://user:password@localhost:{port1}' + ] + + mid = 1 + publish_packet = mosq_test.gen_publish("03/pub/proxy/test", qos=1, mid=mid, payload="message", proto_ver=proto_ver) + if proto_ver == 5: + puback_packet = mosq_test.gen_puback(mid, proto_ver=proto_ver, reason_code=mqtt5_rc.MQTT_RC_NO_MATCHING_SUBSCRIBERS) + else: + puback_packet = mosq_test.gen_puback(mid, proto_ver=proto_ver) + + broker = mosq_test.start_broker(filename=os.path.basename(__file__), port=port2) + + try: + sock = mosq_test.sub_helper(port=port2, topic="#", qos=1, proto_ver=proto_ver) + + pub = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) + pub.wait() + (stdo, stde) = pub.communicate() + + mosq_test.expect_packet(sock, "publish", publish_packet) + rc = 0 + sock.close() + except mosq_test.TestError: + pass + except Exception as e: + print(e) + finally: + proxy.terminate() + broker.terminate() + broker.wait() + (stdo, stde) = broker.communicate() + if rc: + print(stde.decode('utf-8')) + print("proto_ver=%d" % (proto_ver)) + exit(rc) + + +do_test(proto_ver=3) +do_test(proto_ver=4) +do_test(proto_ver=5) diff --git a/test/client/Makefile b/test/client/Makefile index 1f51a879..1a4d3426 100644 --- a/test/client/Makefile +++ b/test/client/Makefile @@ -19,6 +19,7 @@ test : 02 03 ./03-publish-qos0-empty.py ./03-publish-qos1-properties.py ./03-publish-qos1.py + ./03-publish-socks.py ptest : ./test.sh diff --git a/test/client/test.py b/test/client/test.py index 6fdb419f..abd5ca38 100755 --- a/test/client/test.py +++ b/test/client/test.py @@ -15,6 +15,7 @@ tests = [ (1, './03-publish-qos0-empty.py'), (1, './03-publish-qos1-properties.py'), (1, './03-publish-qos1.py'), + (2, './03-publish-socks.py'), ] ptest.run_tests(tests)