diff options
author | Simon Wilkinson <simon@sxw.org.uk> | 2014-02-09 16:09:48 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2017-10-04 13:54:43 +0100 |
commit | 4e70490950e5c5134df48848affaf73685bf0284 (patch) | |
tree | 59de097e770693fb1f81268e85f7802df32cb58e /canohost.c | |
parent | 62f54f20bf351468e0124f63cc2902ee40d9b0e9 (diff) |
GSSAPI key exchange support
This patch has been rejected upstream: "None of the OpenSSH developers are
in favour of adding this, and this situation has not changed for several
years. This is not a slight on Simon's patch, which is of fine quality, but
just that a) we don't trust GSSAPI implementations that much and b) we don't
like adding new KEX since they are pre-auth attack surface. This one is
particularly scary, since it requires hooks out to typically root-owned
system resources."
However, quite a lot of people rely on this in Debian, and it's better to
have it merged into the main openssh package rather than having separate
-krb5 packages (as we used to have). It seems to have a generally good
security history.
Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242
Last-Updated: 2017-10-04
Patch-Name: gssapi.patch
Diffstat (limited to 'canohost.c')
-rw-r--r-- | canohost.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/canohost.c b/canohost.c index f71a08568..404731d24 100644 --- a/canohost.c +++ b/canohost.c | |||
@@ -35,6 +35,99 @@ | |||
35 | #include "canohost.h" | 35 | #include "canohost.h" |
36 | #include "misc.h" | 36 | #include "misc.h" |
37 | 37 | ||
38 | /* | ||
39 | * Returns the remote DNS hostname as a string. The returned string must not | ||
40 | * be freed. NB. this will usually trigger a DNS query the first time it is | ||
41 | * called. | ||
42 | * This function does additional checks on the hostname to mitigate some | ||
43 | * attacks on legacy rhosts-style authentication. | ||
44 | * XXX is RhostsRSAAuthentication vulnerable to these? | ||
45 | * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?) | ||
46 | */ | ||
47 | |||
48 | char * | ||
49 | remote_hostname(struct ssh *ssh) | ||
50 | { | ||
51 | struct sockaddr_storage from; | ||
52 | socklen_t fromlen; | ||
53 | struct addrinfo hints, *ai, *aitop; | ||
54 | char name[NI_MAXHOST], ntop2[NI_MAXHOST]; | ||
55 | const char *ntop = ssh_remote_ipaddr(ssh); | ||
56 | |||
57 | /* Get IP address of client. */ | ||
58 | fromlen = sizeof(from); | ||
59 | memset(&from, 0, sizeof(from)); | ||
60 | if (getpeername(ssh_packet_get_connection_in(ssh), | ||
61 | (struct sockaddr *)&from, &fromlen) < 0) { | ||
62 | debug("getpeername failed: %.100s", strerror(errno)); | ||
63 | return strdup(ntop); | ||
64 | } | ||
65 | |||
66 | ipv64_normalise_mapped(&from, &fromlen); | ||
67 | if (from.ss_family == AF_INET6) | ||
68 | fromlen = sizeof(struct sockaddr_in6); | ||
69 | |||
70 | debug3("Trying to reverse map address %.100s.", ntop); | ||
71 | /* Map the IP address to a host name. */ | ||
72 | if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), | ||
73 | NULL, 0, NI_NAMEREQD) != 0) { | ||
74 | /* Host name not found. Use ip address. */ | ||
75 | return strdup(ntop); | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * if reverse lookup result looks like a numeric hostname, | ||
80 | * someone is trying to trick us by PTR record like following: | ||
81 | * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5 | ||
82 | */ | ||
83 | memset(&hints, 0, sizeof(hints)); | ||
84 | hints.ai_socktype = SOCK_DGRAM; /*dummy*/ | ||
85 | hints.ai_flags = AI_NUMERICHOST; | ||
86 | if (getaddrinfo(name, NULL, &hints, &ai) == 0) { | ||
87 | logit("Nasty PTR record \"%s\" is set up for %s, ignoring", | ||
88 | name, ntop); | ||
89 | freeaddrinfo(ai); | ||
90 | return strdup(ntop); | ||
91 | } | ||
92 | |||
93 | /* Names are stored in lowercase. */ | ||
94 | lowercase(name); | ||
95 | |||
96 | /* | ||
97 | * Map it back to an IP address and check that the given | ||
98 | * address actually is an address of this host. This is | ||
99 | * necessary because anyone with access to a name server can | ||
100 | * define arbitrary names for an IP address. Mapping from | ||
101 | * name to IP address can be trusted better (but can still be | ||
102 | * fooled if the intruder has access to the name server of | ||
103 | * the domain). | ||
104 | */ | ||
105 | memset(&hints, 0, sizeof(hints)); | ||
106 | hints.ai_family = from.ss_family; | ||
107 | hints.ai_socktype = SOCK_STREAM; | ||
108 | if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { | ||
109 | logit("reverse mapping checking getaddrinfo for %.700s " | ||
110 | "[%s] failed.", name, ntop); | ||
111 | return strdup(ntop); | ||
112 | } | ||
113 | /* Look for the address from the list of addresses. */ | ||
114 | for (ai = aitop; ai; ai = ai->ai_next) { | ||
115 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, | ||
116 | sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && | ||
117 | (strcmp(ntop, ntop2) == 0)) | ||
118 | break; | ||
119 | } | ||
120 | freeaddrinfo(aitop); | ||
121 | /* If we reached the end of the list, the address was not there. */ | ||
122 | if (ai == NULL) { | ||
123 | /* Address not found for the host name. */ | ||
124 | logit("Address %.100s maps to %.600s, but this does not " | ||
125 | "map back to the address.", ntop, name); | ||
126 | return strdup(ntop); | ||
127 | } | ||
128 | return strdup(name); | ||
129 | } | ||
130 | |||
38 | void | 131 | void |
39 | ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len) | 132 | ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len) |
40 | { | 133 | { |