/src/mosquitto/src/proxy_v1.c
Line | Count | Source |
1 | | #ifdef WIN32 |
2 | | # include <winsock2.h> |
3 | | # include <ws2tcpip.h> |
4 | | #else |
5 | | # include <arpa/inet.h> |
6 | | #endif |
7 | | #include <stdint.h> |
8 | | #include "mosquitto_broker_internal.h" |
9 | | #include "mosquitto_internal.h" |
10 | | #include "net_mosq.h" |
11 | | |
12 | | #if !defined(WITH_WEBSOCKETS) || WITH_WEBSOCKETS == WS_IS_BUILTIN |
13 | | |
14 | 4.26k | #define PROXY_V1_PACKET_LIMIT 108 |
15 | | |
16 | | const uint8_t signature4[11] = {'P', 'R', 'O', 'X', 'Y', ' ', 'T', 'C', 'P', '4', ' '}; |
17 | | const uint8_t signature6[11] = {'P', 'R', 'O', 'X', 'Y', ' ', 'T', 'C', 'P', '6', ' '}; |
18 | | const uint8_t signatureU[14] = {'P', 'R', 'O', 'X', 'Y', ' ', 'U', 'N', 'K', 'N', 'O', 'W', 'N', ' '}; |
19 | | |
20 | | |
21 | | static void proxy_cleanup(struct mosquitto *context) |
22 | 74 | { |
23 | 74 | mosquitto_FREE(context->proxy.buf); |
24 | 74 | } |
25 | | |
26 | | |
27 | | static int update_transport(struct mosquitto *context) |
28 | 0 | { |
29 | 0 | #if defined(WITH_WEBSOCKETS) && WITH_WEBSOCKETS == WS_IS_BUILTIN |
30 | 0 | if(context->listener->protocol == mp_websockets){ |
31 | 0 | return http__context_init(context); |
32 | 0 | }else |
33 | 0 | #endif |
34 | 0 | { |
35 | 0 | context->transport = mosq_t_tcp; |
36 | 0 | } |
37 | 0 | return MOSQ_ERR_SUCCESS; |
38 | 0 | } |
39 | | |
40 | | |
41 | | static int get_address_for_unknown(struct mosquitto *context) |
42 | 0 | { |
43 | 0 | char address[1024]; |
44 | |
|
45 | 0 | proxy_cleanup(context); |
46 | |
|
47 | 0 | if(!net__socket_get_address(context->sock, address, sizeof(address), &context->remote_port)){ |
48 | 0 | context->address = mosquitto_strdup(address); |
49 | 0 | } |
50 | 0 | if(!context->address){ |
51 | 0 | return MOSQ_ERR_NOMEM; |
52 | 0 | } |
53 | 0 | return update_transport(context); |
54 | 0 | } |
55 | | |
56 | | |
57 | | static int proxy_v1__decode(struct mosquitto *context) |
58 | 0 | { |
59 | 0 | char *saddr_s, *daddr_s, *sport_s, *dport_s; |
60 | 0 | char *saveptr = NULL; |
61 | 0 | int sport, dport; |
62 | 0 | struct in6_addr addr; |
63 | |
|
64 | 0 | if(context->proxy.pos >= sizeof(signatureU) && !memcmp(context->proxy.buf, signatureU, sizeof(signatureU))){ |
65 | 0 | return get_address_for_unknown(context); |
66 | 0 | }else if(context->proxy.pos >= sizeof(signature4) && !memcmp(context->proxy.buf, signature4, sizeof(signature4))){ |
67 | 0 | context->proxy.fam = AF_INET; |
68 | 0 | }else if(context->proxy.pos >= sizeof(signature6) && !memcmp(context->proxy.buf, signature6, sizeof(signature6))){ |
69 | 0 | context->proxy.fam = AF_INET6; |
70 | 0 | }else{ |
71 | 0 | log__printf(NULL, MOSQ_LOG_NOTICE, "Connection rejected, corrupt PROXY header."); |
72 | 0 | proxy_cleanup(context); |
73 | 0 | return MOSQ_ERR_INVAL; |
74 | 0 | } |
75 | | |
76 | 0 | context->proxy.buf[context->proxy.pos-1] = '\0'; |
77 | 0 | context->proxy.buf[context->proxy.pos-2] = '\0'; |
78 | 0 | saddr_s = strtok_r((char *)&context->proxy.buf[sizeof(signature4)], " ", &saveptr); |
79 | 0 | daddr_s = strtok_r(NULL, " ", &saveptr); |
80 | 0 | sport_s = strtok_r(NULL, " ", &saveptr); |
81 | 0 | dport_s = strtok_r(NULL, " ", &saveptr); |
82 | | |
83 | |
|
84 | 0 | if(!saddr_s || !daddr_s || !sport_s || !dport_s || (saveptr && strlen(saveptr) > 0)){ |
85 | 0 | log__printf(NULL, MOSQ_LOG_NOTICE, "Connection rejected, corrupt PROXY header."); |
86 | 0 | proxy_cleanup(context); |
87 | 0 | return MOSQ_ERR_INVAL; |
88 | 0 | } |
89 | | |
90 | | /* Verify ports */ |
91 | 0 | sport = atoi(sport_s); |
92 | 0 | dport = atoi(dport_s); |
93 | 0 | if(sport < 1 || sport > 65535 || dport < 1 || dport > 65535){ |
94 | 0 | log__printf(NULL, MOSQ_LOG_NOTICE, "Connection rejected, corrupt PROXY header."); |
95 | 0 | proxy_cleanup(context); |
96 | 0 | return MOSQ_ERR_INVAL; |
97 | 0 | } |
98 | | |
99 | | /* Verify addresses */ |
100 | 0 | if(context->proxy.fam == AF_INET){ |
101 | 0 | if(inet_pton(AF_INET, saddr_s, &addr) != 1 |
102 | 0 | || inet_pton(AF_INET, daddr_s, &addr) != 1){ |
103 | |
|
104 | 0 | log__printf(NULL, MOSQ_LOG_NOTICE, "Connection rejected, corrupt PROXY header."); |
105 | 0 | proxy_cleanup(context); |
106 | 0 | return MOSQ_ERR_INVAL; |
107 | 0 | } |
108 | 0 | }else if(context->proxy.fam == AF_INET6){ |
109 | 0 | if(inet_pton(AF_INET6, saddr_s, &addr) != 1 |
110 | 0 | || inet_pton(AF_INET6, daddr_s, &addr) != 1){ |
111 | |
|
112 | 0 | log__printf(NULL, MOSQ_LOG_NOTICE, "Connection rejected, corrupt PROXY header."); |
113 | 0 | proxy_cleanup(context); |
114 | 0 | return MOSQ_ERR_INVAL; |
115 | 0 | } |
116 | 0 | } |
117 | | |
118 | 0 | context->address = mosquitto_strdup(saddr_s); |
119 | 0 | if(!context->address){ |
120 | 0 | proxy_cleanup(context); |
121 | 0 | return MOSQ_ERR_NOMEM; |
122 | 0 | } |
123 | 0 | context->remote_port = (uint16_t )sport; |
124 | 0 | proxy_cleanup(context); |
125 | 0 | return update_transport(context); |
126 | 0 | } |
127 | | |
128 | | |
129 | | int proxy_v1__read(struct mosquitto *context) |
130 | 74 | { |
131 | 74 | if(context->proxy.buf == NULL){ |
132 | 74 | context->proxy.buf = mosquitto_calloc(1, PROXY_V1_PACKET_LIMIT); |
133 | 74 | if(!context->proxy.buf){ |
134 | 0 | return MOSQ_ERR_NOMEM; |
135 | 0 | } |
136 | 74 | context->proxy.pos = 0; |
137 | 74 | } |
138 | | |
139 | 4.16k | while(context->proxy.pos < PROXY_V1_PACKET_LIMIT){ |
140 | 4.12k | if(net__read(context, &(context->proxy.buf[context->proxy.pos]), 1) != 1){ |
141 | 42 | proxy_cleanup(context); |
142 | 42 | return MOSQ_ERR_CONN_LOST; |
143 | 42 | } |
144 | 4.08k | context->proxy.pos++; |
145 | 4.08k | if(context->proxy.pos > 2){ /* FIXME: Figure out better limit */ |
146 | 3.94k | if(context->proxy.buf[context->proxy.pos-1] == '\n' |
147 | 417 | && context->proxy.buf[context->proxy.pos-2] == '\r'){ |
148 | | |
149 | | /* Line received, now decode */ |
150 | 0 | return proxy_v1__decode(context); |
151 | 0 | } |
152 | 3.94k | } |
153 | 4.08k | } |
154 | 32 | if(context->proxy.pos == PROXY_V1_PACKET_LIMIT){ |
155 | 32 | log__printf(NULL, MOSQ_LOG_NOTICE, "Connection rejected, corrupt PROXY header."); |
156 | 32 | proxy_cleanup(context); |
157 | 32 | return MOSQ_ERR_INVAL; |
158 | 32 | } |
159 | | |
160 | 0 | return MOSQ_ERR_SUCCESS; |
161 | 32 | } |
162 | | #endif |