123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- http://bugs.gentoo.org/165444
- https://bugzilla.mindrot.org/show_bug.cgi?id=1008
- --- a/readconf.c
- +++ b/readconf.c
- @@ -148,6 +148,7 @@
- oClearAllForwardings, oNoHostAuthenticationForLocalhost,
- oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
- oAddressFamily, oGssAuthentication, oGssDelegateCreds,
- + oGssTrustDns,
- oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
- oSendEnv, oControlPath, oControlMaster, oControlPersist,
- oHashKnownHosts,
- @@ -194,9 +195,11 @@
- #if defined(GSSAPI)
- { "gssapiauthentication", oGssAuthentication },
- { "gssapidelegatecredentials", oGssDelegateCreds },
- + { "gssapitrustdns", oGssTrustDns },
- # else
- { "gssapiauthentication", oUnsupported },
- { "gssapidelegatecredentials", oUnsupported },
- + { "gssapitrustdns", oUnsupported },
- #endif
- #ifdef ENABLE_PKCS11
- { "smartcarddevice", oPKCS11Provider },
- @@ -930,6 +933,10 @@
- intptr = &options->gss_deleg_creds;
- goto parse_flag;
-
- + case oGssTrustDns:
- + intptr = &options->gss_trust_dns;
- + goto parse_flag;
- +
- case oBatchMode:
- intptr = &options->batch_mode;
- goto parse_flag;
- @@ -1649,6 +1656,7 @@
- options->challenge_response_authentication = -1;
- options->gss_authentication = -1;
- options->gss_deleg_creds = -1;
- + options->gss_trust_dns = -1;
- options->password_authentication = -1;
- options->kbd_interactive_authentication = -1;
- options->kbd_interactive_devices = NULL;
- @@ -1779,6 +1787,8 @@
- options->gss_authentication = 0;
- if (options->gss_deleg_creds == -1)
- options->gss_deleg_creds = 0;
- + if (options->gss_trust_dns == -1)
- + options->gss_trust_dns = 0;
- if (options->password_authentication == -1)
- options->password_authentication = 1;
- if (options->kbd_interactive_authentication == -1)
- --- a/readconf.h
- +++ b/readconf.h
- @@ -46,6 +46,7 @@
- /* Try S/Key or TIS, authentication. */
- int gss_authentication; /* Try GSS authentication */
- int gss_deleg_creds; /* Delegate GSS credentials */
- + int gss_trust_dns; /* Trust DNS for GSS canonicalization */
- int password_authentication; /* Try password
- * authentication. */
- int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
- --- a/ssh_config.5
- +++ b/ssh_config.5
- @@ -830,6 +830,16 @@
- Forward (delegate) credentials to the server.
- The default is
- .Cm no .
- +Note that this option applies to protocol version 2 connections using GSSAPI.
- +.It Cm GSSAPITrustDns
- +Set to
- +.Dq yes to indicate that the DNS is trusted to securely canonicalize
- +the name of the host being connected to. If
- +.Dq no, the hostname entered on the
- +command line will be passed untouched to the GSSAPI library.
- +The default is
- +.Dq no .
- +This option only applies to protocol version 2 connections using GSSAPI.
- .It Cm HashKnownHosts
- Indicates that
- .Xr ssh 1
- --- a/sshconnect2.c
- +++ b/sshconnect2.c
- @@ -656,6 +656,13 @@
- static u_int mech = 0;
- OM_uint32 min;
- int ok = 0;
- + const char *gss_host;
- +
- + if (options.gss_trust_dns) {
- + extern const char *auth_get_canonical_hostname(struct ssh *ssh, int use_dns);
- + gss_host = auth_get_canonical_hostname(active_state, 1);
- + } else
- + gss_host = authctxt->host;
-
- /* Try one GSSAPI method at a time, rather than sending them all at
- * once. */
- @@ -668,7 +674,7 @@
- /* My DER encoding requires length<128 */
- if (gss_supported->elements[mech].length < 128 &&
- ssh_gssapi_check_mechanism(&gssctxt,
- - &gss_supported->elements[mech], authctxt->host)) {
- + &gss_supported->elements[mech], gss_host)) {
- ok = 1; /* Mechanism works */
- } else {
- mech++;
- need to move these two funcs back to canohost so they're available to clients
- and the server. auth.c is only used in the server.
- --- a/auth.c
- +++ b/auth.c
- @@ -784,117 +784,3 @@ fakepw(void)
-
- return (&fake);
- }
- -
- -/*
- - * Returns the remote DNS hostname as a string. The returned string must not
- - * be freed. NB. this will usually trigger a DNS query the first time it is
- - * called.
- - * This function does additional checks on the hostname to mitigate some
- - * attacks on legacy rhosts-style authentication.
- - * XXX is RhostsRSAAuthentication vulnerable to these?
- - * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?)
- - */
- -
- -static char *
- -remote_hostname(struct ssh *ssh)
- -{
- - struct sockaddr_storage from;
- - socklen_t fromlen;
- - struct addrinfo hints, *ai, *aitop;
- - char name[NI_MAXHOST], ntop2[NI_MAXHOST];
- - const char *ntop = ssh_remote_ipaddr(ssh);
- -
- - /* Get IP address of client. */
- - fromlen = sizeof(from);
- - memset(&from, 0, sizeof(from));
- - if (getpeername(ssh_packet_get_connection_in(ssh),
- - (struct sockaddr *)&from, &fromlen) < 0) {
- - debug("getpeername failed: %.100s", strerror(errno));
- - return strdup(ntop);
- - }
- -
- - ipv64_normalise_mapped(&from, &fromlen);
- - if (from.ss_family == AF_INET6)
- - fromlen = sizeof(struct sockaddr_in6);
- -
- - debug3("Trying to reverse map address %.100s.", ntop);
- - /* Map the IP address to a host name. */
- - if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
- - NULL, 0, NI_NAMEREQD) != 0) {
- - /* Host name not found. Use ip address. */
- - return strdup(ntop);
- - }
- -
- - /*
- - * if reverse lookup result looks like a numeric hostname,
- - * someone is trying to trick us by PTR record like following:
- - * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5
- - */
- - memset(&hints, 0, sizeof(hints));
- - hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- - hints.ai_flags = AI_NUMERICHOST;
- - if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
- - logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
- - name, ntop);
- - freeaddrinfo(ai);
- - return strdup(ntop);
- - }
- -
- - /* Names are stored in lowercase. */
- - lowercase(name);
- -
- - /*
- - * Map it back to an IP address and check that the given
- - * address actually is an address of this host. This is
- - * necessary because anyone with access to a name server can
- - * define arbitrary names for an IP address. Mapping from
- - * name to IP address can be trusted better (but can still be
- - * fooled if the intruder has access to the name server of
- - * the domain).
- - */
- - memset(&hints, 0, sizeof(hints));
- - hints.ai_family = from.ss_family;
- - hints.ai_socktype = SOCK_STREAM;
- - if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
- - logit("reverse mapping checking getaddrinfo for %.700s "
- - "[%s] failed.", name, ntop);
- - return strdup(ntop);
- - }
- - /* Look for the address from the list of addresses. */
- - for (ai = aitop; ai; ai = ai->ai_next) {
- - if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
- - sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
- - (strcmp(ntop, ntop2) == 0))
- - break;
- - }
- - freeaddrinfo(aitop);
- - /* If we reached the end of the list, the address was not there. */
- - if (ai == NULL) {
- - /* Address not found for the host name. */
- - logit("Address %.100s maps to %.600s, but this does not "
- - "map back to the address.", ntop, name);
- - return strdup(ntop);
- - }
- - return strdup(name);
- -}
- -
- -/*
- - * Return the canonical name of the host in the other side of the current
- - * connection. The host name is cached, so it is efficient to call this
- - * several times.
- - */
- -
- -const char *
- -auth_get_canonical_hostname(struct ssh *ssh, int use_dns)
- -{
- - static char *dnsname;
- -
- - if (!use_dns)
- - return ssh_remote_ipaddr(ssh);
- - else if (dnsname != NULL)
- - return dnsname;
- - else {
- - dnsname = remote_hostname(ssh);
- - return dnsname;
- - }
- -}
- --- a/canohost.c
- +++ b/canohost.c
- @@ -202,3 +202,117 @@ get_local_port(int sock)
- {
- return get_sock_port(sock, 1);
- }
- +
- +/*
- + * Returns the remote DNS hostname as a string. The returned string must not
- + * be freed. NB. this will usually trigger a DNS query the first time it is
- + * called.
- + * This function does additional checks on the hostname to mitigate some
- + * attacks on legacy rhosts-style authentication.
- + * XXX is RhostsRSAAuthentication vulnerable to these?
- + * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?)
- + */
- +
- +static char *
- +remote_hostname(struct ssh *ssh)
- +{
- + struct sockaddr_storage from;
- + socklen_t fromlen;
- + struct addrinfo hints, *ai, *aitop;
- + char name[NI_MAXHOST], ntop2[NI_MAXHOST];
- + const char *ntop = ssh_remote_ipaddr(ssh);
- +
- + /* Get IP address of client. */
- + fromlen = sizeof(from);
- + memset(&from, 0, sizeof(from));
- + if (getpeername(ssh_packet_get_connection_in(ssh),
- + (struct sockaddr *)&from, &fromlen) < 0) {
- + debug("getpeername failed: %.100s", strerror(errno));
- + return strdup(ntop);
- + }
- +
- + ipv64_normalise_mapped(&from, &fromlen);
- + if (from.ss_family == AF_INET6)
- + fromlen = sizeof(struct sockaddr_in6);
- +
- + debug3("Trying to reverse map address %.100s.", ntop);
- + /* Map the IP address to a host name. */
- + if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
- + NULL, 0, NI_NAMEREQD) != 0) {
- + /* Host name not found. Use ip address. */
- + return strdup(ntop);
- + }
- +
- + /*
- + * if reverse lookup result looks like a numeric hostname,
- + * someone is trying to trick us by PTR record like following:
- + * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5
- + */
- + memset(&hints, 0, sizeof(hints));
- + hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- + hints.ai_flags = AI_NUMERICHOST;
- + if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
- + logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
- + name, ntop);
- + freeaddrinfo(ai);
- + return strdup(ntop);
- + }
- +
- + /* Names are stored in lowercase. */
- + lowercase(name);
- +
- + /*
- + * Map it back to an IP address and check that the given
- + * address actually is an address of this host. This is
- + * necessary because anyone with access to a name server can
- + * define arbitrary names for an IP address. Mapping from
- + * name to IP address can be trusted better (but can still be
- + * fooled if the intruder has access to the name server of
- + * the domain).
- + */
- + memset(&hints, 0, sizeof(hints));
- + hints.ai_family = from.ss_family;
- + hints.ai_socktype = SOCK_STREAM;
- + if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
- + logit("reverse mapping checking getaddrinfo for %.700s "
- + "[%s] failed.", name, ntop);
- + return strdup(ntop);
- + }
- + /* Look for the address from the list of addresses. */
- + for (ai = aitop; ai; ai = ai->ai_next) {
- + if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
- + sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
- + (strcmp(ntop, ntop2) == 0))
- + break;
- + }
- + freeaddrinfo(aitop);
- + /* If we reached the end of the list, the address was not there. */
- + if (ai == NULL) {
- + /* Address not found for the host name. */
- + logit("Address %.100s maps to %.600s, but this does not "
- + "map back to the address.", ntop, name);
- + return strdup(ntop);
- + }
- + return strdup(name);
- +}
- +
- +/*
- + * Return the canonical name of the host in the other side of the current
- + * connection. The host name is cached, so it is efficient to call this
- + * several times.
- + */
- +
- +const char *
- +auth_get_canonical_hostname(struct ssh *ssh, int use_dns)
- +{
- + static char *dnsname;
- +
- + if (!use_dns)
- + return ssh_remote_ipaddr(ssh);
- + else if (dnsname != NULL)
- + return dnsname;
- + else {
- + dnsname = remote_hostname(ssh);
- + return dnsname;
- + }
- +}
|