1: /*
2: * Functions for looking up the remote name or addr of a socket.
3: *
4: * Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
5: * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
6: * Copyright (C) 2002-2020 Wayne Davison
7: *
8: * This program is free software; you can redistribute it and/or modify
9: * it under the terms of the GNU General Public License as published by
10: * the Free Software Foundation; either version 3 of the License, or
11: * (at your option) any later version.
12: *
13: * This program is distributed in the hope that it will be useful,
14: * but WITHOUT ANY WARRANTY; without even the implied warranty of
15: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: * GNU General Public License for more details.
17: *
18: * You should have received a copy of the GNU General Public License along
19: * with this program; if not, visit the http://fsf.org website.
20: */
21:
22: /*
23: * This file is now converted to use the new-style getaddrinfo()
24: * interface, which supports IPv6 but is also supported on recent
25: * IPv4-only machines. On systems that don't have that interface, we
26: * emulate it using the KAME implementation.
27: */
28:
29: #include "rsync.h"
30: #include "itypes.h"
31:
32: extern int am_daemon;
33:
34: static const char default_name[] = "UNKNOWN";
35: static const char proxyv2sig[] = "\r\n\r\n\0\r\nQUIT\n";
36:
37: static char ipaddr_buf[100];
38:
39: #define PROXY_V2_SIG_SIZE ((int)sizeof proxyv2sig - 1)
40: #define PROXY_V2_HEADER_SIZE (PROXY_V2_SIG_SIZE + 1 + 1 + 2)
41:
42: #define CMD_LOCAL 0
43: #define CMD_PROXY 1
44:
45: #define PROXY_FAM_TCPv4 0x11
46: #define PROXY_FAM_TCPv6 0x21
47:
48: #define GET_SOCKADDR_FAMILY(ss) ((struct sockaddr*)ss)->sa_family
49:
50: static void client_sockaddr(int fd, struct sockaddr_storage *ss, socklen_t *ss_len);
51: static int check_name(const char *ipaddr, const struct sockaddr_storage *ss, char *name_buf, size_t name_buf_size);
52: static int valid_ipaddr(const char *s);
53:
54: /* Return the IP addr of the client as a string. */
55: char *client_addr(int fd)
56: {
57: struct sockaddr_storage ss;
58: socklen_t length = sizeof ss;
59:
60: if (*ipaddr_buf)
61: return ipaddr_buf;
62:
63: if (am_daemon < 0) { /* daemon over --rsh mode */
64: char *env_str;
65: strlcpy(ipaddr_buf, "0.0.0.0", sizeof ipaddr_buf);
66: if ((env_str = getenv("REMOTE_HOST")) != NULL
67: || (env_str = getenv("SSH_CONNECTION")) != NULL
68: || (env_str = getenv("SSH_CLIENT")) != NULL
69: || (env_str = getenv("SSH2_CLIENT")) != NULL) {
70: char *p;
71: strlcpy(ipaddr_buf, env_str, sizeof ipaddr_buf);
72: /* Truncate the value to just the IP address. */
73: if ((p = strchr(ipaddr_buf, ' ')) != NULL)
74: *p = '\0';
75: }
76: if (valid_ipaddr(ipaddr_buf))
77: return ipaddr_buf;
78: }
79:
80: client_sockaddr(fd, &ss, &length);
81: getnameinfo((struct sockaddr *)&ss, length, ipaddr_buf, sizeof ipaddr_buf, NULL, 0, NI_NUMERICHOST);
82:
83: return ipaddr_buf;
84: }
85:
86:
87: /**
88: * Return the DNS name of the client.
89: *
90: * The name is statically cached so that repeated lookups are quick,
91: * so there is a limit of one lookup per customer.
92: *
93: * If anything goes wrong, including the name->addr->name check, then
94: * we just use "UNKNOWN", so you can use that value in hosts allow
95: * lines.
96: *
97: * After translation from sockaddr to name we do a forward lookup to
98: * make sure nobody is spoofing PTR records.
99: **/
100: char *client_name(const char *ipaddr)
101: {
102: static char name_buf[100];
103: char port_buf[100];
104: struct sockaddr_storage ss;
105: socklen_t ss_len;
106: struct addrinfo hint, *answer;
107: int err;
108:
109: if (*name_buf)
110: return name_buf;
111:
112: strlcpy(name_buf, default_name, sizeof name_buf);
113:
114: if (strcmp(ipaddr, "0.0.0.0") == 0)
115: return name_buf;
116:
117: memset(&ss, 0, sizeof ss);
118: memset(&hint, 0, sizeof hint);
119:
120: #ifdef AI_NUMERICHOST
121: hint.ai_flags = AI_NUMERICHOST;
122: #endif
123: hint.ai_socktype = SOCK_STREAM;
124:
125: if ((err = getaddrinfo(ipaddr, NULL, &hint, &answer)) != 0) {
126: rprintf(FLOG, "malformed address %s: %s\n", ipaddr, gai_strerror(err));
127: return name_buf;
128: }
129:
130: switch (answer->ai_family) {
131: case AF_INET:
132: ss_len = sizeof (struct sockaddr_in);
133: memcpy(&ss, answer->ai_addr, ss_len);
134: break;
135: #ifdef INET6
136: case AF_INET6:
137: ss_len = sizeof (struct sockaddr_in6);
138: memcpy(&ss, answer->ai_addr, ss_len);
139: break;
140: #endif
141: default:
142: NOISY_DEATH("Unknown ai_family value");
143: }
144: freeaddrinfo(answer);
145:
146: /* reverse lookup */
147: err = getnameinfo((struct sockaddr*)&ss, ss_len, name_buf, sizeof name_buf,
148: port_buf, sizeof port_buf, NI_NAMEREQD | NI_NUMERICSERV);
149: if (err) {
150: strlcpy(name_buf, default_name, sizeof name_buf);
151: rprintf(FLOG, "name lookup failed for %s: %s\n", ipaddr, gai_strerror(err));
152: } else
153: check_name(ipaddr, &ss, name_buf, sizeof name_buf);
154:
155: return name_buf;
156: }
157:
158:
159: /* Try to read a proxy protocol header (V1 or V2). Returns 1 on success or 0 on failure. */
160: int read_proxy_protocol_header(int fd)
161: {
162: union {
163: struct {
164: char line[108];
165: } v1;
166: struct {
167: char sig[PROXY_V2_SIG_SIZE];
168: char ver_cmd;
169: char fam;
170: char len[2];
171: union {
172: struct {
173: char src_addr[4];
174: char dst_addr[4];
175: char src_port[2];
176: char dst_port[2];
177: } ip4;
178: struct {
179: char src_addr[16];
180: char dst_addr[16];
181: char src_port[2];
182: char dst_port[2];
183: } ip6;
184: struct {
185: char src_addr[108];
186: char dst_addr[108];
187: } unx;
188: } addr;
189: } v2;
190: } hdr;
191:
192: read_buf(fd, (char*)&hdr, PROXY_V2_SIG_SIZE);
193:
194: if (memcmp(hdr.v2.sig, proxyv2sig, PROXY_V2_SIG_SIZE) == 0) { /* Proxy V2 */
195: int ver, cmd, size;
196:
197: read_buf(fd, (char*)&hdr + PROXY_V2_SIG_SIZE, PROXY_V2_HEADER_SIZE - PROXY_V2_SIG_SIZE);
198:
199: ver = (hdr.v2.ver_cmd & 0xf0) >> 4;
200: cmd = (hdr.v2.ver_cmd & 0x0f);
201: size = (hdr.v2.len[0] << 8) + hdr.v2.len[1];
202:
203: if (ver != 2 || size + PROXY_V2_HEADER_SIZE > (int)sizeof hdr)
204: return 0;
205:
206: /* Grab all the remaining data in the binary request. */
207: read_buf(fd, (char*)&hdr + PROXY_V2_HEADER_SIZE, size);
208:
209: switch (cmd) {
210: case CMD_PROXY:
211: switch (hdr.v2.fam) {
212: case PROXY_FAM_TCPv4:
213: if (size != sizeof hdr.v2.addr.ip4)
214: return 0;
215: inet_ntop(AF_INET, hdr.v2.addr.ip4.src_addr, ipaddr_buf, sizeof ipaddr_buf);
216: return valid_ipaddr(ipaddr_buf);
217: case PROXY_FAM_TCPv6:
218: if (size != sizeof hdr.v2.addr.ip6)
219: return 0;
220: inet_ntop(AF_INET6, hdr.v2.addr.ip6.src_addr, ipaddr_buf, sizeof ipaddr_buf);
221: return valid_ipaddr(ipaddr_buf);
222: default:
223: break;
224: }
225: /* For an unsupported protocol we'll ignore the proxy data (leaving ipaddr_buf unset)
226: * and accept the connection, which will get handled as a normal socket addr. */
227: return 1;
228: case CMD_LOCAL:
229: return 1;
230: default:
231: break;
232: }
233:
234: return 0;
235: }
236:
237: if (memcmp(hdr.v1.line, "PROXY", 5) == 0) { /* Proxy V1 */
238: char *endc, *sp, *p = hdr.v1.line + PROXY_V2_SIG_SIZE;
239: int port_chk;
240:
241: *p = '\0';
242: if (!strchr(hdr.v1.line, '\n')) {
243: while (1) {
244: read_buf(fd, p, 1);
245: if (*p++ == '\n')
246: break;
247: if (p - hdr.v1.line >= (int)sizeof hdr.v1.line - 1)
248: return 0;
249: }
250: *p = '\0';
251: }
252:
253: endc = strchr(hdr.v1.line, '\r');
254: if (!endc || endc[1] != '\n' || endc[2])
255: return 0;
256: *endc = '\0';
257:
258: p = hdr.v1.line + 5;
259:
260: if (!isSpace(p++))
261: return 0;
262: if (strncmp(p, "TCP4", 4) == 0)
263: p += 4;
264: else if (strncmp(p, "TCP6", 4) == 0)
265: p += 4;
266: else if (strncmp(p, "UNKNOWN", 7) == 0)
267: return 1;
268: else
269: return 0;
270:
271: if (!isSpace(p++))
272: return 0;
273:
274: if ((sp = strchr(p, ' ')) == NULL)
275: return 0;
276: *sp = '\0';
277: if (!valid_ipaddr(p))
278: return 0;
279: strlcpy(ipaddr_buf, p, sizeof ipaddr_buf); /* It will always fit when valid. */
280:
281: p = sp + 1;
282: if ((sp = strchr(p, ' ')) == NULL)
283: return 0;
284: *sp = '\0';
285: if (!valid_ipaddr(p))
286: return 0;
287: /* Ignore destination address. */
288:
289: p = sp + 1;
290: if ((sp = strchr(p, ' ')) == NULL)
291: return 0;
292: *sp = '\0';
293: port_chk = strtol(p, &endc, 10);
294: if (*endc || port_chk == 0)
295: return 0;
296: /* Ignore source port. */
297:
298: p = sp + 1;
299: port_chk = strtol(p, &endc, 10);
300: if (*endc || port_chk == 0)
301: return 0;
302: /* Ignore destination port. */
303:
304: return 1;
305: }
306:
307: return 0;
308: }
309:
310:
311: /**
312: * Get the sockaddr for the client.
313: *
314: * If it comes in as an ipv4 address mapped into IPv6 format then we
315: * convert it back to a regular IPv4.
316: **/
317: static void client_sockaddr(int fd, struct sockaddr_storage *ss, socklen_t *ss_len)
318: {
319: memset(ss, 0, sizeof *ss);
320:
321: if (getpeername(fd, (struct sockaddr *) ss, ss_len)) {
322: /* FIXME: Can we really not continue? */
323: rsyserr(FLOG, errno, "getpeername on fd%d failed", fd);
324: exit_cleanup(RERR_SOCKETIO);
325: }
326:
327: #ifdef INET6
328: if (GET_SOCKADDR_FAMILY(ss) == AF_INET6
329: && IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
330: /* OK, so ss is in the IPv6 family, but it is really
331: * an IPv4 address: something like
332: * "::ffff:10.130.1.2". If we use it as-is, then the
333: * reverse lookup might fail or perhaps something else
334: * bad might happen. So instead we convert it to an
335: * equivalent address in the IPv4 address family. */
336: struct sockaddr_in6 sin6;
337: struct sockaddr_in *sin;
338:
339: memcpy(&sin6, ss, sizeof sin6);
340: sin = (struct sockaddr_in *)ss;
341: memset(sin, 0, sizeof *sin);
342: sin->sin_family = AF_INET;
343: *ss_len = sizeof (struct sockaddr_in);
344: #ifdef HAVE_SOCKADDR_IN_LEN
345: sin->sin_len = *ss_len;
346: #endif
347: sin->sin_port = sin6.sin6_port;
348:
349: /* There is a macro to extract the mapped part
350: * (IN6_V4MAPPED_TO_SINADDR ?), but it does not seem
351: * to be present in the Linux headers. */
352: memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12], sizeof sin->sin_addr);
353: }
354: #endif
355: }
356:
357:
358: /**
359: * Compare an addrinfo from the resolver to a sockinfo.
360: *
361: * Like strcmp, returns 0 for identical.
362: **/
363: static int compare_addrinfo_sockaddr(const struct addrinfo *ai, const struct sockaddr_storage *ss)
364: {
365: int ss_family = GET_SOCKADDR_FAMILY(ss);
366: const char fn[] = "compare_addrinfo_sockaddr";
367:
368: if (ai->ai_family != ss_family) {
369: rprintf(FLOG, "%s: response family %d != %d\n",
370: fn, ai->ai_family, ss_family);
371: return 1;
372: }
373:
374: /* The comparison method depends on the particular AF. */
375: if (ss_family == AF_INET) {
376: const struct sockaddr_in *sin1, *sin2;
377:
378: sin1 = (const struct sockaddr_in *) ss;
379: sin2 = (const struct sockaddr_in *) ai->ai_addr;
380:
381: return memcmp(&sin1->sin_addr, &sin2->sin_addr, sizeof sin1->sin_addr);
382: }
383:
384: #ifdef INET6
385: if (ss_family == AF_INET6) {
386: const struct sockaddr_in6 *sin1, *sin2;
387:
388: sin1 = (const struct sockaddr_in6 *) ss;
389: sin2 = (const struct sockaddr_in6 *) ai->ai_addr;
390:
391: if (ai->ai_addrlen < (int)sizeof (struct sockaddr_in6)) {
392: rprintf(FLOG, "%s: too short sockaddr_in6; length=%d\n",
393: fn, (int)ai->ai_addrlen);
394: return 1;
395: }
396:
397: if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr, sizeof sin1->sin6_addr))
398: return 1;
399:
400: #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
401: if (sin1->sin6_scope_id != sin2->sin6_scope_id)
402: return 1;
403: #endif
404: return 0;
405: }
406: #endif /* INET6 */
407:
408: /* don't know */
409: return 1;
410: }
411:
412:
413: /**
414: * Do a forward lookup on @p name_buf and make sure it corresponds to
415: * @p ss -- otherwise we may be being spoofed. If we suspect we are,
416: * then we don't abort the connection but just emit a warning, and
417: * change @p name_buf to be "UNKNOWN".
418: *
419: * We don't do anything with the service when checking the name,
420: * because it doesn't seem that it could be spoofed in any way, and
421: * getaddrinfo on random service names seems to cause problems on AIX.
422: **/
423: static int check_name(const char *ipaddr, const struct sockaddr_storage *ss, char *name_buf, size_t name_buf_size)
424: {
425: struct addrinfo hints, *res, *res0;
426: int error;
427: int ss_family = GET_SOCKADDR_FAMILY(ss);
428:
429: memset(&hints, 0, sizeof hints);
430: hints.ai_family = ss_family;
431: hints.ai_flags = AI_CANONNAME;
432: hints.ai_socktype = SOCK_STREAM;
433: error = getaddrinfo(name_buf, NULL, &hints, &res0);
434: if (error) {
435: rprintf(FLOG, "forward name lookup for %s failed: %s\n",
436: name_buf, gai_strerror(error));
437: strlcpy(name_buf, default_name, name_buf_size);
438: return error;
439: }
440:
441: /* Given all these results, we expect that one of them will be
442: * the same as ss. The comparison is a bit complicated. */
443: for (res = res0; res; res = res->ai_next) {
444: if (!compare_addrinfo_sockaddr(res, ss))
445: break; /* OK, identical */
446: }
447:
448: if (!res0) {
449: /* We hit the end of the list without finding an
450: * address that was the same as ss. */
451: rprintf(FLOG, "no known address for \"%s\": "
452: "spoofed address?\n", name_buf);
453: strlcpy(name_buf, default_name, name_buf_size);
454: } else if (res == NULL) {
455: /* We hit the end of the list without finding an
456: * address that was the same as ss. */
457: rprintf(FLOG, "%s is not a known address for \"%s\": "
458: "spoofed address?\n", ipaddr, name_buf);
459: strlcpy(name_buf, default_name, name_buf_size);
460: }
461:
462: freeaddrinfo(res0);
463: return 0;
464: }
465:
466: /* Returns 1 for a valid IPv4 or IPv6 addr, or 0 for a bad one. */
467: static int valid_ipaddr(const char *s)
468: {
469: int i;
470:
471: if (strchr(s, ':') != NULL) { /* Only IPv6 has a colon. */
472: int count, saw_double_colon = 0;
473: int ipv4_at_end = 0;
474:
475: if (*s == ':') { /* A colon at the start must be a :: */
476: if (*++s != ':')
477: return 0;
478: saw_double_colon = 1;
479: s++;
480: }
481:
482: for (count = 0; count < 8; count++) {
483: if (!*s)
484: return saw_double_colon;
485:
486: if (strchr(s, ':') == NULL && strchr(s, '.') != NULL) {
487: if ((!saw_double_colon && count != 6) || (saw_double_colon && count > 6))
488: return 0;
489: ipv4_at_end = 1;
490: break;
491: }
492:
493: if (!isHexDigit(s++)) /* Need 1-4 hex digits */
494: return 0;
495: if (isHexDigit(s) && isHexDigit(++s) && isHexDigit(++s) && isHexDigit(++s))
496: return 0;
497:
498: if (*s == ':') {
499: if (!*++s)
500: return 0;
501: if (*s == ':') {
502: if (saw_double_colon)
503: return 0;
504: saw_double_colon = 1;
505: s++;
506: }
507: }
508: }
509:
510: if (!ipv4_at_end)
511: return !*s;
512: }
513:
514: /* IPv4 */
515: for (i = 0; i < 4; i++) {
516: long n;
517: char *end;
518:
519: if (i && *s++ != '.')
520: return 0;
521: n = strtol(s, &end, 10);
522: if (n > 255 || n < 0 || end <= s || end > s+3)
523: return 0;
524: s = end;
525: }
526:
527: return !*s;
528: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>